ACTIONS & SURFACES

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

import { Button, IconButton } from 'damo-ui'

Usage

1<Button variant="primary">Save</Button>
2<Button variant="ghost">Cancel</Button>

Sizes

1<Button variant="primary" size="sm">Small</Button>
2<Button variant="primary" size="md">Medium</Button>
3<Button variant="primary" size="lg">Large</Button>

With inline icons

Place an icon inside the Button alongside text. Keep the visible label so the action stays announce-able.

1<Button variant="ghost">
2  <ArrowRightIcon size={14} /> Continue
3</Button>

Disabled

1<Button variant="primary" disabled>
2  Save
3</Button>

Full width

Stretch the button to the container — useful inside narrow forms or mobile sheets.

1<Button variant="primary" fullWidth>
2  Continue
3</Button>

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

1import Link from 'next/link'
2import { Button } from 'damo-ui'
3
4// Render the Link as a Button. All variant, size, and animation
5// classes — including the Memphis press effect on :active — are
6// merged onto the underlying <a>.
7<Button asChild variant="primary" size="lg">
8  <Link href="/docs">Browse docs</Link>
9</Button>

Button API

Button props
PropTypeDefaultDescription
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.
disabledbooleanfalseOn 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.
fullWidthbooleanfalseStretches the button to the full width of its container.
asChildbooleanfalseWhen 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>.
classNamestringTailwind classes are merged on top of the variant defaults.

Accessibility

  • Renders a native <button type="button">; pass type="submit" when used inside a form.
  • Always provide a non-empty label. For icon-only triggers use IconButton (documented below) with an aria-label.
  • disabled blocks both pointer and keyboard activation on a real <button>. With asChild, only the disabled CSS utilities apply — for a fully inactive link also remove href or set aria-disabled="true" on the child.

SAME FAMILY

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

1<IconButton aria-label="Settings" variant="ghost">
2  <CogIcon size={18} />
3</IconButton>

Variants

Same six variants as Button. The icon-only version of link is rarely useful; reach for ghost instead.

1<IconButton aria-label="Continue" variant="primary">
2  <ArrowRightIcon size={18} />
3</IconButton>
4<IconButton aria-label="Quick action" variant="outline">
5  <BoltIcon size={18} />
6</IconButton>
7<IconButton aria-label="Settings" variant="ghost">
8  <CogIcon size={18} />
9</IconButton>

IconButton API

IconButton props
PropTypeDefaultDescription
aria-label*stringIconButtons have no visible text, so every instance MUST carry a non-empty aria-label for screen readers. The TypeScript signature enforces this.
children*ReactNodeA 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.
disabledbooleanBlocks pointer and keyboard activation.

Accessibility

  • aria-label is required and must be non-empty. The TypeScript signature enforces this — passing aria-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.