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
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
defaultwhen the interface needs one obvious next step. - Use
outline,secondary,ghost, orquietwhen the action should stay available without competing for attention. - Use
catalog,accent, orinvertedwhen the surrounding surface has stronger art direction or contrast requirements. - Use
linkwhen 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.
| Variant | Use it for |
|---|---|
default | The main action in a section, form, dialog, or toolbar. |
secondary | A lower-emphasis filled alternative that still needs visible weight. |
outline | Secondary actions that should remain clearly interactive on neutral surfaces. |
ghost | Minimal controls in dense layouts like tables, cards, and row actions. |
quiet | Secondary actions on editorial or docs surfaces where borders should stay subtle. |
link | Inline actions that belong inside flowing text or metadata rows. |
destructive | Confirmed delete, archive, or reset paths. |
catalog | Product, launch, or gallery CTAs that need stronger typographic character. |
accent | Highlighted actions tied to campaign, status, or system accent color. |
inverted | Dark 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
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
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
Submitwhen the outcome can be named directly.
Choose Variant By Hierarchy
- Prefer one strong action per section.
- Use
quietorlinkbefore creating another filled button. - Reserve
destructivefor actions that genuinely remove, reset, or damage state.
Keep Composition Intentional
- Use
asChildwhen semantics matter more than the defaultbuttonelement. - Use
ButtonGroupwhen 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.
| Prop | Type | Default |
|---|---|---|
variant | "default" | "destructive" | "outline" | "secondary" | "ghost" | "link" | "quiet" | "inverted" | "catalog" | "accent" | "default" |
size | "sm" | "default" | "lg" | "icon" | "default" |
asChild | boolean | false |
ButtonProps also extends the standard React.ButtonHTMLAttributes<HTMLButtonElement> API, so native props like type, disabled, and onClick work as expected.