Button
Every call to action: a link when it has href, a button otherwise.
import { Button } from '@zitdevs/ui';Examples
Section titled “Examples”On a light field
Section titled “On a light field”<Button label="Book a consultation" icon="arrow-right" /><Button label="See services" variant="secondary" /><Button label="Download" variant="ghost" icon="download" iconPosition="before" /><Button label="Cancel" variant="quiet" /><Button label="Read the guide" variant="link" href="/guide" icon="arrow-right" />On a band
Section titled “On a band”inverse, inverseOutline and linkInverse are for the primary and the inverse band.
Minimum heights of 40, 48 and 56px. On the link variants, size sets the text size only.
States
Section titled “States”<Button label="Sending" type="submit" loading /><Button label="Unavailable" href="/booking" disabled /> {/* renders <button disabled> */}A label that does not fit
Section titled “A label that does not fit”A label that fits stays on one line, as drawn. One that does not wraps inside the button rather than running past its column, whatever text spacing the reader sets (WCAG 1.4.12).
Through a router’s link
Section titled “Through a router’s link”asChild renders the button’s one child instead of its own <a>: the child brings the element and
its routing props, the button its look, content and state. See
Router links.
import Link from 'next/link';
<Button asChild label="See services" icon="arrow-right"> <Link href="/services" /></Button>;| Prop | Type | Default | Notes |
|---|---|---|---|
label |
string |
required | Visible text and accessible name. |
variant |
ButtonVariant |
'primary' |
primary secondary ghost quiet on light fields; inverse inverseOutline on a band; link linkInverse are text links. |
size |
'sm' | 'md' | 'lg' |
'md' |
Minimum height 40 / 48 / 56px. On the link variants it sets the text size only. |
icon |
IconName |
— | Decorative; never part of the name. See Icon. |
iconPosition |
'before' | 'after' |
'after' |
before gives way to the spinner while loading. |
href |
string |
— | Renders an <a>. Ignored while disabled. |
target |
<a> target |
— | Links only. _blank adds rel="noopener noreferrer". |
type |
'button' | 'submit' | 'reset' |
'button' |
Buttons only. |
disabled |
boolean |
false |
Always renders <button disabled>, even with href. |
loading |
boolean |
false |
Spinner and aria-busy="true". Does not disable the control. |
block |
boolean |
false |
Fills its container. No effect on the link variants. |
asChild |
boolean |
false |
Renders its one child element (a router’s link) with the button’s classes and content. Ignored while disabled. |
children |
ReactElement |
— | With asChild, the element to render as. Its own children are replaced by the label and icon. |
ref |
Ref<HTMLAnchorElement | HTMLButtonElement> |
— | The element that renders. |
className |
string |
— | Merged last with cn(), so it can place the button or override a class. |
| anything else | <button> attributes |
— | name, value, form, formAction, aria-*, data-*, handlers: passed to the rendered element. |
Exported types: ButtonProps, ButtonVariant, ButtonSize.
Accessibility
Section titled “Accessibility”- A control that navigates is a link; one that acts is a button. A disabled control is always a
<button disabled>: an anchor cannot be disabled, and a dead link that looks live is worse. - A button is
type="button"unless told otherwise, so it never submits a form by accident. - While
loading, the label stays the accessible name andaria-busysays why nothing happens yet. The control stays enabled: the form handler ignores a second submit. - Icons and the spinner are hidden from assistive technology, and the label is always shown. For a
control that shows only an icon, use IconButton, whose
labelis its accessible name. - The focus ring is drawn by the button itself: 2px of
--ui-focus-offsetthen 2px of--ui-focus, which reaches 3:1 on light fields and on both bands. Forced-colours modes paint its outline instead. - Every size is at least 40px tall, above the 24px target minimum.
- The spinner stops for readers who ask for reduced motion.
Without JavaScript
Section titled “Without JavaScript”A <Button href> is a link and a <Button type="submit"> submits its form: both work in plain
HTML. The component holds no state and renders as a Server Component.
Theming
Section titled “Theming”primary, primary-hover, primary-active, primary-disabled, primary-soft,
primary-soft-active, primary-line, primary-inverse, on-primary, on-inverse, ink,
subtle, border-default, surface-hover, surface-active, and the focus ring.