DESIGN

Raw
DESIGN.mdlatestcurrentRetrieved 2026-05-12

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

/* 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

/* 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

--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

/* 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

--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)

StyleSizeWeightUse
Display2.5remSemiboldHero text
Title Large2remSemiboldPage headings
Title Medium1.25remSemiboldSection headings
Title Small1remSemiboldSub-sections, card titles
Body Large1remNormalIntroductory prose
Body Medium0.875remNormalDefault UI text
Body Small0.75remNormalHelper text, compact contexts
Caption0.75remNormalImage captions, auxiliary labels
Code Block0.875remNormalMulti-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.

--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.

--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

--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.

--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.

/* 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.