Button
The custom element is <hui-button>.
Overview
A button in the nova treatment, with shadcn's variant and size API. It carries no form value of its own; type="submit" and type="reset" drive the surrounding form.
Example
Source
<hui-button>Default</hui-button><hui-button variant="secondary">Secondary</hui-button><hui-button variant="destructive">Destructive</hui-button><hui-button variant="outline">Outline</hui-button><hui-button variant="ghost">Ghost</hui-button><hui-button variant="link">Link</hui-button>The Go template that renders it:
{{ range .Variants }} <hui-button variant="{{ .Name }}">{{ .Label }}</hui-button>{{ end }}API
Attributes4
| Name | Type | Default | Description |
|---|---|---|---|
variant | "default" | "secondary" | "destructive" | "outline" | "ghost" | "link" | "default" | The visual treatment. An unknown value falls back to default. |
size | "sm" | "default" | "lg" | "icon" | "icon-sm" | "default" | The height and padding. icon is a 2rem square and icon-sm a 1.75rem one, for a card action or a row menu; both expect an aria-label. |
disabled | boolean | false | Disables the internal button, removes it from the tab order and swallows the click. |
type | "button" | "submit" | "reset" | "button" | Native button behaviour. submit and reset call requestSubmit() and reset() on the ancestor form. |
Properties4
| Name | Type | Default | Description |
|---|---|---|---|
variant | ButtonVariant | 'default' | Reflects to the variant attribute. |
size | ButtonSize | 'default' | Reflects to the size attribute. |
disabled | boolean | false | Reflects to the disabled attribute. |
type | ButtonType | 'button' | Reflects to the type attribute. |
Events1
| Name | Description |
|---|---|
click | The native click from the internal button. It bubbles and is composed, so an Alpine x-on:click on an ancestor sees it. Suppressed while disabled. |
Slots1
| Name | Description |
|---|---|
(default) | The label and any leading or trailing icon. Inline SVG inherits currentColor. |
CSS custom properties3
| Name | Default | Description |
|---|---|---|
--hui-primary | oklch(0.496 0.265 301.924) | Fill of the default variant. |
--hui-radius | 0.45rem | Base radius; the button uses --hui-radius-lg. |
--hui-focus-ring-width | 3px | Width of the keyboard focus ring. |
::part() hooks1
| Name | Description |
|---|---|
button | The internal native <button>. Use ::part(button) for a style no token covers. |
States
Sizes
The three sizes beside the icon size. An icon button is square and takes its name from aria-label, because it has no text to read.
Source
<hui-button size="sm">Small</hui-button><hui-button>Default</hui-button><hui-button size="lg">Large</hui-button><hui-button size="icon" aria-label="More options">+</hui-button>Disabled
disabled on two variants. The element forwards it to the button it renders, so the control leaves the tab order and submits nothing.
Source
<hui-button disabled>Disabled</hui-button><hui-button variant="outline" disabled>Disabled</hui-button>Server-side mechanics
The server owns the label (the default slot) and the variant, size, type and disabled attributes. It is form-associated only so that type="submit" and type="reset" can call requestSubmit() and reset() on the ancestor form; it carries no value and no name, so it contributes nothing to FormData. An hx-swap may replace the button at any time because it holds no interaction state, so the server only has to re-emit the attributes. There is no validation state for a button, so aria-invalid and hui-field do not apply to it.
Accessibility
- The accessible name comes from the slotted text or an
aria-label; aniconbutton with neither is a defect. - Focus is shown with the shared 3px translucent ring on
:focus-visibleonly, so a mouse click does not draw it. - When
disabled, the internal button carries the nativedisabledattribute, so it leaves the tab order as native buttons do.
Keyboard
| Keys | Action |
|---|---|
Tab | Moves focus to and from the button. |
Enter, Space | Activates the button, exactly as the native control does. |
Gotchas
None recorded.