DIM 1 composition (component-coherence audit), close family:
- popover-close + banner-close now compose the canonical <IconButton>/<Button>
(via soma child snippet for popover; direct for the eidos-only banner) instead
of bespoke chrome. They inherit Button's variant/size/color/focus-ring; the
aria-label routes through langs ("Cerrar" / "Descartar"). Consistent with the
already-migrated dialog/drawer closes (solid/primary default; consumer overrides
for subtle).
- Removed the redundant [data-popover-close] / [data-banner-close] chrome from CSS
and the now-orphaned --popover-close-* / --popover-transition-* recipe tokens;
regenerated base.css. banner keeps only `margin-inline-start: auto` for end
placement, scoped under [data-banner] so it out-ranks [data-button] (composing
IconButton flips CSS load order — the equal-specificity bare selector loses).
- Cleaned the 15 orphaned --drawer-close-* recipe tokens the earlier drawer-close
migration left behind, and fixed the component-visual-attrs manifest: drawer +
popover closes delegate icon-only to IconButton, so they stamp no wrapper attr.
eidos suite 9->8 failures (the 8 remaining are inherited: spin-field + palabras +
icon, outside this work). svelte-check clean for all touched files. Verified in
browser. Excludes words/palabras/chronos.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
active-uix
parent
ebc742e73b
commit
0a43225ec2
@ -1,50 +1,38 @@
|
||||
<script lang="ts">
|
||||
/**
|
||||
* Eidos `<Banner.Close>` — visually-styled dismiss button. Pure
|
||||
* eidos-only part: meets the four rules in
|
||||
* `eidos/components/README.md` (no behavior, no aria contract, no
|
||||
* event-target role, no keyboard). The consumer wires `onclick` to
|
||||
* their own visibility state — Banner does not own the dismissal.
|
||||
*
|
||||
* Defaults to a localized "Dismiss" `aria-label` (via langs) so consumers
|
||||
* don't have to remember, but the consumer can override.
|
||||
* Eidos `<Banner.Close>` — the banner dismiss control. Composes the canonical
|
||||
* `<IconButton>` (eidos-only part — Banner has no soma close; the consumer
|
||||
* wires `onclick` to their own visibility state). Inherits Button's chrome,
|
||||
* focus ring and disabled treatment; only the positioning
|
||||
* (`margin-inline-start: auto`) stays in `banner.css`. Default `variant='ghost'
|
||||
* color='neutral'` — a subtle dismiss. The glyph defaults to ✕.
|
||||
*/
|
||||
import { ActiveEidos } from '$uix/eidos';
|
||||
import { IconButton } from '$uix/eidos/components/icon-button';
|
||||
import { SvgX } from '$uix/eidos/components/svg';
|
||||
import type { BannerCloseProps } from './types';
|
||||
|
||||
let {
|
||||
'aria-label': ariaLabel,
|
||||
class: className,
|
||||
variant = 'ghost',
|
||||
size,
|
||||
color = 'neutral',
|
||||
children,
|
||||
...restProps
|
||||
}: BannerCloseProps = $props();
|
||||
|
||||
const eidos = ActiveEidos.require();
|
||||
// Accessible name routes through langs — explicit prop wins, else the
|
||||
// localized default. No hardcoded English.
|
||||
// Accessible name routes through langs — explicit prop wins, else localized.
|
||||
const resolvedLabel = $derived(ariaLabel ?? eidos.langs.ts('#?common.buttons.dismiss|Dismiss'));
|
||||
</script>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
<IconButton
|
||||
{...restProps}
|
||||
{variant}
|
||||
size={size ?? 'sm'}
|
||||
{color}
|
||||
aria-label={resolvedLabel}
|
||||
class={className}
|
||||
data-banner-close=""
|
||||
>
|
||||
{#if children}{@render children()}{:else}<svg
|
||||
viewBox="0 0 16 16"
|
||||
width="14"
|
||||
height="14"
|
||||
aria-hidden="true"
|
||||
focusable="false"
|
||||
>
|
||||
<path
|
||||
d="M3 3l10 10M13 3L3 13"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
/>
|
||||
</svg>{/if}
|
||||
</button>
|
||||
{#if children}{@render children()}{:else}<SvgX />{/if}
|
||||
</IconButton>
|
||||
|
||||
@ -1,31 +1,50 @@
|
||||
<script lang="ts">
|
||||
/**
|
||||
* Eidos `Popover.Close` — passes through to headless. Optional auto-X
|
||||
* icon when no children are provided (matches the air baseline +
|
||||
* Dialog/Drawer pattern). The recipe styles a square button with
|
||||
* focus ring.
|
||||
* Eidos `Popover.Close` — composes the canonical button primitives via soma's
|
||||
* `child` snippet (no bespoke close chrome — it inherits Button's variant /
|
||||
* focus-ring / disabled):
|
||||
*
|
||||
* - no text children → icon close: an `<IconButton>` with the ✕ glyph and a
|
||||
* localized "Close" `aria-label`.
|
||||
* - text children → text close: a `<Button>` with the label inline.
|
||||
*
|
||||
* A `child` snippet bypasses both primitives.
|
||||
*/
|
||||
import { ActiveEidos } from '$uix/eidos';
|
||||
import * as Popover from '$soma/components/popover';
|
||||
import { Button } from '$uix/eidos/components/button';
|
||||
import { IconButton } from '$uix/eidos/components/icon-button';
|
||||
import { SvgX } from '$uix/eidos/components/svg';
|
||||
import type { PopoverCloseProps } from './types';
|
||||
|
||||
let { children, ...rest }: PopoverCloseProps = $props();
|
||||
let {
|
||||
variant,
|
||||
size,
|
||||
color,
|
||||
'aria-label': ariaLabel,
|
||||
child: outerChild,
|
||||
children,
|
||||
...rest
|
||||
}: PopoverCloseProps = $props();
|
||||
|
||||
const eidos = ActiveEidos.require();
|
||||
const resolvedSize = $derived(size ?? 'md');
|
||||
// Accessible name routes through langs — explicit prop wins, else localized.
|
||||
const closeLabel = $derived(ariaLabel ?? eidos.langs.ts('#?common.buttons.close|Close'));
|
||||
</script>
|
||||
|
||||
<Popover.Close {...rest} data-icon-only={!children ? '' : undefined}>
|
||||
{#if children}
|
||||
<Popover.Close {...rest}>
|
||||
{#snippet child({ props })}
|
||||
{#if outerChild}
|
||||
{@render outerChild({ props })}
|
||||
{:else if children}
|
||||
<Button {...props} {variant} size={resolvedSize} {color} aria-label={ariaLabel ?? undefined}>
|
||||
{@render children()}
|
||||
</Button>
|
||||
{:else}
|
||||
<svg
|
||||
width="12"
|
||||
height="12"
|
||||
viewBox="0 0 14 14"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.6"
|
||||
stroke-linecap="round"
|
||||
aria-hidden="true"
|
||||
>
|
||||
<path d="M3 3l8 8M11 3l-8 8" />
|
||||
</svg>
|
||||
<IconButton {...props} {variant} size={resolvedSize} {color} aria-label={closeLabel}>
|
||||
<SvgX />
|
||||
</IconButton>
|
||||
{/if}
|
||||
{/snippet}
|
||||
</Popover.Close>
|
||||
|
||||
Loading…
Reference in new issue