feat(eidos): Lote A — float-panel-close composes IconButton

float-panel-close now composes the canonical <IconButton> via soma's child
snippet (variant/color defer to Button defaults; aria-label via the common close
label). Extracted [data-float-panel-close] from the shared chrome selector so
Action + StageTrigger keep their square-button styling while Close inherits
button.css. No recipe change (the shared --float-panel-button-size etc. stay for
the siblings). Verified in browser (solid-primary icon close, "Cerrar").

Completes the close family (dialog/drawer/popover/banner/toast/float-panel).
Excludes words/palabras/chronos.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
active-uix
dev 4 months ago
parent 7092450734
commit a32608dadd

@ -1,10 +1,40 @@
<script lang="ts"> <script lang="ts">
/**
* Eidos `FloatPanel.Close` — composes the canonical `<IconButton>` via soma's
* `child` snippet (no bespoke close chrome — it inherits Button's chrome, focus
* ring and disabled). `variant` / `color` defer to Button's canonical defaults;
* the accessible name routes through langs ("Cerrar"). A `child` snippet
* bypasses IconButton.
*/
import { ActiveEidos } from '$uix/eidos';
import * as FloatPanel from '$soma/components/float-panel'; import * as FloatPanel from '$soma/components/float-panel';
import { IconButton } from '$uix/eidos/components/icon-button';
import { SvgX } from '$uix/eidos/components/svg';
import type { FloatPanelCloseProps } from './types'; import type { FloatPanelCloseProps } from './types';
let { children, ...rest }: FloatPanelCloseProps = $props(); let {
variant,
size,
color,
'aria-label': ariaLabel,
child: outerChild,
children,
...rest
}: FloatPanelCloseProps = $props();
const eidos = ActiveEidos.require();
const resolvedSize = $derived(size ?? 'sm');
const closeLabel = $derived(ariaLabel ?? eidos.langs.ts('#?common.buttons.close|Close'));
</script> </script>
<FloatPanel.Close {...rest}> <FloatPanel.Close {...rest}>
{@render children?.()} {#snippet child({ props })}
{#if outerChild}
{@render outerChild({ props })}
{:else}
<IconButton {...props} {variant} size={resolvedSize} {color} aria-label={closeLabel}>
{#if children}{@render children()}{:else}<SvgX />{/if}
</IconButton>
{/if}
{/snippet}
</FloatPanel.Close> </FloatPanel.Close>

@ -169,10 +169,10 @@
flex: 0 0 auto; flex: 0 0 auto;
} }
/* Close + Action + StageTrigger share ONE square icon-button chrome, so a custom /* Action + StageTrigger share ONE square icon-button chrome, so a custom action
action (a delete icon, say) and the stage buttons sit flush next to Close with (a delete icon, say) and the stage buttons sit flush next to Close with
identical sizing/hover/focus. */ identical sizing/hover/focus. (Close itself composes the canonical
[data-float-panel-close], <IconButton>, so its chrome comes from button.css.) */
[data-float-panel-action], [data-float-panel-action],
[data-float-panel-stage-trigger] { [data-float-panel-stage-trigger] {
display: inline-flex; display: inline-flex;
@ -189,13 +189,11 @@
line-height: 1; line-height: 1;
cursor: pointer; cursor: pointer;
} }
[data-float-panel-close]:hover,
[data-float-panel-action]:hover, [data-float-panel-action]:hover,
[data-float-panel-stage-trigger]:hover { [data-float-panel-stage-trigger]:hover {
background: var(--color-surface-muted); background: var(--color-surface-muted);
color: var(--color-content-primary); color: var(--color-content-primary);
} }
[data-float-panel-close]:focus-visible,
[data-float-panel-action]:focus-visible, [data-float-panel-action]:focus-visible,
[data-float-panel-stage-trigger]:focus-visible { [data-float-panel-stage-trigger]:focus-visible {
outline: none; outline: none;

@ -12,8 +12,9 @@ import type {
ResizeHandleProps, ResizeHandleProps,
ResizeGripProps ResizeGripProps
} from '$soma/components/float-panel'; } from '$soma/components/float-panel';
import type { ColorRole, ControlVariant } from '$uix/eidos/lib/types'; import type { ColorRole, ControlVariant, ResponsiveProp } from '$uix/eidos/lib/types';
import type { MotionPresetName } from '$uix/eidos/lib/motion/registry'; import type { MotionPresetName } from '$uix/eidos/lib/motion/registry';
import type { ButtonVariant, ButtonSize, ButtonProps } from '$uix/eidos/components/button';
/** Surface treatment of the panel — canonical control variants (no invented values). */ /** Surface treatment of the panel — canonical control variants (no invented values). */
export type FloatPanelVariant = ControlVariant; export type FloatPanelVariant = ControlVariant;
@ -49,7 +50,14 @@ export type FloatPanelHeaderProps = HeaderProps & {
closable?: boolean; closable?: boolean;
}; };
export type FloatPanelTitleProps = TitleProps; export type FloatPanelTitleProps = TitleProps;
export type FloatPanelCloseProps = CloseProps; export type FloatPanelCloseProps = CloseProps & {
/** Button visual variant — defers to Button's canonical default. */
variant?: ButtonVariant;
/** Button size of the close control. @default 'sm' */
size?: ResponsiveProp<ButtonSize>;
/** Hierarchical color — defers to Button's canonical default. */
color?: ButtonProps['color'];
};
/** Header button group (right-aligned cluster holding Close / Action / custom buttons). */ /** Header button group (right-aligned cluster holding Close / Action / custom buttons). */
export type FloatPanelControlsProps = ControlsProps; export type FloatPanelControlsProps = ControlsProps;
/** /**

Loading…
Cancel
Save

Powered by TurnKey Linux.