Basel Standard

Basel Standard / Docs

Button

Core action primitive with Swiss-styled variants for product, docs, editorial, and commerce surfaces.

Buttons establish hierarchy quickly. In this system they are compact, typographic, and deliberate: one clear primary action, quieter secondary paths, and a few surface-specific variants for editorial or catalog contexts.

Installation

Install
Purchase access, then open /account/install to issue a registry token.

Usage

import { Button } from "@/components/ui/button"
<Button>Primary action</Button>
<Button variant="outline">Secondary action</Button>
<Button variant="catalog">Open collection</Button>

Why This Primitive Exists

The Swiss button is meant to stay useful across very different surfaces without turning into a one-off per page.

  • Use default when the interface needs one obvious next step.
  • Use outline, secondary, ghost, or quiet when the action should stay available without competing for attention.
  • Use catalog, accent, or inverted when the surrounding surface has stronger art direction or contrast requirements.
  • Use link when the action should read inline with text rather than as a framed control.

Examples

Variant Overview

This component includes the baseline variants you would expect from shadcn plus a few system-specific variants that are useful on editorial and commerce pages.

VariantUse it for
defaultThe main action in a section, form, dialog, or toolbar.
secondaryA lower-emphasis filled alternative that still needs visible weight.
outlineSecondary actions that should remain clearly interactive on neutral surfaces.
ghostMinimal controls in dense layouts like tables, cards, and row actions.
quietSecondary actions on editorial or docs surfaces where borders should stay subtle.
linkInline actions that belong inside flowing text or metadata rows.
destructiveConfirmed delete, archive, or reset paths.
catalogProduct, launch, or gallery CTAs that need stronger typographic character.
accentHighlighted actions tied to campaign, status, or system accent color.
invertedDark or image-heavy surfaces where the button needs to reverse against the background.

Sizes

Use size changes to fit layout density, not to create visual importance. Hierarchy should come from variant choice first.

<Button size="sm">Compact action</Button>
<Button>Default action</Button>
<Button size="lg">Prominent action</Button>
<Button size="icon" aria-label="Zoom in">
  <Plus className="size-4" />
</Button>

With Icons

Icons should clarify direction or intent, not decorate the label. Use them when the action benefits from a cue like forward motion, export, search, or external navigation.

import { ArrowRight, Download } from "lucide-react"
import { Button } from "@/components/ui/button"

<Button>
  Open Story
  <ArrowRight className="size-4" />
</Button>

<Button variant="outline">
  <Download className="size-4" />
  Download Spec
</Button>

For icon-only buttons, always provide an aria-label.

Loading And Disabled States

When an action has already been committed, keep the button in place and communicate progress instead of swapping the control out of the layout.

import { Button } from "@/components/ui/button"
import { Spinner } from "@/components/ui/spinner"

<Button disabled>
  <Spinner className="text-current" />
  Publishing
</Button>

As Child

Use asChild when another semantic element should keep its native behavior while borrowing button styling. This is useful for links, route transitions, or composed navigation elements.

import Link from "next/link"
import { Button } from "@/components/ui/button"

<Button asChild>
  <Link href="/docs/components/card">Read the card docs</Link>
</Button>

Grouped Actions

For closely related controls, pair the button primitive with Button Group. Horizontal groups work well in toolbars; vertical groups work better in admin panels and side rails.

Stacked controls

Vertical groups work for dense admin surfaces.
import { Button } from "@/components/ui/button"
import { ButtonGroup } from "@/components/ui/button-group"

<ButtonGroup>
  <Button variant="outline">Filter</Button>
  <Button variant="outline">Export</Button>
  <Button variant="outline">Configure</Button>
</ButtonGroup>

In Context

A button doc page should show more than isolated controls. This example demonstrates how action hierarchy behaves inside a real editorial surface.

Editorial CTA row

Buttons should support hierarchy before decoration.

A primary action anchors the section, while quieter controls handle secondary paths without adding visual noise.

Guidance

Write Better Labels

  • Start with a verb: Publish, Export, Request Access.
  • Keep labels short enough to scan in a toolbar or card footer.
  • Avoid vague labels like Submit when the outcome can be named directly.

Choose Variant By Hierarchy

  • Prefer one strong action per section.
  • Use quiet or link before creating another filled button.
  • Reserve destructive for actions that genuinely remove, reset, or damage state.

Keep Composition Intentional

  • Use asChild when semantics matter more than the default button element.
  • Use ButtonGroup when controls are part of the same decision cluster.
  • Use icon-only buttons sparingly and always label them for assistive technology.

API Reference

Button

The Button component wraps a native button and adds shared variants, sizing, and asChild composition.

PropTypeDefault
variant"default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "quiet" | "inverted" | "catalog" | "accent""default"
size"sm" | "default" | "lg" | "icon""default"
asChildbooleanfalse

ButtonProps also extends the standard React.ButtonHTMLAttributes<HTMLButtonElement> API, so native props like type, disabled, and onClick work as expected.