Skip to content

Latest commit

 

History

History
167 lines (115 loc) · 6.5 KB

button.md

File metadata and controls

167 lines (115 loc) · 6.5 KB

Button

ui.button · parts: Button · elements: <a>, <button>

Purpose

Button triggers an action. With href it renders an anchor (navigation that looks like an action). Event handlers (onClick) flow through attrs/rest.

Notes

  • Use href for navigation that looks like an action; plain links use Link.
  • disabled on the anchor form becomes aria-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.

Props

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.

Variants

No variants: the primitive ships no visual classes; style it with token classes via class.

Children

Accepts children (default slot / children / { children... } / trusted HTML string in Twig, Latte, Jinja2 — see runtimes). Void tags selected via tag render no children.

ARIA

  • 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.

Classes escape hatch

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).

Rendered DOM per state

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>

Usage

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 %}

Rules: contract · Index: docs