DhButton
Role-colour button (primary / secondary / tertiary / error / ghost) with a boolean outlined surface modifier, the M3 Expressive five-size scale, size-scaled corner radii, a subtle press scale, icon slots, and loading.
Variants
`variant` picks the role colour. Surface defaults to filled — except `secondary`, which outlines by default (the conditional default for the most common Cancel/Skip button).
<DhButton>Secondary</DhButton> <!-- bare default -->
<DhButton variant="primary">Primary</DhButton>
<DhButton variant="tertiary">Tertiary</DhButton>
<DhButton variant="error">Error</DhButton>
<DhButton variant="ghost">Ghost</DhButton>Surface modifier
`outlined` is a boolean modifier; default is filled. It defaults to `true` for `secondary` and `false` for everything else; pass it explicitly to override.
<DhButton variant="primary">Filled (default)</DhButton>
<DhButton variant="primary" outlined>Outlined</DhButton>
<!-- Secondary's outlined default is true; pass outlined={false} to fill it. -->
<DhButton>Secondary outlined</DhButton>
<DhButton outlined={false}>Secondary filled</DhButton>Sizes
The M3 Expressive five-size scale: `xs` (2rem), `sm` (2.5rem, default), `md` (3.5rem), `lg` (6rem), `xl` (8.5rem). Square corner radius scales with the size.
<DhButton variant="primary" size="xs">XSmall</DhButton>
<DhButton variant="primary" size="sm">Small (default)</DhButton>
<DhButton variant="primary" size="md">Medium</DhButton>
<DhButton variant="primary" size="lg">Large</DhButton>
<DhButton variant="primary" size="xl">XLarge</DhButton>Shape
`square` (default) scales its corner radius with the size (`0.75rem` on xs/sm up to `1.75rem` on lg/xl). `round` sets the radius to half the height for a full pill.
<DhButton variant="primary">Square (default)</DhButton>
<DhButton variant="primary" shape="round">Round (pill)</DhButton>With icons
<DhButton variant="primary" startIcon="plus" text="Create" />
<DhButton endIcon="arrow-right" text="Next" />
<DhButton variant="ghost" startIcon="copy" endIcon="chevron-down" text="Copy" />
<DhButton variant="error" startIcon="trash-2" text="Delete" />States
Loading replaces the leading icon with a spinner; the label dims to `0.6` opacity, `aria-busy` is set, and clicks are blocked.
<DhButton variant="primary" text="Default" />
<DhButton variant="primary" text="Disabled" disabled />
<DhButton variant="primary" text="Loading" loading={isLoading} onclick={simulateLoad} />As submit in a form
`type='submit'` fires the surrounding form; `type='reset'` clears it. Type defaults to `'button'`.
<form onsubmit={(e) => e.preventDefault()}>
<DhButton type="submit" variant="primary" text="Submit" />
<DhButton type="reset" text="Reset" />
</form>