Skip to main content
Gremorie

Button

When to use a button, hierarchy across variants, and the label rule (1-3 words, imperative).

TL;DR

A button performs an action. A link navigates. One screen carries at most one primary action; everything else is secondary. Labels are 1-3 words, imperative, and contextual ("Save changes", not "Submit").

The rule

  1. Action vs navigation. If activating it changes data, opens an overlay, or runs a process, it is a button. If it moves you to another URL or scrolls to a section, it is a link. Style does not determine semantics: a link can look like a button, but render <a>.
  2. One primary per surface. Each card, panel, form, or page header has at most one button styled as primary (the default variant). All other actions on that surface use a lower-emphasis variant: outline, secondary, ghost, or link.
  3. Destructive is its own hierarchy. A destructive action (delete, remove, revoke) uses the destructive variant, never the primary. It is also rarely primary in flow: the safe action is.
  4. Label = verb + object. Imperative, 1-3 words: "Save changes", "Add member", "Discard draft". Avoid "OK", "Submit", "Click here".
  5. Disabled state needs a reason. Never disable a button without telling the user why. Show the missing requirement near the button, or replace disabled with a tooltip-explained reason.

Why

Buttons carry intent. When every action looks equally important, none of them do, and the user pauses to read each label instead of recognizing the safe path. Visual hierarchy is how the interface answers "what should I do here?" before the user finishes reading. Nielsen's heuristic #6 (recognition over recall) and Fitts' law together argue for one obvious target per decision: large, contrast-rich, on the path the eye already follows.

The label rule is a downstream consequence. A generic "Submit" forces the user to remember which form they are in. "Save changes" or "Send invitation" carries that context for them.

How to apply

Do

<div className="flex justify-end gap-2">
  <Button variant="outline">Cancel</Button>
  <Button>Save changes</Button>
</div>

One primary ("Save changes") next to one secondary ("Cancel"). Labels describe what happens.

Don't

<div className="flex justify-end gap-2">
  <Button>Cancel</Button>
  <Button>OK</Button>
  <Button>Submit</Button>
</div>

Three primaries compete. Two labels ("OK", "Submit") tell the user nothing about the result.

Destructive in confirmation flows

<Dialog>
  <DialogContent>
    <DialogTitle>Delete project?</DialogTitle>
    <DialogDescription>This cannot be undone.</DialogDescription>
    <DialogFooter>
      <Button variant="outline">Keep project</Button>
      <Button variant="destructive">Delete project</Button>
    </DialogFooter>
  </DialogContent>
</Dialog>

The safe action is on the left, low-emphasis. The destructive action is explicit ("Delete project", not "Yes").

Counter-cases

  • Toolbars and segmented controls legitimately repeat ghost or outline buttons because they form a set, not a hierarchy. Use ToggleGroup instead of a row of buttons.
  • Card grids can carry one primary action per card when each card is an independent surface (a product, a project). The "one per surface" rule applies per card, not per page.
  • Splash and onboarding screens sometimes promote two equally-weighted CTAs ("Sign up" vs "Log in"). Acceptable when the choice is genuinely binary; pair with distinct copy so the labels disambiguate.
  • Icon-only buttons in dense UI (table rows, toolbars) need a tooltip and aria-label; the icon is the label and must be unambiguous.

Sources

  • Nielsen Norman Group: "Primary vs. Secondary Action Buttons" (https://www.nngroup.com/articles/primary-vs-secondary-actions/)
  • Krug, "Don't Make Me Think" (2014): chapter on clickability and visual hierarchy.
  • WCAG 2.1 SC 2.4.4 - Link Purpose (In Context): labels must convey purpose.
  • WAI-ARIA Authoring Practices: button vs link semantics.

On this page