Button
Bordered, shadowed action surface. Six variants, three sizes plus the dedicated icon size, full keyboard access via a native <button>. Pair with IconButton (documented below) for icon-only triggers — same chrome, locked to a 40×40 square.
Import
Usage
Sizes
With inline icons
Place an icon inside the Button alongside text. Keep the visible label so the action stays announce-able.
Disabled
Full width
Stretch the button to the container — useful inside narrow forms or mobile sheets.
Use as a link
Pass asChild to render a single child element with all Button styles applied (Radix Slot pattern). Useful for navigation CTAs that need both the Memphis press animation and routing — the variant classes, hover lift, and active-press collapse are all merged onto the underlying <a>.
Button API
| Prop | Type | Default | Description |
|---|---|---|---|
| variant | 'primary' | 'secondary' | 'ghost' | 'outline' | 'destructive' | 'link' | 'primary' | Visual style. Primary/secondary use the brand accents; outline and ghost are neutral; destructive surfaces destructive intent; link reduces to an inline anchor. |
| size | 'sm' | 'md' | 'lg' | 'icon' | 'md' | Adjusts vertical padding and font size. icon is a 40×40 square — used internally by IconButton. |
| disabled | boolean | false | On a real <button>, blocks pointer / keyboard activation. With asChild on a non-button child, only the disabled CSS utilities apply — set aria-disabled and remove href on the child for full inertness. |
| fullWidth | boolean | false | Stretches the button to the full width of its container. |
| asChild | boolean | false | When true, render the child element with all Button styles applied (Radix Slot pattern). The child must be a single React element such as a <Link> or <a>. |
| className | string | — | Tailwind classes are merged on top of the variant defaults. |
Accessibility
- Renders a native
<button type="button">; passtype="submit"when used inside a form. - Always provide a non-empty label. For icon-only triggers use
IconButton(documented below) with anaria-label. disabledblocks both pointer and keyboard activation on a real<button>. WithasChild, only the disabled CSS utilities apply — for a fully inactive link also removehrefor setaria-disabled="true"on the child.
IconButton
A square 40×40 button for icon-only actions. Composes Button with size="icon" and the same Memphis press effect; aria-label is required so the action is announced.
Basic usage
Variants
Same six variants as Button. The icon-only version of link is rarely useful; reach for ghost instead.
IconButton API
| Prop | Type | Default | Description |
|---|---|---|---|
| aria-label* | string | — | IconButtons have no visible text, so every instance MUST carry a non-empty aria-label for screen readers. The TypeScript signature enforces this. |
| children* | ReactNode | — | A single icon node — typically one of the icons exported from damo-ui. |
| variant | 'primary' | 'secondary' | 'ghost' | 'outline' | 'destructive' | 'link' | 'primary' | Same six variants as Button. The size is locked to the 40×40 icon preset. |
| disabled | boolean | — | Blocks pointer and keyboard activation. |
Accessibility
aria-labelis required and must be non-empty. The TypeScript signature enforces this — passingaria-label=""is a type error.- The icon child is rendered visually only; ensure the surrounding context doesn't rely on the icon being announced (it is not).
- The 40×40 square satisfies WCAG 2.5.8 (Level AA, WCAG 2.2), which requires a 24×24 CSS pixel minimum. To reach the 44×44 threshold of WCAG 2.5.5 (Level AAA), wrap the button with a 4px margin or add hit-slop on the parent.