--- system: primer category: design-md topic: DESIGN content_type: design-md status: latest version_label: "current" retrieved: 2026-05-12 source_url: https://github.com/primer/design derived_from: - kb/design-systems/primer/guidance/foundations/color-system - kb/design-systems/primer/guidance/foundations/typography - kb/design-systems/primer/assets/tokens/colors tags: [design-md, primer, github, color, typography, tokens] --- # Primer Design System ## Overview Primer is GitHub's design system. It powers github.com and all GitHub products. The visual language is functional and neutral — it prioritizes clarity, information density, and accessibility over expressive aesthetics. The system supports nine themes (light, dark, high contrast, colorblind, dimmed) through a semantic all-functional token model. **When to use Primer as a reference:** - Productivity and developer tools with a GitHub-adjacent context - Systems requiring multi-theme support without algorithmic color generation - Interfaces where token names should describe UI intent, not visual appearance --- ## Color ### Token model Three tiers: Base → Functional → Component/pattern. Components consume functional tokens only. Never use base tokens directly. **Functional token naming pattern:** - `{property}-{role}` — e.g. `bgColor-default`, `fgColor-muted` - `{property}-{semantic}-{variant}` — e.g. `bgColor-success-emphasis`, `borderColor-danger-muted` ### Neutral tokens ```css /* Text / Foreground */ --fgColor-default /* primary text */ --fgColor-muted /* secondary text, metadata */ --fgColor-onEmphasis /* text on emphasis backgrounds */ --fgColor-disabled /* disabled state */ --fgColor-link /* interactive links */ /* Background */ --bgColor-default /* page background */ --bgColor-muted /* secondary bg — code blocks, sidebars, table headers */ --bgColor-inset /* recessed bg — inputs, wells */ --bgColor-emphasis /* high-emphasis bg — tooltips; pair with fgColor-onEmphasis */ --bgColor-inverse /* opposite-theme bg */ /* Border */ --borderColor-default /* standard borders */ --borderColor-muted /* subtle dividers */ --borderColor-emphasis /* strong borders */ ``` ### Semantic color roles ```css /* accent — links, focus, selected */ --fgColor-accent --bgColor-accent-muted --bgColor-accent-emphasis /* success — primary actions, positive states */ --fgColor-success --bgColor-success-muted --bgColor-success-emphasis /* attention — warnings, active processes */ --fgColor-attention --bgColor-attention-muted --bgColor-attention-emphasis /* danger — errors, destructive actions */ --fgColor-danger --bgColor-danger-muted --bgColor-danger-emphasis /* open / closed / done — GitHub workflow states */ --fgColor-open --fgColor-closed --fgColor-done --bgColor-open-emphasis --bgColor-closed-emphasis --bgColor-done-emphasis /* sponsors — GitHub Sponsors context */ --fgColor-sponsors --bgColor-sponsors-emphasis ``` ### Key rules - Always use `fgColor-onEmphasis` for text on any `bgColor-*.emphasis` background. - Semantic role tokens auto-adapt across all nine themes. - `bgColor-success-emphasis` is the primary button background (green). - `bgColor-danger-emphasis` is the danger button background (red). --- ## Typography ### Font stacks ```css --fontStack-system: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans', Helvetica, Arial, sans-serif; --fontStack-monospace: ui-monospace, SFMono-Regular, 'SF Mono', Menlo, Consolas, 'Liberation Mono', monospace; ``` No custom typeface. System fonts only. ### Type scale ```css /* Base sizes */ --base-text-size-xs: 0.75rem; /* 12px — captions, compact labels */ --base-text-size-sm: 0.875rem; /* 14px — default body, most UI */ --base-text-size-md: 1rem; /* 16px — large body, small titles */ --base-text-size-lg: 1.25rem; /* 20px — medium titles */ --base-text-size-xl: 2rem; /* 32px — large headings */ --base-text-size-2xl: 2.5rem; /* 40px — display / hero */ ``` ### Font weights ```css --base-text-weight-light: 300; --base-text-weight-normal: 400; /* body text default */ --base-text-weight-medium: 500; /* labels, metadata emphasis */ --base-text-weight-semibold: 600; /* headings, strong labels */ ``` ### Typographic styles (shorthand) | Style | Size | Weight | Use | |---|---|---|---| | Display | 2.5rem | Semibold | Hero text | | Title Large | 2rem | Semibold | Page headings | | Title Medium | 1.25rem | Semibold | Section headings | | Title Small | 1rem | Semibold | Sub-sections, card titles | | Body Large | 1rem | Normal | Introductory prose | | Body Medium | 0.875rem | Normal | Default UI text | | Body Small | 0.75rem | Normal | Helper text, compact contexts | | Caption | 0.75rem | Normal | Image captions, auxiliary labels | | Code Block | 0.875rem | Normal | Multi-line code, monospace | ### Rules - `rem` units throughout — supports browser zoom. - Line heights are unitless, aligned to 4px grid. - Do not adjust `letter-spacing`. - Use weight CSS variables, not raw numbers. - Do not reorder heading tags (h1–h6) for visual styling — use CSS classes. --- ## Spacing Primer uses a 4px base grid. Most layout spacing is expressed in multiples of 4px. ```css --base-size-4: 0.25rem; /* 4px */ --base-size-8: 0.5rem; /* 8px */ --base-size-12: 0.75rem; /* 12px */ --base-size-16: 1rem; /* 16px */ --base-size-24: 1.5rem; /* 24px */ --base-size-32: 2rem; /* 32px */ --base-size-40: 2.5rem; /* 40px */ --base-size-48: 3rem; /* 48px */ --base-size-64: 4rem; /* 64px */ ``` --- ## Shape Primer uses a small set of border-radius values. Components tend toward subtle rounding. ```css --borderRadius-small: 3px; /* inline elements, small tags */ --borderRadius-medium: 6px; /* buttons, inputs, cards */ --borderRadius-large: 12px; /* larger containers */ --borderRadius-full: 9999px; /* pills, circular avatars */ ``` --- ## Shadow / Elevation ```css --shadow-resting-xsmall /* cards, resting surfaces */ --shadow-resting-small /* slightly elevated surfaces */ --shadow-floating-small /* tooltips, small dropdowns */ --shadow-floating-medium /* menus, popovers */ --shadow-floating-large /* dialogs */ --shadow-inset /* active inputs, sunken elements */ ``` --- ## Focus All interactive elements must have a visible focus indicator. ```css --focus-outlineColor /* accent color in all themes */ --focus-outlineWidth /* 2px */ --focus-outlineOffset /* 2px */ ``` `box-shadow: 0 0 0 var(--focus-outlineWidth) var(--focus-outlineColor)` is the standard focus ring implementation. --- ## Interactive states State layers use the `bgColor-neutral-muted` token at varying opacities, or theme-specific state tokens. ```css /* Component state tokens */ --control-bgColor-hover /* hover state background for controls */ --control-bgColor-active /* active/pressed state */ --control-bgColor-disabled /* disabled state background */ --control-borderColor-default --control-borderColor-hover --control-borderColor-danger --control-fgColor-placeholder ``` --- ## Components ### Button **Variants:** Primary (success-emphasis), Secondary (default neutral), Danger (danger-emphasis), Invisible (transparent), Inactive, Loading. ``` bgColor-success-emphasis → Primary button bg bgColor-danger-emphasis → Danger button bg bgColor-default → Secondary button bg fgColor-onEmphasis → Text on Primary and Danger buttons focus-outlineColor → Focus ring borderRadius-medium → Button shape ``` - One Primary button per page/group. - Label should be descriptive enough without surrounding context. - Prefer Inactive over Disabled — disabled buttons aren't always focusable. - Loading state: `aria-disabled="true"`, keep focusable, use live region. ### Form controls ``` control-bgColor-default → Input background control-borderColor-default → Input border at rest control-borderColor-hover → Input border on hover borderColor-accent-emphasis → Focus border borderColor-danger-emphasis → Error border fgColor-danger → Error message text control-fgColor-placeholder → Placeholder text ``` ### Status indicators (Labels, Badges) Use semantic role token pairs: - Muted: `bgColor-{role}-muted` + `fgColor-{role}` - Emphasis: `bgColor-{role}-emphasis` + `fgColor-onEmphasis` GitHub workflow states use `open`, `closed`, `done` roles specifically.