About & Accessibility
The design system's philosophy and its WCAG 2.1 AA accessibility commitment.
GHDS (GH Design System) is a cross-platform design system that keeps its hand-drawn (sketchy) look and feel without compromising on consistency or accessibility.
Philosophy
- Tokens are the single source of truth — every color, spacing, typography, radius, and
shadow value comes from
@ghds/tokens. - Framework-neutral — React, Lit web components, and React Native all consume the same tokens.
- Three-tier tokens — the
comp → sys → refboundary separates meaning from value.
See Design Principles for the full principle set behind these decisions.
Why Hand-Drawn?
Intent
The sketchy rendering is a deliberate choice, not an accident of the tooling:
- Friendliness and informality — the wobble reads as approachable rather than sterile.
- Human warmth — hand-drawn lines feel made by someone, not generated by a template.
- A deliberately non-corporate tone — GHDS avoids the flat, interchangeable look of most component libraries.
- Psychological safety — a softer visual register takes some of the edge off errors, empty states, and onboarding moments.
When it’s appropriate
- Marketing and product surfaces
- Illustrations and empty-state art
- Onboarding flows
- Casual, consumer-facing contexts
When to dial it down
- High-trust financial UIs
- Safety-critical confirmations
- Legal or compliance flows
- Dense data tables and enterprise dashboards
In these contexts, precision and authority matter more than warmth — see principle 1.
How sketch-core implements it
@ghds/sketch-core perturbs geometry rather than drawing by hand: offset() in
packages/sketch-core/src/geometry/offset.ts applies the jitter, and SketchOptions in
packages/sketch-core/src/types.ts exposes the numeric knobs (roughness, bowing,
hachureGap, hachureAngle, elevation) that every component reads. These knobs are token-driven,
never hardcoded — the same rule as principle 2.
Roughness token scale — dialing intensity up/down
| Intensity | roughness | bowing | hachureGap | hachureAngle | elevation |
|---|---|---|---|---|---|
| none / flat | 0 | 0 | — | — | flat (0) |
| subtle | 0.8 | 1 | tight (4) | — | — |
| default | 1.4 | 2 | default (8) | -41 | raised (4) |
| rough / strong / cross | 2.4 | 4 (strong) | loose (14) | cross (41) | — |
These live at the reference tier (ref.sketch.*). sys.sketch.* aliases the default/raised
values so they’re theme-invariant, and each component’s comp.<component>.sketch.* tokens
(e.g. comp.button.sketch.*, comp.card.sketch.*, comp.input.sketch.*) alias the sys tier in
turn — never ref directly.
To dial a specific component down — a “confirm delete” button in a high-trust flow, for example —
the component’s comp.*.sketch.roughness token must still resolve through sys, never skip
straight to ref (the comp → sys → ref boundary applies here too). The correct path is to add a
new sys-tier role (e.g. sys.sketch.roughness.subtle, aliasing ref.sketch.roughness.subtle),
then repoint that component’s comp.*.sketch.roughness alias to the new sys token — documenting
why with a comment. Never hardcode a numeric roughness value, and never have a comp token
reference ref directly.
Accessibility Commitment
- Text/background color pairings meet WCAG 2.1 AA contrast minimums (4.5:1 for normal text, 3:1 for large text), validated automatically in the tokens package.
- Components ship with keyboard focus,
aria-*attributes, and meaningful labels by default. - Dark mode works via the
[data-theme="dark"]token, and also respects the user’s system preference.
See the Accessibility Guide for keyboard interaction, focus management, ARIA patterns, and testing checklists.
License
MIT.