ui.button · parts: Button · elements: <a>, <button>
Button triggers an action. With href it renders an anchor (navigation that
looks like an action). Event handlers (onClick) flow through attrs/rest.
- Use
hreffor navigation that looks like an action; plain links use Link. disabledon the anchor form becomesaria-disabled="true"+tabindex="-1"(anchors have no native disabled).- Event handlers (
onClick,@click,on:click) go through rest/attrs.
Button renders a button element, or an anchor when Href is set. Type/Form apply only in button mode; Disabled on anchors uses aria-disabled.
| Canonical (templ, Jinja2) | React / Solid | HTML (Svelte, Vue, WC) | Type | Default | Kind | Description |
|---|---|---|---|---|---|---|
Type |
type |
type |
"button" | "submit" | "reset" |
— | prop | button type (default button) |
Form |
form |
form |
string |
— | passthrough attr | associated form id (button mode) |
Href |
href |
href |
string |
— | prop | renders an anchor when set |
Disabled |
disabled |
disabled |
boolean |
— | prop | blocks interaction |
AriaLabel |
aria-label |
aria-label |
string |
— | passthrough attr | |
AriaPressed |
aria-pressed |
aria-pressed |
string |
— | passthrough attr | |
AriaExpanded |
aria-expanded |
aria-expanded |
string |
— | passthrough attr | |
AriaControls |
aria-controls |
aria-controls |
string |
— | passthrough attr |
Also accepts: class (className in React), extra attributes (rest props in UI frameworks, Attrs in templ/Jinja2, attrs in Twig/Latte; caller wins), children.
No variants: the primitive ships no visual classes; style it with token classes via class.
Accepts children (default slot / children / { children... } / trusted HTML string in Twig, Latte, Jinja2 — see runtimes). Void tags selected via tag render no children.
- Computed/forwarded:
aria-label,aria-pressed,aria-expanded,aria-controls,aria-disabled(omitted when empty). - Typed ARIA props:
aria-label,aria-pressed,aria-expanded,aria-controls— static values only.
Compose the part's classes without rendering it (custom root element, no asChild outside React):
| Runtime | Helper |
|---|---|
| React / Solid / Vue / Svelte / WC | buttonClasses({ ... }) from button/button.shared.ts |
| templ | button.ButtonClasses(button.ButtonProps{...}) |
| Twig | ui8kit_classes('buttonClasses', { class: '…' }) |
| Latte | \UI8Kit\Latte\Classes::buttonClasses(['class' => '…']) |
| Jinja2 | button_classes(p) |
React additionally supports asChild (merges props onto the single child via Slot).
Canonical renderer output (children = Content); all 9 runtimes are parity-tested to produce this DOM.
| State | Props | HTML |
|---|---|---|
| defaults | — | <button type="button">Content</button> |
| submit | {"Type":"submit","Class":"bg-primary text-primary-foreground"} |
<button type="submit" class="bg-primary text-primary-foreground">Content</button> |
| disabled | {"Disabled":true} |
<button type="button" disabled>Content</button> |
| form | {"Form":"f1","AriaLabel":"Save"} |
<button type="button" form="f1" aria-label="Save">Content</button> |
| pressed | {"AriaPressed":"true","AriaExpanded":"false","AriaControls":"m1"} |
<button type="button" aria-pressed="true" aria-expanded="false" aria-controls="m1">Content</button> |
| href | {"Href":"/docs","Class":"underline"} |
<a href="/docs" class="underline">Content</a> |
| hrefDisabled | {"Href":"/x","Disabled":true} |
<a href="/x" aria-disabled="true" tabindex="-1">Content</a> |
| Type=button | {"Type":"button"} |
<button type="button">Content</button> |
| Type=submit | {"Type":"submit"} |
<button type="submit">Content</button> |
| Type=reset | {"Type":"reset"} |
<button type="reset">Content</button> |
| Disabled | {"Disabled":true} |
<button type="button" disabled>Content</button> |
Fixture submit ({"Type":"submit","Class":"bg-primary text-primary-foreground"}) — every snippet renders:
<button type="submit" class="bg-primary text-primary-foreground">Content</button>React (runtime notes)
import { Button } from "./ui/button/button";
<Button type="submit" className="bg-primary text-primary-foreground">Content</Button>Vue 3 (runtime notes)
<script setup lang="ts">
import Button from "./ui/button/Button.vue";
</script>
<template>
<Button type="submit" class="bg-primary text-primary-foreground">Content</Button>
</template>Svelte 5 (runtime notes)
<script lang="ts">
import Button from "./ui/button/Button.svelte";
</script>
<Button type="submit" class="bg-primary text-primary-foreground">Content</Button>SolidJS (runtime notes)
import { Button } from "./ui/button/button.solid";
<Button type="submit" class="bg-primary text-primary-foreground">Content</Button>Web Components (runtime notes)
import { renderButton } from "./ui/button/button.wc";
document.body.append(renderButton({ type: "submit", class: "bg-primary text-primary-foreground" }, "Content"));Go templ (runtime notes)
import "github.com/ui8kit/codegen/generated/templ/ui/button"
@button.Button(button.ButtonProps{Type: "submit", Class: "bg-primary text-primary-foreground"}) {
Content
}Twig (runtime notes)
{% include 'button/Button.html.twig' with { type: 'submit', class: 'bg-primary text-primary-foreground', children: 'Content' } only %}Latte (runtime notes)
{include 'button/Button.latte', type: 'submit', class: 'bg-primary text-primary-foreground', children: 'Content'}Jinja2 (runtime notes)
{% with p = {'Type': 'submit', 'Class': 'bg-primary text-primary-foreground'}, children = 'Content' %}{% include 'ui/button/button.html.j2' %}{% endwith %}