@headspace_designsystem/hsds-web-library
v0.2.2
Published
HeadSpace Design System — web component library (React + TypeScript + Emotion)
Downloads
426
Readme
hsds_web_library
HeadSpace Design System — Web Component Library
A TypeScript-first design token library and React component system built with Emotion for CSS-in-JS. This library translates the HeadSpace design system directly into code, giving engineers production-ready, typed, accessible components and giving designers a single source of truth that flows from Figma to the browser.
What this is
| For designers | For engineers | |---|---| | Contribute styling changes directly in code, not just in Figma | Install components as a package — no building from scratch | | Token changes propagate automatically to all components | Full TypeScript autocomplete on every design token | | Components match Figma 1:1 | Versioned releases via npm — no stale, deprecated components |
Token Architecture
All visual decisions flow in one direction:
Primitive tokens Raw HeadSpace palette
↓ (warmGrey100, blue200, ...)
Semantic tokens Intent-driven aliases
↓ (foreground, background, border, ...)
HsdsTheme object Typed Emotion theme assembled from tokens
↓
ThemeProvider React context that injects theme into the tree
↓
Components Button, Input, Card, ... — all read from themeWhy two layers?
If the primary blue changes, you update one hex value in primitives/colors.ts. Every semantic token that references it (Primary/primary, Foreground/foregroundLink, etc.) picks it up instantly — no hunt-and-replace across 50 components.
Quick Start
1. Install
npm install @headspace/hsds-web-libraryreact, react-dom, @emotion/react, and @emotion/styled are peer dependencies — your app must already have them installed.
2. Wrap your app with the ThemeProvider
import { HsdsThemeProvider } from '@headspace/hsds-web-library';
function App() {
return (
<HsdsThemeProvider>
<YourApp />
</HsdsThemeProvider>
);
}3. Access tokens in your own styled components
import styled from '@emotion/styled';
// theme is fully typed — autocomplete works, typos fail at compile time
const MyCard = styled.div(({ theme }) => ({
backgroundColor: theme.colors.background.surface,
borderRadius: theme.borders.radius.medium,
padding: theme.spacing[4],
boxShadow: theme.shadows.raised,
}));Token Reference
Colors
Primitive palette
Raw color values. Never use these in components directly — use semantic tokens instead.
Families: warmGrey, coolGrey, blue, orange, yellow, green, pink, purple, indigo, winkle, red
Semantic colors
| Category | Tokens |
|---|---|
| colors.primary | primary, primaryStrong |
| colors.background | background, backgroundStrong |
| colors.surface | surface, surfaceStrong, surfaceStronger, surfaceStrongest, surfaceModal, surfaceOnModal |
| colors.overlay | overlay60/40/20, overlayInverse60, overlayLightStatic{80/60/40/20}, overlayDarkStatic{80/60/40/20} |
| colors.foreground | foreground, foregroundWeak, foregroundWeaker, foregroundWeakest, foregroundInverse, foregroundLink, foregroundLinkStrong, foregroundHighlight, foregroundCritical, foregroundSuccess |
| colors.border | border, borderStrong, borderStronger, borderStrongest, borderInverse |
| colors.interactive | interactive, interactiveStrong, interactiveStronger, interactiveStrongest, interactiveInverse, interactiveInverseStrong |
| colors.contrast | contrastForeground, contrastBackground, contrastForegroundWeak/Weaker/Weakest, contrastBackgroundWeak/Weaker |
| colors.status | statusCritical, statusSuccess, statusWarning, statusInfo, statusHighlight (+ *Strong variants) |
Typography
Font family: Headspace Apercu (primary), Apercu Mono (utility/code)
Type scale categories: heading (3xl–s), body (l–3xs), label (l–3xs), link (l–3xs), utility (l–xs), caption
const headingStyle = theme.typography.desktop.heading['2xl'];
// → { fontFamily, fontSize: '56px', fontWeight: 700, lineHeight: '1.1', letterSpacing: '-3px' }Spacing
16-step scale from 2px to 128px. Access via theme.spacing[16] → '16px'
Border Radius
| Token | Value | Figma name |
|---|---|---|
| sharp | 0px | hs-border-radius-sharp |
| small2X | 4px | hs-border-radius-small2X |
| smallX | 8px | hs-border-radius-smallX |
| small | 12px | hs-border-radius-small |
| medium | 16px | hs-border-radius-medium |
| large | 24px | hs-border-radius-large |
| largeX | 32px | hs-border-radius-largeX |
| pill | 999px | hs-border-radius-pill |
| circle | 50% | hs-border-radius-circle |
Shadows
none, default, navigationTop, navigationBottom, raised, overlay
Repository Structure
src/
├── tokens/
│ ├── primitives/ Raw palette values (internal — do not import in components)
│ │ ├── colors.ts Warm grey, cool grey, blue, orange, green, red, ...
│ │ ├── typography.ts Font families, weights, line heights, letter spacing
│ │ ├── spacing.ts 2px–128px scale
│ │ ├── borders.ts Border radii and widths
│ │ └── shadows.ts Elevation shadow strings
│ └── semantic/ Intent-driven aliases (what components consume)
│ ├── colors.ts primary, background, surface, foreground, border, ...
│ └── typography.ts Desktop type scale objects
├── theme/
│ ├── types.ts HsdsTheme interface — the stable typed contract
│ ├── emotion.d.ts Module augmentation (makes theme typed in styled())
│ ├── theme.ts Assembled HsdsTheme object
│ └── ThemeProvider.tsx React ThemeProvider wrapper
└── components/ (Phase 2+)Roadmap
| Phase | Status | Scope | |---|---|---| | 1 — Foundation | Complete | Token files, HsdsTheme, ThemeProvider | | 2 — Core Components | Planned | Button, Text, Stack, Input, Badge, Card, Divider | | 3 — Storybook | Planned | Component docs, interactive playground | | 4 — Full Library | Planned | Modal, Tooltip, Tabs, Checkbox, Toast, Avatar, + more |
Contributing (for designers)
- Clone this repository and run
npm install - Edit token files in
src/tokens/to update values - Run
npm run typecheck— if it passes, the values are valid - Open a PR
Tech Stack
- React 18 + TypeScript 5 + Emotion 11 + Vite 5
