DhButton
Role-colour button (primary / secondary / tertiary / error / ghost) with boolean outlined / elevated surface modifiers, sizes, 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 modifiers
`outlined` and `elevated` are boolean modifiers; `elevated` wins if both are set. Default is filled. `outlined` 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>
<DhButton variant="primary" elevated>Elevated</DhButton>
<!-- Secondary's outlined default is true; pass outlined={false} to fill it. -->
<DhButton>Secondary outlined</DhButton>
<DhButton outlined={false}>Secondary filled</DhButton>Sizes
`sm` is the default at `2.75rem` tall with `1rem` padding and `0.5rem` corners.
<DhButton variant="primary" size="sm">Small (default)</DhButton>
<DhButton variant="primary" size="md">Medium</DhButton>
<DhButton variant="primary" size="lg">Large</DhButton>Shape
`square` (default) gives Davidhorn's standard `0.5rem` corner radius. `round` resolves to `--radius-full` 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>Migrating from Ark
How Ark's button props map to the Justin API. Most are 1:1; the cases below are the ones worth noting.
variant="primary"→variant="primary"variant="secondary"→<DhButton>(default)variant="tertiary"→variant="ghost"(newtertiaryis filled orange — not a drop-in)variant="neutral"→outlined=falsevariant="danger"→variant="error"<a>-styled buttons →<DhLinkButton>
Not covered yet (in flight):
shape="circle"→DhIconButton(PRD-3240)selected={…}→DhToggleButton(PRD-3241)