feat(eidos): button audit — focus canon, press archetype, intrinsic box, plain pure-emphasis, spinner via Spinner
- focus ring: adopt canonical `--focus-ring-*` (outline, HCM-safe, primary-tint) — drops the per-color fork - press archetype: new `STATIC_PRESS` primitive (`--press-scale: 0.985` / `--press-duration: 80ms`) emitted from foundation. Button switches from hardcoded `translateY(1px)` to canonical `scale(var(--press-scale))`. Card recipe repointed to the shared token — single press signature across the system - intrinsic box: `inline-size`/`block-size: fit-content` defends the Button against flex/grid stretch (was filling 400×160 in a grid; now 94×36). `data-block` still opts into width-stretch, `data-icon-only` still square - variant=emphasis only: `plain` no longer mutates layout (`min-block-size: auto` + `padding-inline: 0` removed) — same control box as the other 5 variants. Inline link-like actions belong to <Link>, not here - spinner composition: Button drops its bespoke SVG ring + `@keyframes button-spinner-spin` + `--button-spinner-duration: 720ms` and composes the canonical <Spinner variant="ring"> via two new modes: `presentation` (no role=status/aria-live, marks aria-hidden — Button owns the a11y) + `color="inherit"` (currentColor + 25% track). One spinner across the system, unified duration (0.9s) and reduced-motion behaviour Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>active-uix
parent
4878ccfbef
commit
5a132ead22
@ -1,33 +1,22 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
/**
|
/**
|
||||||
* Eidos `<Button.Spinner>` — visual wrapper over the soma spinner part.
|
* Eidos `<Button.Spinner>` — visual wrapper over the soma spinner slot.
|
||||||
*
|
*
|
||||||
* Renders an inline SVG ring with a CSS rotate animation. The recipe
|
* Composes the canonical `<Spinner>` (variant `ring`) in presentational
|
||||||
* (`button.css`) controls the colour via `currentColor` and animates
|
* mode (no `role=status` — the Button owns the loading a11y via `aria-busy`)
|
||||||
* via `@keyframes button-spinner-spin`.
|
* with `color="inherit"` so the ring follows the button's text colour.
|
||||||
*/
|
*/
|
||||||
import * as Button from '$soma/components/button';
|
import * as Button from '$soma/components/button';
|
||||||
|
import { Spinner } from '../spinner';
|
||||||
import type { ButtonSpinnerWrapperProps } from './types';
|
import type { ButtonSpinnerWrapperProps } from './types';
|
||||||
|
|
||||||
let { children, ...rest }: ButtonSpinnerWrapperProps = $props();
|
let { children, size = 'md', ...rest }: ButtonSpinnerWrapperProps = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Button.Spinner {...rest}>
|
<Button.Spinner {...rest}>
|
||||||
{#if children}
|
{#if children}
|
||||||
{@render children?.()}
|
{@render children?.()}
|
||||||
{:else}
|
{:else}
|
||||||
<!-- Default ring spinner. Stroked SVG with currentColor so it
|
<Spinner variant="ring" presentation color="inherit" {size} />
|
||||||
inherits the button's text colour. The recipe animates it. -->
|
|
||||||
<svg
|
|
||||||
class="eidos-button-spinner-ring"
|
|
||||||
viewBox="0 0 16 16"
|
|
||||||
fill="none"
|
|
||||||
stroke="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
aria-hidden="true"
|
|
||||||
>
|
|
||||||
<circle cx="8" cy="8" r="6" opacity="0.25" />
|
|
||||||
<path d="M14 8a6 6 0 0 0-6-6" stroke-linecap="round" />
|
|
||||||
</svg>
|
|
||||||
{/if}
|
{/if}
|
||||||
</Button.Spinner>
|
</Button.Spinner>
|
||||||
|
|||||||
Loading…
Reference in new issue