@hirobius/design-system 0.13.0 → 0.14.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.
- package/NOTICE.md +9 -0
- package/README.md +109 -43
- package/dist/contexts.js +62 -60
- package/dist/hirobius-ui.js +6810 -5807
- package/dist/manifest.js +5 -5
- package/dist/static.css +1 -1
- package/dist/styles.css +1 -1
- package/dist/tokens.css +1 -1
- package/dist/tokens.js +2 -2
- package/dist/types/src/app/components/activity-feed.d.ts +6 -0
- package/dist/types/src/app/components/alert.d.ts +1 -0
- package/dist/types/src/app/components/avatar.d.ts +1 -0
- package/dist/types/src/app/components/badge.d.ts +1 -0
- package/dist/types/src/app/components/box.d.ts +2 -2
- package/dist/types/src/app/components/breadcrumb.d.ts +1 -0
- package/dist/types/src/app/components/button.d.ts +1 -0
- package/dist/types/src/app/components/callout.d.ts +1 -0
- package/dist/types/src/app/components/card.d.ts +7 -2
- package/dist/types/src/app/components/checkbox.d.ts +1 -0
- package/dist/types/src/app/components/code-block.d.ts +1 -0
- package/dist/types/src/app/components/combobox.d.ts +1 -0
- package/dist/types/src/app/components/dialog.d.ts +5 -0
- package/dist/types/src/app/components/disclosure.d.ts +1 -0
- package/dist/types/src/app/components/divider.d.ts +4 -0
- package/dist/types/src/app/components/empty-state.d.ts +1 -0
- package/dist/types/src/app/components/field.d.ts +1 -0
- package/dist/types/src/app/components/form.d.ts +7 -1
- package/dist/types/src/app/components/icon-button.d.ts +2 -2
- package/dist/types/src/app/components/icon.d.ts +1 -1
- package/dist/types/src/app/components/inline-code.d.ts +3 -0
- package/dist/types/src/app/components/inline-link.d.ts +1 -0
- package/dist/types/src/app/components/input.d.ts +1 -0
- package/dist/types/src/app/components/menu.d.ts +1 -0
- package/dist/types/src/app/components/nav-group.d.ts +2 -2
- package/dist/types/src/app/components/nav-item.d.ts +1 -1
- package/dist/types/src/app/components/pagination.d.ts +1 -0
- package/dist/types/src/app/components/popover.d.ts +1 -0
- package/dist/types/src/app/components/progress.d.ts +1 -0
- package/dist/types/src/app/components/radio.d.ts +1 -0
- package/dist/types/src/app/components/skeleton.d.ts +1 -0
- package/dist/types/src/app/components/slider.d.ts +1 -0
- package/dist/types/src/app/components/spinner.d.ts +1 -0
- package/dist/types/src/app/components/stack.d.ts +1 -1
- package/dist/types/src/app/components/stat.d.ts +1 -0
- package/dist/types/src/app/components/status-list-item.d.ts +1 -0
- package/dist/types/src/app/components/status-tile.d.ts +1 -0
- package/dist/types/src/app/components/surface.d.ts +1 -1
- package/dist/types/src/app/components/table.d.ts +1 -0
- package/dist/types/src/app/components/tabs.d.ts +6 -0
- package/dist/types/src/app/components/tag.d.ts +1 -0
- package/dist/types/src/app/components/textarea.d.ts +1 -0
- package/dist/types/src/app/components/toast.d.ts +1 -0
- package/dist/types/src/app/components/toggle.d.ts +1 -0
- package/dist/types/src/app/context/TenantContext.d.ts +20 -6
- package/dist/types/src/app/context/index.d.ts +7 -7
- package/dist/types/src/app/design-system/generated-token-refs.d.ts +13 -2
- package/dist/types/src/app/design-system/generated-token-values.d.ts +3 -3
- package/dist/types/src/app/design-system/theme.d.ts +1 -1
- package/dist/types/src/app/design-system/tokens.d.ts +2 -2
- package/dist/types/src/app/hooks/useHdsMotion.d.ts +16 -0
- package/dist/types/src/app/hooks/useReducedMotion.d.ts +1 -0
- package/dist/types/src/app/layouts/HdsSystemDocLayout.d.ts +1 -1
- package/dist/types/src/app/lib/hds-search.d.ts +1 -1
- package/dist/types/src/brand/index.d.ts +1 -1
- package/dist/types/src/form/index.d.ts +3 -3
- package/dist/types/src/index.d.ts +253 -118
- package/dist/types/src/lib/env.d.ts +31 -0
- package/dist/types/src/lib/manifest-entry.d.ts +1 -1
- package/dist/types/src/scroll/index.d.ts +2 -2
- package/dist/variables.css +56 -34
- package/hirobius.tokens.json +200 -65
- package/package.json +56 -17
- package/public/hds-manifest.json +1575 -696
- /package/{LICENSE/main.tsx → LICENSE} +0 -0
package/NOTICE.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# License notice
|
|
2
|
+
|
|
3
|
+
`@hirobius/design-system` is not under a single license.
|
|
4
|
+
|
|
5
|
+
- **HDS code** (components, compiled JavaScript, types, CSS, and token files): MIT. See [LICENSE](LICENSE).
|
|
6
|
+
- **Satoshi** (weights 500 and 700, by Indian Type Foundry, distributed through [Fontshare](https://www.fontshare.com/fonts/satoshi)): ITF Free Font License.
|
|
7
|
+
- **Geist Mono** (weight 400, by Vercel, [source](https://github.com/vercel/geist-font)): SIL Open Font License 1.1.
|
|
8
|
+
|
|
9
|
+
Both fonts are embedded as base64 `@font-face` data in `dist/tokens.css` and `dist/styles.css`. The MIT license does not cover them; each font keeps its own license. `dist/variables.css` embeds no fonts.
|
package/README.md
CHANGED
|
@@ -1,32 +1,27 @@
|
|
|
1
1
|
# Hirobius Design System
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
>
|
|
21
|
-
> **To take it off the shelf:** restore the `pull_request`/`push` triggers in
|
|
22
|
-
> `.github/workflows/{chromatic,release}.yml`, resume from `main`, and pick work
|
|
23
|
-
> from #80.
|
|
24
|
-
>
|
|
25
|
-
> **One human step (credential-gated, not automatable):** optionally run `npm
|
|
26
|
-
deprecate "@hirobius/design-system@<=0.12.0" "Frozen — see the repo README"` to
|
|
27
|
-
> flag the package as paused for npm browsers. It does not break installs.
|
|
3
|
+
A publishable React + TypeScript component library backed by a governed design-token pipeline, published to npm as `@hirobius/design-system`.
|
|
4
|
+
|
|
5
|
+
<!--
|
|
6
|
+
PLACEHOLDER — ADRIAN TO WRITE (hds front-door PR).
|
|
7
|
+
If you want the README to mention the July–September 2026 pause, put one or
|
|
8
|
+
two sentences here in your own words, then delete this comment. Leaving the
|
|
9
|
+
comment in place publishes nothing. Do not restore the old status line this
|
|
10
|
+
PR removed: CI, release, and Chromatic triggers were restored in #204.
|
|
11
|
+
-->
|
|
12
|
+
|
|
13
|
+
<!-- auto:start:front-door-counts -->
|
|
14
|
+
|
|
15
|
+
- **108** public component modules, exported from `src/index.ts`
|
|
16
|
+
- **362** DTCG tokens in `hirobius.tokens.json`, compiled to CSS variables and TypeScript constants
|
|
17
|
+
- **447** Storybook stories in **113** story files, reviewed visually in Chromatic
|
|
18
|
+
|
|
19
|
+
<!-- auto:end:front-door-counts -->
|
|
28
20
|
|
|
29
|
-
|
|
21
|
+
- Theming through four root attributes and CSS variables (theme, density, brand, font) that need no JavaScript
|
|
22
|
+
- Deterministic gates in git hooks and CI: typecheck, zero-warning ESLint, token validity and contrast, Vitest unit and contract tests, bundle budgets, a consumer smoke build, and a Storybook build
|
|
23
|
+
|
|
24
|
+
The counts are generated from source by `pnpm readme:counts`, which `pnpm tokens` also runs. `scripts/__tests__/front-door.test.mjs` fails if this README claims more than the source has.
|
|
30
25
|
|
|
31
26
|
## Using the published package
|
|
32
27
|
|
|
@@ -104,27 +99,43 @@ import { HdsThemeProvider } from '@hirobius/design-system';
|
|
|
104
99
|
</HdsThemeProvider>;
|
|
105
100
|
```
|
|
106
101
|
|
|
102
|
+
## Figma ↔ code
|
|
103
|
+
|
|
104
|
+
Code is the source of truth, and sync runs one way, from code to Figma. What exists today:
|
|
105
|
+
|
|
106
|
+
- **Tokens → Figma model:** `pnpm figma:model` projects `hirobius.tokens.json` into `figma/model.json` — the Primitives, Semantic (Light/Dark), Component, Role, Brand and Density collections, plus text and effect styles. Light and Dark keep their own values.
|
|
107
|
+
- **Model → Figma file:** `pnpm figma:push` writes the upsert scripts that apply that model to a Figma file, and `pnpm figma:native-import` writes DTCG files for Figma's own Variables ▸ Import. Both are run by hand — no workflow pushes to Figma. The runbook is [`figma/README.md`](figma/README.md).
|
|
108
|
+
- **Figma → repo:** `pnpm figma:snapshot --ingest` records the file's state in `figma/snapshot.json`, and `pnpm check:figma-drift` compares the model against that committed snapshot. A hand edit in Figma is drift, not a source change.
|
|
109
|
+
- **Legacy export:** `pnpm figma-variables` still writes the older plugin and REST export files, now projected from the same model.
|
|
110
|
+
- **Components → Code Connect:** the v2 templates live in the repo, but no Code Connect mapping is published, so Dev Mode shows no snippets. Publishing Code Connect needs a Figma Organization plan.
|
|
111
|
+
|
|
112
|
+
What each Figma plan allows, and the Pro-plan architecture this follows, are in [ADR-025](docs/adr/025-figma-sync-pro-architecture.md).
|
|
113
|
+
|
|
107
114
|
## Developing this repo
|
|
108
115
|
|
|
109
116
|
```bash
|
|
110
117
|
pnpm install
|
|
111
|
-
|
|
118
|
+
# Generated data files are gitignored; create them once (the same step CI runs):
|
|
119
|
+
node scripts/generate-manifest.mjs && node scripts/generate-component-api.mjs && node scripts/enrich-manifest.mjs && node scripts/sync-icons.mjs && node scripts/audit-tokens.mjs --full
|
|
120
|
+
pnpm storybook # component workbench on http://localhost:6006
|
|
112
121
|
```
|
|
113
122
|
|
|
114
123
|
Core verification commands:
|
|
115
124
|
|
|
116
125
|
```bash
|
|
117
126
|
pnpm typecheck
|
|
118
|
-
pnpm
|
|
119
|
-
pnpm
|
|
127
|
+
pnpm lint
|
|
128
|
+
pnpm exec vitest run # unit + contract tests, as the pre-push hook and CI run them
|
|
129
|
+
pnpm tokens:verify
|
|
120
130
|
pnpm check:size
|
|
131
|
+
pnpm build-storybook
|
|
121
132
|
```
|
|
122
133
|
|
|
123
134
|
## Architecture
|
|
124
135
|
|
|
125
136
|
HDS is built around three structural rules:
|
|
126
137
|
|
|
127
|
-
- **Strict semantics** — public surfaces prefer system primitives such as `
|
|
138
|
+
- **Strict semantics** — public surfaces prefer system primitives such as `Stack`, `Grid`, `Surface`, and `TextLockup` instead of raw layout divs or ad hoc CSS.
|
|
128
139
|
- **Polymorphism** — primitives preserve semantic HTML while staying composable through governed APIs such as `forwardRef`, `as`, and layout slots.
|
|
129
140
|
- **12-column grid** — page structure follows a consistent editorial grid: readable center columns, intentional breakout zones, and explicit `gap` ownership rather than one-off spacing math.
|
|
130
141
|
|
|
@@ -136,6 +147,63 @@ Source-of-truth files:
|
|
|
136
147
|
- `DESIGN.md` — lean visual spec for agents and engineers.
|
|
137
148
|
- `DESIGN-HANDOFF.md` — verbose visual mirror for handoff and review.
|
|
138
149
|
|
|
150
|
+
<!-- design-links:start (generated by `pnpm figma:links`; edit the @figma JSDoc tag, not this section) -->
|
|
151
|
+
|
|
152
|
+
## Design ↔ Code links
|
|
153
|
+
|
|
154
|
+
Each component has one Figma source: `figmaUrl` in `public/hds-manifest.json`, which `pnpm manifest:generate` sets from the `@figma` tag in the component JSDoc. `pnpm figma:links` keeps this table current and Storybook reads the same field (`parameters.design`). The Figma-side links (dev resources and component descriptions) exist only once someone runs their steps in [`figma/README.md`](figma/README.md).
|
|
155
|
+
|
|
156
|
+
**44 of 139** components link a Figma node.
|
|
157
|
+
|
|
158
|
+
| Component | Figma node | Story | Source |
|
|
159
|
+
| ------------------ | -------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
|
160
|
+
| `Alert` | [33:34](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=33-34) | [alert.stories.tsx](src/stories/alert.stories.tsx) | [alert.tsx](src/app/components/alert.tsx) |
|
|
161
|
+
| `Avatar` | [34:18](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=34-18) | [avatar.stories.tsx](src/stories/avatar.stories.tsx) | [avatar.tsx](src/app/components/avatar.tsx) |
|
|
162
|
+
| `Badge` | [31:15](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=31-15) | [badge.stories.tsx](src/stories/badge.stories.tsx) | [badge.tsx](src/app/components/badge.tsx) |
|
|
163
|
+
| `Breadcrumb` | [86:159](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=86-159) | [breadcrumb.stories.tsx](src/stories/breadcrumb.stories.tsx) | [breadcrumb.tsx](src/app/components/breadcrumb.tsx) |
|
|
164
|
+
| `Button` | [28:138](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=28-138) | [button.stories.tsx](src/stories/button.stories.tsx) | [button.tsx](src/app/components/button.tsx) |
|
|
165
|
+
| `Callout` | [88:85](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-85) | [callout.stories.tsx](src/stories/callout.stories.tsx) | [callout.tsx](src/app/components/callout.tsx) |
|
|
166
|
+
| `Card` | [39:11](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=39-11) | [card.stories.tsx](src/stories/card.stories.tsx) | [card.tsx](src/app/components/card.tsx) |
|
|
167
|
+
| `CodeBlock` | [89:154](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=89-154) | [code-block.stories.tsx](src/stories/code-block.stories.tsx) | [code-block.tsx](src/app/components/code-block.tsx) |
|
|
168
|
+
| `Combobox` | [82:237](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=82-237) | [combobox.stories.tsx](src/stories/combobox.stories.tsx) | [combobox.tsx](src/app/components/combobox.tsx) |
|
|
169
|
+
| `Dialog` | [93:27](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=93-27) | [dialog.stories.tsx](src/stories/dialog.stories.tsx) | [dialog.tsx](src/app/components/dialog.tsx) |
|
|
170
|
+
| `Disclosure` | [88:453](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-453) | [disclosure.stories.tsx](src/stories/disclosure.stories.tsx) | [disclosure.tsx](src/app/components/disclosure.tsx) |
|
|
171
|
+
| `Divider` | [89:26](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=89-26) | [divider.stories.tsx](src/stories/divider.stories.tsx) | [divider.tsx](src/app/components/divider.tsx) |
|
|
172
|
+
| `EmptyState` | [88:352](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-352) | [empty-state.stories.tsx](src/stories/empty-state.stories.tsx) | [empty-state.tsx](src/app/components/empty-state.tsx) |
|
|
173
|
+
| `Field` | [85:81](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=85-81) | [field.stories.tsx](src/stories/field.stories.tsx) | [field.tsx](src/app/components/field.tsx) |
|
|
174
|
+
| `Form` | [85:94](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=85-94) | [form.stories.tsx](src/stories/form.stories.tsx) | [form.tsx](src/app/components/form.tsx) |
|
|
175
|
+
| `HdsCheckbox` | [35:29](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=35-29) | [checkbox.stories.tsx](src/stories/checkbox.stories.tsx) | [checkbox.tsx](src/app/components/checkbox.tsx) |
|
|
176
|
+
| `HdsRadio` | [36:17](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=36-17) | [radio.stories.tsx](src/stories/radio.stories.tsx) | [radio.tsx](src/app/components/radio.tsx) |
|
|
177
|
+
| `HdsSelect` | [82:49](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=82-49) | [select.stories.tsx](src/stories/select.stories.tsx) | [select.tsx](src/app/components/select.tsx) |
|
|
178
|
+
| `HdsSlider` | [82:265](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=82-265) | [slider.stories.tsx](src/stories/slider.stories.tsx) | [slider.tsx](src/app/components/slider.tsx) |
|
|
179
|
+
| `HdsToggle` | [37:19](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=37-19) | [toggle.stories.tsx](src/stories/toggle.stories.tsx) | [toggle.tsx](src/app/components/toggle.tsx) |
|
|
180
|
+
| `IconButton` | [40:39](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=40-39) | [icon-button.stories.tsx](src/stories/icon-button.stories.tsx) | [icon-button.tsx](src/app/components/icon-button.tsx) |
|
|
181
|
+
| `InlineCode` | [89:155](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=89-155) | [inline-code.stories.tsx](src/stories/inline-code.stories.tsx) | [inline-code.tsx](src/app/components/inline-code.tsx) |
|
|
182
|
+
| `InlineLink` | [89:161](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=89-161) | [inline-link.stories.tsx](src/stories/inline-link.stories.tsx) | [inline-link.tsx](src/app/components/inline-link.tsx) |
|
|
183
|
+
| `Input` | [38:20](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=38-20) | [input.stories.tsx](src/stories/input.stories.tsx) | [input.tsx](src/app/components/input.tsx) |
|
|
184
|
+
| `Menu` | [93:59](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=93-59) | [menu.stories.tsx](src/stories/menu.stories.tsx) | [menu.tsx](src/app/components/menu.tsx) |
|
|
185
|
+
| `NavGroup` | [86:304](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=86-304) | [nav-group.stories.tsx](src/stories/nav-group.stories.tsx) | [nav-group.tsx](src/app/components/nav-group.tsx) |
|
|
186
|
+
| `NavItem` | [86:258](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=86-258) | [nav-item.stories.tsx](src/stories/nav-item.stories.tsx) | [nav-item.tsx](src/app/components/nav-item.tsx) |
|
|
187
|
+
| `Pagination` | [86:194](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=86-194) | [pagination.stories.tsx](src/stories/pagination.stories.tsx) | [pagination.tsx](src/app/components/pagination.tsx) |
|
|
188
|
+
| `Popover` | [93:32](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=93-32) | [popover.stories.tsx](src/stories/popover.stories.tsx) | [popover.tsx](src/app/components/popover.tsx) |
|
|
189
|
+
| `Progress` | [88:91](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-91) | [progress.stories.tsx](src/stories/progress.stories.tsx) | [progress.tsx](src/app/components/progress.tsx) |
|
|
190
|
+
| `SegmentedControl` | [82:334](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=82-334) | [segmented-control.stories.tsx](src/stories/segmented-control.stories.tsx) | [segmented-control.tsx](src/app/components/segmented-control.tsx) |
|
|
191
|
+
| `SideNav` | [86:332](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=86-332) | [side-nav.stories.tsx](src/stories/side-nav.stories.tsx) | [side-nav.tsx](src/app/components/side-nav.tsx) |
|
|
192
|
+
| `Skeleton` | [88:95](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-95) | [skeleton.stories.tsx](src/stories/skeleton.stories.tsx) | [skeleton.tsx](src/app/components/skeleton.tsx) |
|
|
193
|
+
| `Spinner` | [88:106](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-106) | [spinner.stories.tsx](src/stories/spinner.stories.tsx) | [spinner.tsx](src/app/components/spinner.tsx) |
|
|
194
|
+
| `Stat` | [88:247](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-247) | [stat.stories.tsx](src/stories/stat.stories.tsx) | [stat.tsx](src/app/components/stat.tsx) |
|
|
195
|
+
| `StatusListItem` | [88:350](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-350) | [status-list-item.stories.tsx](src/stories/status-list-item.stories.tsx) | [status-list-item.tsx](src/app/components/status-list-item.tsx) |
|
|
196
|
+
| `StatusTile` | [88:292](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=88-292) | [status-tile.stories.tsx](src/stories/status-tile.stories.tsx) | [status-tile.tsx](src/app/components/status-tile.tsx) |
|
|
197
|
+
| `StepperField` | [82:425](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=82-425) | [stepper-field.stories.tsx](src/stories/stepper-field.stories.tsx) | [stepper-field.tsx](src/app/components/stepper-field.tsx) |
|
|
198
|
+
| `Surface` | [89:27](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=89-27) | [surface.stories.tsx](src/stories/surface.stories.tsx) | [surface.tsx](src/app/components/surface.tsx) |
|
|
199
|
+
| `Table` | [89:300](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=89-300) | [table.stories.tsx](src/stories/table.stories.tsx) | [table.tsx](src/app/components/table.tsx) |
|
|
200
|
+
| `Tabs` | [86:89](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=86-89) | [tabs.stories.tsx](src/stories/tabs.stories.tsx) | [tabs.tsx](src/app/components/tabs.tsx) |
|
|
201
|
+
| `Tag` | [32:11](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=32-11) | [tag.stories.tsx](src/stories/tag.stories.tsx) | [tag.tsx](src/app/components/tag.tsx) |
|
|
202
|
+
| `Textarea` | [85:14](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=85-14) | [textarea.stories.tsx](src/stories/textarea.stories.tsx) | [textarea.tsx](src/app/components/textarea.tsx) |
|
|
203
|
+
| `ToastProvider` | [93:367](https://www.figma.com/design/c8MaVgwxOlxm4wr8wnH0Z4/HDS-Tokens-Components?node-id=93-367) | [toast.stories.tsx](src/stories/toast.stories.tsx) | [toast.tsx](src/app/components/toast.tsx) |
|
|
204
|
+
|
|
205
|
+
<!-- design-links:end -->
|
|
206
|
+
|
|
139
207
|
## Visual direction: Editorial Enterprise
|
|
140
208
|
|
|
141
209
|
The governing direction is "Editorial Enterprise" — enterprise rigor with editorial pacing. It favors sharp hierarchy, open whitespace, monochrome neutrals, and a single electric-blue accent. In practice:
|
|
@@ -147,26 +215,20 @@ The governing direction is "Editorial Enterprise" — enterprise rigor with edit
|
|
|
147
215
|
|
|
148
216
|
## Verification workflow
|
|
149
217
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
- `CLAUDE.md` is the operating contract — agent execution protocol, UI guardrails, required validation steps, and the self-heal requirement before a task is considered done.
|
|
153
|
-
- `scripts/self-heal.mjs` (`pnpm run heal`) runs the local static and smoke checks, captures failures, and gives a consistent path to fix type, layout, and runtime drift.
|
|
154
|
-
- The Playwright suite covers accessibility, layout integrity, collision detection, responsiveness, and visual regression, so changes that break containment, overlap, or responsive behavior fail automatically.
|
|
218
|
+
The gates are deterministic and need no browser or live site:
|
|
155
219
|
|
|
156
|
-
|
|
220
|
+
- **pre-commit** (`.husky/pre-commit`): secrets scan, Prettier on staged files, typecheck, zero-warning ESLint, and token validity and contrast.
|
|
221
|
+
- **pre-push** (`.husky/pre-push`): Vitest unit and contract tests, then the consumer smoke build (library build, subpath resolution, publint, consumer typecheck).
|
|
222
|
+
- **CI** (`.github/workflows/ci.yml`): typecheck, zero-warning ESLint, token validity and contrast, Vitest, and the consumer smoke build, plus bundle budgets and a Storybook build.
|
|
223
|
+
- **Visual review:** Storybook is the visual verification surface, and Chromatic (`.github/workflows/chromatic.yml`) runs it on pull requests. The earlier browser test suite drove a docs site that no longer exists; it is archived in `tests-archive/`.
|
|
157
224
|
|
|
158
|
-
|
|
159
|
-
2. Run `pnpm typecheck` and `pnpm run heal`.
|
|
160
|
-
3. Let Playwright catch runtime and visual regressions.
|
|
161
|
-
4. If self-healing fixes a regression, log the root cause and resolution.
|
|
162
|
-
5. Update the verification checklist and ship.
|
|
225
|
+
`CLAUDE.md` is the operating contract for agents working in this repo.
|
|
163
226
|
|
|
164
227
|
## Bundle and release hygiene
|
|
165
228
|
|
|
166
229
|
- `pnpm check:size` builds the library bundle and runs `size-limit`.
|
|
167
|
-
- `pnpm check:release` runs the full release gate (accessibility, responsive, collision, visual, and bundle-size checks).
|
|
168
230
|
|
|
169
|
-
Releases are cut with [Changesets](https://github.com/changesets/changesets)
|
|
231
|
+
Releases are cut with [Changesets](https://github.com/changesets/changesets). A pull request that changes the published package adds a changeset (`pnpm changeset:add`). On a push to `main`, `.github/workflows/release.yml` opens or updates a "Version Packages" PR, and merging that PR publishes the new version to public npm.
|
|
170
232
|
|
|
171
233
|
## Repository shape
|
|
172
234
|
|
|
@@ -190,3 +252,7 @@ public/
|
|
|
190
252
|
- `DESIGN-HANDOFF.md` — verbose visual mirror
|
|
191
253
|
- `TOKEN_GOVERNANCE.md` — token system rules
|
|
192
254
|
- `SYSTEMS_REGISTRY.md` — systems & guardrail registry
|
|
255
|
+
|
|
256
|
+
## License
|
|
257
|
+
|
|
258
|
+
The HDS code is MIT ([LICENSE](LICENSE)). The package CSS also embeds the Satoshi and Geist Mono fonts, which keep their own licenses and are not covered by MIT. See [NOTICE.md](NOTICE.md).
|
package/dist/contexts.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { useState as
|
|
3
|
-
import { F as
|
|
4
|
-
const
|
|
1
|
+
import { jsx as l, Fragment as I } from "react/jsx-runtime";
|
|
2
|
+
import { useState as i, useCallback as a, useEffect as s, useContext as E, createContext as S } from "react";
|
|
3
|
+
import { F as j, H as q, L as N, T as V, b as J, u as Q, a as U, c as W } from "./chunks/TokenDisplayContext-B3gxyQN7.js";
|
|
4
|
+
const x = ["system", "light", "dark"], d = "hds-theme-mode", P = "hds-theme", T = S({
|
|
5
5
|
isDark: !0,
|
|
6
6
|
toggleDark: () => {
|
|
7
7
|
},
|
|
@@ -14,22 +14,22 @@ const L = ["system", "light", "dark"], m = "hds-theme-mode", x = "hds-theme", _
|
|
|
14
14
|
setDensity: () => {
|
|
15
15
|
}
|
|
16
16
|
});
|
|
17
|
-
function
|
|
17
|
+
function y() {
|
|
18
18
|
try {
|
|
19
|
-
const t = localStorage.getItem(
|
|
20
|
-
if (t &&
|
|
19
|
+
const t = localStorage.getItem(d);
|
|
20
|
+
if (t && x.includes(t)) return t;
|
|
21
21
|
} catch {
|
|
22
22
|
}
|
|
23
23
|
return "system";
|
|
24
24
|
}
|
|
25
|
-
function
|
|
25
|
+
function L() {
|
|
26
26
|
var t;
|
|
27
27
|
return typeof window > "u" ? !1 : !!((t = window.matchMedia) != null && t.call(window, "(prefers-color-scheme: dark)").matches);
|
|
28
28
|
}
|
|
29
|
-
function
|
|
30
|
-
return t === "dark" ? !0 : t === "light" ? !1 :
|
|
29
|
+
function D(t) {
|
|
30
|
+
return t === "dark" ? !0 : t === "light" ? !1 : L();
|
|
31
31
|
}
|
|
32
|
-
function
|
|
32
|
+
function C() {
|
|
33
33
|
try {
|
|
34
34
|
const t = localStorage.getItem("hds-density");
|
|
35
35
|
if (t === "compact" || t === "comfortable") return t;
|
|
@@ -38,100 +38,102 @@ function N() {
|
|
|
38
38
|
return "comfortable";
|
|
39
39
|
}
|
|
40
40
|
function F({ children: t }) {
|
|
41
|
-
const [n,
|
|
41
|
+
const [n, f] = i(y), [r, u] = i(() => D(y())), [c, h] = i(C), g = a((e) => {
|
|
42
42
|
const o = e ? "dark" : "light";
|
|
43
43
|
try {
|
|
44
|
-
localStorage.setItem(
|
|
44
|
+
localStorage.setItem(P, o);
|
|
45
45
|
} catch {
|
|
46
46
|
}
|
|
47
47
|
document.documentElement.setAttribute("data-theme", o), document.documentElement.classList.toggle("dark", e);
|
|
48
48
|
}, []);
|
|
49
|
-
|
|
49
|
+
s(() => {
|
|
50
50
|
try {
|
|
51
51
|
localStorage.setItem("hds-density", c);
|
|
52
52
|
} catch {
|
|
53
53
|
}
|
|
54
54
|
document.documentElement.setAttribute("data-density", c);
|
|
55
|
-
}, [c]),
|
|
56
|
-
|
|
57
|
-
}, [r,
|
|
55
|
+
}, [c]), s(() => {
|
|
56
|
+
g(r);
|
|
57
|
+
}, [r, g]), s(() => {
|
|
58
58
|
if (n !== "system" || typeof window > "u" || !window.matchMedia) return;
|
|
59
59
|
const e = window.matchMedia("(prefers-color-scheme: dark)"), o = () => {
|
|
60
|
-
|
|
60
|
+
u(e.matches);
|
|
61
61
|
};
|
|
62
62
|
return e.addEventListener("change", o), () => {
|
|
63
63
|
e.removeEventListener("change", o);
|
|
64
64
|
};
|
|
65
65
|
}, [n]);
|
|
66
|
-
const
|
|
66
|
+
const b = a(() => {
|
|
67
67
|
const e = !r, o = e ? "dark" : "light";
|
|
68
|
-
|
|
68
|
+
f(o), u(e);
|
|
69
69
|
try {
|
|
70
|
-
localStorage.setItem(
|
|
70
|
+
localStorage.setItem(d, o);
|
|
71
71
|
} catch {
|
|
72
72
|
}
|
|
73
|
-
}, [r]),
|
|
74
|
-
|
|
73
|
+
}, [r]), A = a((e) => {
|
|
74
|
+
f(e), u(D(e));
|
|
75
75
|
try {
|
|
76
|
-
localStorage.setItem(
|
|
76
|
+
localStorage.setItem(d, e);
|
|
77
77
|
} catch {
|
|
78
78
|
}
|
|
79
|
-
}, []),
|
|
79
|
+
}, []), w = a(
|
|
80
80
|
() => h((e) => e === "comfortable" ? "compact" : "comfortable"),
|
|
81
81
|
[]
|
|
82
|
-
),
|
|
83
|
-
return /* @__PURE__ */
|
|
84
|
-
|
|
82
|
+
), M = a((e) => h(e), []);
|
|
83
|
+
return /* @__PURE__ */ l(
|
|
84
|
+
T.Provider,
|
|
85
85
|
{
|
|
86
|
-
value: { isDark: r, toggleDark:
|
|
86
|
+
value: { isDark: r, toggleDark: b, mode: n, setMode: A, density: c, toggleDensity: w, setDensity: M },
|
|
87
87
|
children: t
|
|
88
88
|
}
|
|
89
89
|
);
|
|
90
90
|
}
|
|
91
|
-
function
|
|
92
|
-
return
|
|
91
|
+
function O() {
|
|
92
|
+
return E(T);
|
|
93
93
|
}
|
|
94
|
-
const
|
|
95
|
-
function
|
|
96
|
-
for (const n of
|
|
94
|
+
const k = S({ tenantSlug: null }), v = ["data-brand", "data-tenant"];
|
|
95
|
+
function m(t) {
|
|
96
|
+
for (const n of v) document.documentElement.setAttribute(n, t);
|
|
97
97
|
}
|
|
98
|
-
function
|
|
99
|
-
for (const t of
|
|
98
|
+
function p() {
|
|
99
|
+
for (const t of v) document.documentElement.removeAttribute(t);
|
|
100
100
|
}
|
|
101
|
-
function
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
function B({
|
|
102
|
+
children: t,
|
|
103
|
+
slug: n = null
|
|
104
|
+
}) {
|
|
105
|
+
return s(() => {
|
|
104
106
|
if (n)
|
|
105
|
-
return
|
|
106
|
-
}, [n]), /* @__PURE__ */
|
|
107
|
+
return m(n), () => p();
|
|
108
|
+
}, [n]), /* @__PURE__ */ l(k.Provider, { value: { tenantSlug: n }, children: t });
|
|
107
109
|
}
|
|
108
|
-
function
|
|
109
|
-
return
|
|
110
|
+
function H() {
|
|
111
|
+
return E(k);
|
|
110
112
|
}
|
|
111
|
-
function
|
|
112
|
-
|
|
113
|
+
function z(t) {
|
|
114
|
+
s(() => {
|
|
113
115
|
const n = document.documentElement.getAttribute("data-brand");
|
|
114
|
-
return
|
|
115
|
-
n !== null ?
|
|
116
|
+
return m(t), () => {
|
|
117
|
+
n !== null ? m(n) : p();
|
|
116
118
|
};
|
|
117
119
|
}, [t]);
|
|
118
120
|
}
|
|
119
|
-
function
|
|
120
|
-
return /* @__PURE__ */
|
|
121
|
+
function G({ children: t }) {
|
|
122
|
+
return /* @__PURE__ */ l(I, { children: t });
|
|
121
123
|
}
|
|
122
124
|
export {
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
G as FontProvider,
|
|
126
|
+
j as FreezeState,
|
|
127
|
+
q as HdsRouterProvider,
|
|
128
|
+
N as LanguageProvider,
|
|
129
|
+
B as TenantProvider,
|
|
128
130
|
F as ThemeProvider,
|
|
129
|
-
|
|
131
|
+
V as TokenDisplayProvider,
|
|
130
132
|
J as useFrozenState,
|
|
131
133
|
Q as useHdsRouter,
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
134
|
+
U as useLanguage,
|
|
135
|
+
H as useTenant,
|
|
136
|
+
z as useTenantOnDocument,
|
|
137
|
+
O as useTheme,
|
|
138
|
+
W as useTokenDisplay
|
|
137
139
|
};
|