Every eidos variant across all 8 color roles.
Hierarchy (primary / secondary / neutral) rides the
color prop; the evaluative palette (affirm / fulfill
/ risk / threat / loss) rides intent,
which wins on data-color.
{#each variants as v}
{v}
{#each gallery as c}
{/each}
{/each}
{/if}
{#if tab === 'api'}
API reference
Single-part component: the root IS the <button>.
The Spinner is rendered automatically when loading=true
— consumers can override the glyph via the spinner
snippet prop on the root, or compose Button.Spinner
explicitly inside a child snippet for total control.
Slot composition (Radix asChild pattern). Spread props into your own element.
…native button attrs
PrimitiveButtonAttributes
—
onclick, form, formaction, autofocus, etc.
Button.Spinner
Prop
Type
Default
Description
id
string
auto
—
children
Snippet
default ring SVG
Override the spinner glyph.
…native span attrs
PrimitiveSpanAttributes
—
—
Reference parity
Feature
Radix
bits-ui
shadcn
Chakra v3
Mantine
MUI
Eidos (this)
Component exists
—
✓ (thin)
✓
✓
✓
✓
✓
variant count
—
—
6
7
8
3
6
color palette
—
—
implicit
palette token
color
color
8 (3 hierarchy + 5 intents)
sizes
—
—
4
6
5
3
5
loading state
—
—
—
✓
✓
✓
✓
loadingText
—
—
—
✓
—
—
✓
spinnerPlacement
—
—
—
✓
—
—
✓
iconOnly square
—
—
'icon' size
—
—
—
✓
block / fullWidth
—
—
—
—
✓
✓
✓
rounded scale
—
—
—
—
radius
—
✓
asChild / Slot
✓
✓
✓
✓
—
—
✓
commit-action semantic event
—
—
—
—
—
—
✓
per-intent perceptual signature
—
—
—
—
—
—
✓
{/if}
{#if tab === 'morfo'}
morfo
· declarative contract
2 parts (Provider + optional Spinner), 1 event
(commit-action with intent fromProp). Sequence
pre — perceptual signal lands at click, before the
consumer's onclick. Source:
src/uix/morfo/components/button.ts.
commit-action fires with sequence pre so
the perceptual signal lands at the moment of the click; the
consumer's onclick may then run async work without blocking.
Intent is bound to the intent prop; supported
intents are the full commit-friendly set (neutral / affirm /
fulfill / risk / threat / loss).
name
family
verb
sequence
intent
target
prewrite
commit
{#each events as action (action.name)}
{@const sem = action.semantic}
{@const intentDecl = 'intent' in sem ? sem.intent : undefined}
{@const intentStr = typeof intentDecl === 'string' ? intentDecl : intentDecl ? `fromProp:${(intentDecl as { fromProp?: string }).fromProp ?? '?'} (default ${(intentDecl as { default?: string }).default ?? '?'})` : '—'}
One event: commit-action from the
commit family. Each press fires it with sequence
pre — the perceptual signal lands at the click moment,
before any async work in the consumer's onclick. Intent is per-
button via fromProp:intent and modulates the
non-visual signature (sound timbre + haptic curve) via
SEMA_MAP.intents.
Name
Family
Verb
Sequence
Intent
Play
{#each events as action (action.name)}
{@const sem = action.semantic}
{@const intentDecl = 'intent' in sem ? sem.intent : undefined}
{@const effectiveIntent =
typeof intentDecl === 'string'
? intentDecl
: intentDecl
? intent
: undefined}
{action.name}
{sem.family}
{sem.verb ?? '—'}
{sem.sequence ?? 'pre'}
{effectiveIntent ?? '—'} (live)
{/each}
{/if}
{#if tab === 'recipe'}
Eidos recipe
Source: src/uix/eidos/components/button/button.css.
Recipe tokens declared in src/uix/eidos/lib/recipes/base.ts
under the button key. Six variant slices map the
resolved palette to bg / fg / border / hover-*
private vars; the size cascade overrides height / padding /
gap / font-size / icon-size; the per-color cascade re-binds
the palette block (8 system tokens).
Selector
Source
Concern
[data-button]
morfo
Base layout: inline-flex, gap, height, padding, border, radius, transitions.
Follows the APG button pattern.
Renders a native <button> — gets the full
native keyboard + focus model. iconOnly consumers
MUST set aria-label. While loading, the button
exposes aria-busy='true' so screen readers
announce the deferred state.
Keyboard
Key
Action
Enter
Activate (native).
Space
Activate (native).
Tab / Shift+Tab
Move focus to next / previous focusable.
ARIA contract
Part
Attribute
Value
provider
type
{`{type}`} (default "button" — explicit to avoid implicit submit in forms)
provider
data-state
"idle" | "loading"
provider
data-color
resolved color (intent wins when evaluative)
provider
data-loading
"true" when loading
provider
data-disabled
"true" when disabled
provider
aria-busy
"true" when loading
provider
aria-disabled
"true" when disabled
provider
aria-label
{`{aria-label}`} when set (required for iconOnly)
spinner
aria-hidden
"true" (decorative — aria-busy on provider conveys state to AT)