Actions

Button

The pill button for every action. Six variants, four text sizes and four icon sizes, on Base UI's Button so it can render as a link.

packages/design-system/components/ui/button.tsx

Examples

Variants
Sizes: xs, sm, default, lg
Icon sizes: icon-xs, icon-sm, icon, icon-lg
With an icon, marked data-icon so the padding tightens
Loading and disabled
As a link: render a Link, and turn nativeButton off
On black

Anatomy

  1. 01Pill, rounded-4xl, transparent border
  2. 02Optional leading icon, data-icon="inline-start"
  3. 03Label, text-sm medium
  4. 04Optional trailing icon, data-icon="inline-end"

Usage

import { Button } from "@repo/design-system/components/ui/button";
import Link from "next/link";

<Button>Start a project</Button>
<Button variant="outline" size="sm">See work</Button>
<Button size="icon" aria-label="Add"><PlusIcon /></Button>

// A link that looks like a button
<Button nativeButton={false} render={<Link href="/contact" />}>
  Contact
</Button>

Props

PropTypeDefaultDescription
variant"default" | "outline" | "secondary" | "ghost" | "destructive" | "link""default"Default is the primary fill. Destructive is a tinted red, not a solid one.
size"default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg""default"Heights 24, 32, 36 and 40px. The icon sizes are square.
renderReactElement | (props, state) => ReactElementnoneBase UI's replacement for asChild: render the part as another element, such as a Button or a Link.
nativeButtonbooleantrueSet false when render is not a <button>, so Base UI adds the right role and keys.
disabledbooleanfalseHalf opacity, no pointer events.
classNamestringnoneMerged last with cn(). Use it for layout (width, margin), not to restyle the component.

Guidance

Do

  • Use one default button per view for the main action; outline or ghost for the rest.
  • Give icon-only buttons an aria-label.

Don't

  • Wrap a Button in a Link. Use render with nativeButton={false}.
  • Recolour it with className. If a variant is missing, it belongs in the cva.

Where it's used