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">
|
||||
/**
|
||||
* 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
|
||||
* (`button.css`) controls the colour via `currentColor` and animates
|
||||
* via `@keyframes button-spinner-spin`.
|
||||
* Composes the canonical `<Spinner>` (variant `ring`) in presentational
|
||||
* mode (no `role=status` — the Button owns the loading a11y via `aria-busy`)
|
||||
* with `color="inherit"` so the ring follows the button's text colour.
|
||||
*/
|
||||
import * as Button from '$soma/components/button';
|
||||
import { Spinner } from '../spinner';
|
||||
import type { ButtonSpinnerWrapperProps } from './types';
|
||||
|
||||
let { children, ...rest }: ButtonSpinnerWrapperProps = $props();
|
||||
let { children, size = 'md', ...rest }: ButtonSpinnerWrapperProps = $props();
|
||||
</script>
|
||||
|
||||
<Button.Spinner {...rest}>
|
||||
{#if children}
|
||||
{@render children?.()}
|
||||
{:else}
|
||||
<!-- Default ring spinner. Stroked SVG with currentColor so it
|
||||
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>
|
||||
<Spinner variant="ring" presentation color="inherit" {size} />
|
||||
{/if}
|
||||
</Button.Spinner>
|
||||
|
||||
Loading…
Reference in new issue