@headspace_designsystem/hsds-web-library 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +184 -0
  2. package/dist/components/Button/Button.d.ts +3 -0
  3. package/dist/components/Button/Button.d.ts.map +1 -0
  4. package/dist/components/Button/Button.types.d.ts +18 -0
  5. package/dist/components/Button/Button.types.d.ts.map +1 -0
  6. package/dist/components/Button/index.d.ts +3 -0
  7. package/dist/components/Button/index.d.ts.map +1 -0
  8. package/dist/components/index.d.ts +2 -0
  9. package/dist/components/index.d.ts.map +1 -0
  10. package/dist/demo.d.ts +2 -0
  11. package/dist/demo.d.ts.map +1 -0
  12. package/dist/hsds-web-library.es.js +1927 -0
  13. package/dist/hsds-web-library.es.js.map +1 -0
  14. package/dist/hsds-web-library.umd.js +19 -0
  15. package/dist/hsds-web-library.umd.js.map +1 -0
  16. package/dist/index.d.ts +17 -0
  17. package/dist/index.d.ts.map +1 -0
  18. package/dist/theme/ThemeProvider.d.ts +14 -0
  19. package/dist/theme/ThemeProvider.d.ts.map +1 -0
  20. package/dist/theme/index.d.ts +4 -0
  21. package/dist/theme/index.d.ts.map +1 -0
  22. package/dist/theme/theme.d.ts +3 -0
  23. package/dist/theme/theme.d.ts.map +1 -0
  24. package/dist/theme/types.d.ts +88 -0
  25. package/dist/theme/types.d.ts.map +1 -0
  26. package/dist/tokens/index.d.ts +3 -0
  27. package/dist/tokens/index.d.ts.map +1 -0
  28. package/dist/tokens/primitives/borders.d.ts +41 -0
  29. package/dist/tokens/primitives/borders.d.ts.map +1 -0
  30. package/dist/tokens/primitives/colors.d.ts +67 -0
  31. package/dist/tokens/primitives/colors.d.ts.map +1 -0
  32. package/dist/tokens/primitives/index.d.ts +6 -0
  33. package/dist/tokens/primitives/index.d.ts.map +1 -0
  34. package/dist/tokens/primitives/shadows.d.ts +38 -0
  35. package/dist/tokens/primitives/shadows.d.ts.map +1 -0
  36. package/dist/tokens/primitives/spacing.d.ts +29 -0
  37. package/dist/tokens/primitives/spacing.d.ts.map +1 -0
  38. package/dist/tokens/primitives/typography.d.ts +46 -0
  39. package/dist/tokens/primitives/typography.d.ts.map +1 -0
  40. package/dist/tokens/semantic/colors.d.ts +154 -0
  41. package/dist/tokens/semantic/colors.d.ts.map +1 -0
  42. package/dist/tokens/semantic/index.d.ts +3 -0
  43. package/dist/tokens/semantic/index.d.ts.map +1 -0
  44. package/dist/tokens/semantic/typography.d.ts +253 -0
  45. package/dist/tokens/semantic/typography.d.ts.map +1 -0
  46. package/package.json +45 -0
