--- system: primer category: components topic: button content_type: guidance status: latest version_label: "current" retrieved: 2026-05-12 source_url: https://github.com/primer/design/blob/main/content/components/button.mdx tags: [button, components, variants, accessibility, interactive-states] --- # Primer — Button ## Overview Button is used to initiate actions on a page or form. At GitHub, buttons are a fundamental building block. Most interactions use the `secondary` variant; other variants communicate hierarchy or specific functionality. --- ## Anatomy A button consists of up to four elements: | Element | Required | Description | |---|---|---| | Label | Yes | Text describing the action; serves as the accessible name | | Leading visual | No | Icon before the label providing additional context | | Trailing visual | No | Counters or supplementary information after the label | | Trailing action | No | Dropdown caret or similar; always locked to the end of the button | **Trailing action alignment:** A call-to-action button (Submit, Save) has label and visuals center-aligned. A selection button (Sort ▾, Weeks ▾) has contents left-aligned inside the container. --- ## Variants | Variant | Background | Use | |---|---|---| | **Primary** | `bgColor-success-emphasis` (green) | Highest-priority action. Only one per page or button group. | | **Secondary** | `bgColor-default` (neutral) | Default for most interactions. Can pair with primary. | | **Danger** | `bgColor-danger-emphasis` (red) | Destructive actions. Typically opens a confirmation dialog. | | **Invisible** | Transparent | Transparent background with translucent hover/active states. Used in compound components like ActionList. | | **Inactive** | Muted styling | Non-functional button that remains on screen. Unlike disabled, it responds to input (can show tooltips or dialogs). | | **Loading** | — | Replaces label with a spinner while an action is processing. | --- ## Sizing | Size | Height | Use | |---|---|---| | Small | — | Limited space, less significant actions | | **Medium** (default) | — | Preferred for most interfaces | | Large | — | Emphasizes action significance; use sparingly | --- ## States | State | Visual | Notes | |---|---|---| | Rest | Variant default colors | | | Hover | Translucent state layer overlay | | | Focus | 2px focus ring (`focus-outlineColor`) | Required; must be visible on keyboard interaction | | Active / Pressed | Deeper translucent state layer | | | Disabled | `fgColor-disabled` opacity | Consider Inactive state instead of Disabled — disabled buttons can frustrate users | | Loading | Spinner replaces label; button disabled | Apply `aria-disabled="true"`; keep button focusable; use hidden live region for status | | Inactive | Muted styling; responds to input | Use `aria-disabled="true"` only if the button is non-interactive | --- ## Best practices - **Label:** Keep labels short and use sentence case. No line breaks. Labels should describe the action clearly enough to stand alone. - **Primary button:** Use only one primary button per page or button group, and typically only one per view. - **Pairing:** Primary buttons should be paired with secondary buttons, not other primary buttons. - **Position:** Place the primary button at the end of a button group (right side in LTR layouts). - **Icons:** Leading icons provide context but don't replace label text. Don't rely on an icon alone to convey meaning. - **Selecting multiple items:** Use "2 selected" format rather than comma-separated value lists on the button label. --- ## Accessibility - **Minimum touch target:** 24×24 CSS pixels. - **Accessible name:** The button label is the accessible name. It must be descriptive enough on its own — don't rely on surrounding context or icons. - **Focus indicator:** Always display focus styles on keyboard interaction. Do not suppress the focus ring. - **Icons:** Octicons used as leading/trailing visuals are purely visual — no text alternative is provided. Screen readers hear only the button label. - **Disabled vs. Inactive:** - Prefer Inactive state over Disabled. Disabled buttons are not focusable in some implementations, reducing discoverability. - An Inactive button that shows a dialog on click should not use `aria-disabled`. - An Inactive button that is truly non-interactive may use `aria-disabled="true"`. - **Loading state:** Apply `aria-disabled="true"`, keep the button focusable, and use a visually hidden live region to communicate loading status to screen reader users. - **ARIA role:** Native `