Button

The button wraps Base UI’s button component with Density’s shared control attributes.

import { Button } from "density-base-ui";

export default function ButtonExample() {
  return <Button type="button">Save changes</Button>;
}

Icons and dots

Use icons and decorative dots alongside a button’s text label.

import { Button, Indicator, View } from "density-base-ui";
import { Download } from "lucide-react";

export default function ButtonContentExample() {
  return (
    <View align="center" orientation="horizontal" padding={false} wrap>
      <Button type="button">
        <Download aria-hidden="true" size={16} strokeWidth={1.75} />
        Download report
      </Button>
      <Button type="button" emphasis="secondary">
        <Indicator />
        Syncing
      </Button>
    </View>
  );
}

Emphasis

import { Button, View } from "density-base-ui";

export default function ButtonEmphasisExample() {
  return (
    <View orientation="horizontal" padding={false} wrap>
      <Button type="button" emphasis="primary">
        Primary
      </Button>
      <Button type="button" emphasis="secondary">
        Secondary
      </Button>
      <Button type="button" emphasis="outline">
        Outline
      </Button>
      <Button type="button" emphasis="ghost-primary">
        Ghost primary
      </Button>
      <Button type="button" emphasis="ghost-secondary">
        Ghost secondary
      </Button>
      <Button type="button" emphasis="ghost-tertiary">
        Ghost tertiary
      </Button>
    </View>
  );
}

Color

Set color to destructive, warning, or success for semantic action color. It is independent of emphasis, so choose the emphasis that fits the action’s hierarchy while keeping its status meaning clear. This grid shows every color and emphasis combination.

primarysecondaryoutlineghost-primaryghost-secondaryghost-tertiary
destructive
warning
success
import { Button, View } from "density-base-ui";

const colors = ["destructive", "warning", "success"] as const;
const emphases = [
  "primary",
  "secondary",
  "outline",
  "ghost-primary",
  "ghost-secondary",
  "ghost-tertiary",
] as const;

export default function ButtonColorExample() {
  return (
    <View align="stretch" gap="md">
      <View
        align="center"
        gap="md"
        layout="grid"
        style={{ gridTemplateColumns: "7rem repeat(6, minmax(0, 1fr))" }}
      >
        <span />
        {emphases.map((emphasis) => (
          <span key={emphasis} data-dn-size="xs">
            {emphasis}
          </span>
        ))}
      </View>
      {colors.map((color) => (
        <View
          key={color}
          align="center"
          gap="md"
          layout="grid"
          style={{ gridTemplateColumns: "7rem repeat(6, minmax(0, 1fr))" }}
        >
          <span data-dn-size="xs">{color}</span>
          {emphases.map((emphasis) => (
            <Button
              color={color}
              emphasis={emphasis}
              key={emphasis}
              type="button"
            >
              Action
            </Button>
          ))}
        </View>
      ))}
    </View>
  );
}

Selected

Use selected for persistent choices. It is separate from pointer active and keyboard focus states, and works with every emphasis.

import { Button, View } from "density-base-ui";

export default function ButtonSelectedExample() {
  return (
    <View orientation="horizontal" padding={false} wrap>
      <Button type="button" emphasis="primary" selected>
        Primary
      </Button>
      <Button type="button" emphasis="secondary" selected>
        Secondary
      </Button>
      <Button type="button" emphasis="outline" selected>
        Outline
      </Button>
      <Button type="button" emphasis="ghost-primary" selected>
        Ghost primary
      </Button>
      <Button type="button" emphasis="ghost-secondary" selected>
        Ghost secondary
      </Button>
      <Button type="button" emphasis="ghost-tertiary" selected>
        Ghost tertiary
      </Button>
    </View>
  );
}

Hover visibility

Inside a reveal host such as ListItem, set hoverVisibility="hover" to show a button while its host is hovered or contains keyboard focus. Use not-hover for the inverse; always is the default.

Release notes
import { Button, ListItem, View } from "density-base-ui";

export default function ButtonHoverVisibilityExample() {
  return (
    <View align="start" gap="md" padding={false}>
      <ListItem
        as="div"
        title="Release notes"
        childrenEnd={
          <Button hoverVisibility="hover" size="sm" type="button">
            View
          </Button>
        }
      />
    </View>
  );
}

Size

Button sizes use the shared Density control scale: 2xs, xs, sm, md, lg, xl, 2xl, and 3xl. A button and input with the same size have the same height.

import { Button, View } from "density-base-ui";

export default function ButtonSizeExample() {
  return (
    <View orientation="horizontal" padding={false} wrap>
      <Button type="button" size="2xs">
        2xs
      </Button>
      <Button type="button" size="xs">
        xs
      </Button>
      <Button type="button" size="sm">
        sm
      </Button>
      <Button type="button" size="md">
        md
      </Button>
      <Button type="button" size="lg">
        lg
      </Button>
      <Button type="button" size="xl">
        xl
      </Button>
      <Button type="button" size="2xl">
        2xl
      </Button>
      <Button type="button" size="3xl">
        3xl
      </Button>
    </View>
  );
}

Shape

Use radius="full" for pill buttons and square for icon-only buttons. Combine them for circular icon buttons. Use the other shared radius values when a button must match a surrounding surface.

import { Button, View } from "density-base-ui";

export default function ButtonShapeExample() {
  return (
    <View orientation="horizontal" padding={false} wrap>
      <Button type="button">Default</Button>
      <Button type="button" radius="full">
        Pill
      </Button>
      <Button type="button" square aria-label="Square button">
        +
      </Button>
      <Button type="button" radius="full" square aria-label="Round button">
        +
      </Button>
    </View>
  );
}