package/README.md ADDED
@@ -0,0 +1,184 @@
1
+ # hsds_web_library
2
+
3
+ HeadSpace Design System — Web Component Library
4
+
5
+ A TypeScript-first design token library and React component system built with [Emotion](https://emotion.sh/) 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.
6
+
7
+ ---
8
+
9
+ ## What this is
10
+
11
+ | For designers | For engineers |
12
+ |---|---|
13
+ | Contribute styling changes directly in code, not just in Figma | Install components as a package — no building from scratch |
14
+ | Token changes propagate automatically to all components | Full TypeScript autocomplete on every design token |
15
+ | Components match Figma 1:1 | Versioned releases via npm — no stale, deprecated components |
16
+
17
+ ---
18
+
19
+ ## Token Architecture
20
+
21
+ All visual decisions flow in one direction:
22
+
23
+ ```
24
+ Primitive tokens Raw HeadSpace palette
25
+ ↓ (warmGrey100, blue200, ...)
26
+ Semantic tokens Intent-driven aliases
27
+ ↓ (foreground, background, border, ...)
28
+ HsdsTheme object Typed Emotion theme assembled from tokens
29
+
30
+ ThemeProvider React context that injects theme into the tree
31
+
32
+ Components Button, Input, Card, ... — all read from theme
33
+ ```
34
+
35
+ **Why two layers?**
36
+ 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.
37
+
38
+ ---
39
+
40
+ ## Quick Start
41
+
42
+ ### 1. Install
43
+
44
+ ```bash
45
+ npm install @headspace/hsds-web-library
46
+ ```
47
+
48
+ `react`, `react-dom`, `@emotion/react`, and `@emotion/styled` are peer dependencies — your app must already have them installed.
49
+
50
+ ### 2. Wrap your app with the ThemeProvider
51
+
52
+ ```tsx
53
+ import { HsdsThemeProvider } from '@headspace/hsds-web-library';
54
+
55
+ function App() {
56
+ return (
57
+ <HsdsThemeProvider>
58
+ <YourApp />
59
+ </HsdsThemeProvider>
60
+ );
61
+ }
62
+ ```
63
+
64
+ ### 3. Access tokens in your own styled components
65
+
66
+ ```tsx
67
+ import styled from '@emotion/styled';
68
+
69
+ // theme is fully typed — autocomplete works, typos fail at compile time
70
+ const MyCard = styled.div(({ theme }) => ({
71
+ backgroundColor: theme.colors.background.surface,
72
+ borderRadius: theme.borders.radius.medium,
73
+ padding: theme.spacing[4],
74
+ boxShadow: theme.shadows.raised,
75
+ }));
76
+ ```
77
+
78
+ ---
79
+
80
+ ## Token Reference
81
+
82
+ ### Colors
83
+
84
+ #### Primitive palette
85
+ Raw color values. **Never use these in components directly** — use semantic tokens instead.
86
+
87
+ Families: `warmGrey`, `coolGrey`, `blue`, `orange`, `yellow`, `green`, `pink`, `purple`, `indigo`, `winkle`, `red`
88
+
89
+ #### Semantic colors
90
+
91
+ | Category | Tokens |
92
+ |---|---|
93
+ | `colors.primary` | `primary`, `primaryStrong` |
94
+ | `colors.background` | `background`, `backgroundStrong` |
95
+ | `colors.surface` | `surface`, `surfaceStrong`, `surfaceStronger`, `surfaceStrongest`, `surfaceModal`, `surfaceOnModal` |
96
+ | `colors.overlay` | `overlay60/40/20`, `overlayInverse60`, `overlayLightStatic{80/60/40/20}`, `overlayDarkStatic{80/60/40/20}` |
97
+ | `colors.foreground` | `foreground`, `foregroundWeak`, `foregroundWeaker`, `foregroundWeakest`, `foregroundInverse`, `foregroundLink`, `foregroundLinkStrong`, `foregroundHighlight`, `foregroundCritical`, `foregroundSuccess` |
98
+ | `colors.border` | `border`, `borderStrong`, `borderStronger`, `borderStrongest`, `borderInverse` |
99
+ | `colors.interactive` | `interactive`, `interactiveStrong`, `interactiveStronger`, `interactiveStrongest`, `interactiveInverse`, `interactiveInverseStrong` |
100
+ | `colors.contrast` | `contrastForeground`, `contrastBackground`, `contrastForegroundWeak/Weaker/Weakest`, `contrastBackgroundWeak/Weaker` |
101
+ | `colors.status` | `statusCritical`, `statusSuccess`, `statusWarning`, `statusInfo`, `statusHighlight` (+ `*Strong` variants) |
102
+
103
+ ### Typography
104
+
105
+ Font family: **Headspace Apercu** (primary), **Apercu Mono** (utility/code)
106
+
107
+ Type scale categories: `heading` (3xl–s), `body` (l–3xs), `label` (l–3xs), `link` (l–3xs), `utility` (l–xs), `caption`
108
+
109
+ ```tsx
110
+ const headingStyle = theme.typography.desktop.heading['2xl'];
111
+ // → { fontFamily, fontSize: '56px', fontWeight: 700, lineHeight: '1.1', letterSpacing: '-3px' }
112
+ ```
113
+
114
+ ### Spacing
115
+
116
+ 16-step scale from `2px` to `128px`. Access via `theme.spacing[16]` → `'16px'`
117
+
118
+ ### Border Radius
119
+
120
+ | Token | Value | Figma name |
121
+ |---|---|---|
122
+ | `sharp` | 0px | hs-border-radius-sharp |
123
+ | `small2X` | 4px | hs-border-radius-small2X |
124
+ | `smallX` | 8px | hs-border-radius-smallX |
125
+ | `small` | 12px | hs-border-radius-small |
126
+ | `medium` | 16px | hs-border-radius-medium |
127
+ | `large` | 24px | hs-border-radius-large |
128
+ | `largeX` | 32px | hs-border-radius-largeX |
129
+ | `pill` | 999px | hs-border-radius-pill |
130
+ | `circle` | 50% | hs-border-radius-circle |
131
+
132
+ ### Shadows
133
+
134
+ `none`, `default`, `navigationTop`, `navigationBottom`, `raised`, `overlay`
135
+
136
+ ---
137
+
138
+ ## Repository Structure
139
+
140
+ ```
141
+ src/
142
+ ├── tokens/
143
+ │ ├── primitives/ Raw palette values (internal — do not import in components)
144
+ │ │ ├── colors.ts Warm grey, cool grey, blue, orange, green, red, ...
145
+ │ │ ├── typography.ts Font families, weights, line heights, letter spacing
146
+ │ │ ├── spacing.ts 2px–128px scale
147
+ │ │ ├── borders.ts Border radii and widths
148
+ │ │ └── shadows.ts Elevation shadow strings
149
+ │ └── semantic/ Intent-driven aliases (what components consume)
150
+ │ ├── colors.ts primary, background, surface, foreground, border, ...
151
+ │ └── typography.ts Desktop type scale objects
152
+ ├── theme/
153
+ │ ├── types.ts HsdsTheme interface — the stable typed contract
154
+ │ ├── emotion.d.ts Module augmentation (makes theme typed in styled())
155
+ │ ├── theme.ts Assembled HsdsTheme object
156
+ │ └── ThemeProvider.tsx React ThemeProvider wrapper
157
+ └── components/ (Phase 2+)
158
+ ```
159
+
160
+ ---
161
+
162
+ ## Roadmap
163
+
164
+ | Phase | Status | Scope |
165
+ |---|---|---|
166
+ | 1 — Foundation | Complete | Token files, HsdsTheme, ThemeProvider |
167
+ | 2 — Core Components | Planned | Button, Text, Stack, Input, Badge, Card, Divider |
168
+ | 3 — Storybook | Planned | Component docs, interactive playground |
169
+ | 4 — Full Library | Planned | Modal, Tooltip, Tabs, Checkbox, Toast, Avatar, + more |
170
+
171
+ ---
172
+
173
+ ## Contributing (for designers)
174
+
175
+ 1. Clone this repository and run `npm install`
176
+ 2. Edit token files in `src/tokens/` to update values
177
+ 3. Run `npm run typecheck` — if it passes, the values are valid
178
+ 4. Open a PR
179
+
180
+ ---
181
+
182
+ ## Tech Stack
183
+
184
+ - **React 18** + **TypeScript 5** + **Emotion 11** + **Vite 5**
@@ -0,0 +1,3 @@
1
+ import { ButtonProps } from './Button.types';
2
+ export declare function Button({ variant, size, isLoading, isFullWidth, leftIcon, rightIcon, disabled, children, ...rest }: ButtonProps): import("@emotion/react/jsx-runtime").JSX.Element;
3
+ //# sourceMappingURL=Button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../../../src/components/Button/Button.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAA6B,MAAM,gBAAgB,CAAC;AA8R7E,wBAAgB,MAAM,CAAC,EACrB,OAAmB,EACnB,IAAc,EACd,SAAiB,EACjB,WAAmB,EACnB,QAAQ,EACR,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,GAAG,IAAI,EACR,EAAE,WAAW,oDAuBb"}
@@ -0,0 +1,18 @@
1
+ import { default as React } from 'react';
2
+ export type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'ghost' | 'black' | 'white' | 'critical' | 'success' | 'warning' | 'textPrimary' | 'textSecondary';
3
+ export type ButtonSize = 'large' | 'mediumLarge' | 'medium' | 'small' | 'xSmall';
4
+ export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
5
+ /** Visual style of the button. @default 'primary' */
6
+ variant?: ButtonVariant;
7
+ /** Height and font size tier. @default 'large' */
8
+ size?: ButtonSize;
9
+ /** Replaces content with a spinner and sets disabled. @default false */
10
+ isLoading?: boolean;
11
+ /** Stretches the button to fill its container. @default false */
12
+ isFullWidth?: boolean;
13
+ /** Icon rendered before the label. */
14
+ leftIcon?: React.ReactNode;
15
+ /** Icon rendered after the label. */
16
+ rightIcon?: React.ReactNode;
17
+ }
18
+ //# sourceMappingURL=Button.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Button.types.d.ts","sourceRoot":"","sources":["../../../src/components/Button/Button.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,aAAa,GACrB,SAAS,GACT,WAAW,GACX,UAAU,GACV,OAAO,GACP,OAAO,GACP,OAAO,GACP,UAAU,GACV,SAAS,GACT,SAAS,GACT,aAAa,GACb,eAAe,CAAC;AACpB,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,QAAQ,CAAC;AAEjF,MAAM,WAAW,WAAY,SAAQ,KAAK,CAAC,oBAAoB,CAAC,iBAAiB,CAAC;IAChF,qDAAqD;IACrD,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,kDAAkD;IAClD,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,wEAAwE;IACxE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iEAAiE;IACjE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC3B,qCAAqC;IACrC,SAAS,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC7B"}
@@ -0,0 +1,3 @@
1
+ export { Button } from './Button';
2
+ export type { ButtonProps, ButtonVariant, ButtonSize } from './Button.types';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/Button/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export * from './Button';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC"}
package/dist/demo.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=demo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"demo.d.ts","sourceRoot":"","sources":["../src/demo.tsx"],"names":[],"mappings":""}