@hirobius/design-system 0.22.0 → 0.23.1

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 (67) hide show
  1. package/AGENTS.md +11 -1
  2. package/CHANGELOG.md +101 -0
  3. package/CONSUMING.md +3 -3
  4. package/DESIGN.md +26 -26
  5. package/NOTICE.md +4 -4
  6. package/README.md +23 -14
  7. package/UPGRADING.md +35 -1
  8. package/dist/chunks/{empty-state-DNoThgfV.js → empty-state-ChC_xZfg.js} +109 -92
  9. package/dist/chunks/{form-By82qZcC.js → form-zCZ_B83I.js} +16 -16
  10. package/dist/css-contract.json +1 -0
  11. package/dist/fonts/ibm-plex-mono-400.woff2 +0 -0
  12. package/dist/fonts/ibm-plex-mono-LICENSE.txt +93 -0
  13. package/dist/fonts/plus-jakarta-sans-400.woff2 +0 -0
  14. package/dist/fonts/plus-jakarta-sans-500.woff2 +0 -0
  15. package/dist/fonts/plus-jakarta-sans-700.woff2 +0 -0
  16. package/dist/fonts/plus-jakarta-sans-LICENSE.txt +22 -0
  17. package/dist/fonts.css +19 -19
  18. package/dist/form.js +1 -1
  19. package/dist/hirobius-ui.js +1263 -1190
  20. package/dist/manifest.js +5 -4
  21. package/dist/patterns.js +164 -162
  22. package/dist/styles.css +1 -1
  23. package/dist/tokens.css +1 -1
  24. package/dist/tokens.js +16 -3
  25. package/dist/types/src/app/components/asset-img.d.ts +1 -0
  26. package/dist/types/src/app/components/button.d.ts +1 -1
  27. package/dist/types/src/app/components/callout.d.ts +2 -1
  28. package/dist/types/src/app/components/card.d.ts +5 -3
  29. package/dist/types/src/app/components/code-block.d.ts +1 -0
  30. package/dist/types/src/app/components/combobox.d.ts +1 -1
  31. package/dist/types/src/app/components/data-table-section.d.ts +1 -0
  32. package/dist/types/src/app/components/destructive-section.d.ts +1 -0
  33. package/dist/types/src/app/components/divider.d.ts +1 -1
  34. package/dist/types/src/app/components/error-pattern.d.ts +1 -0
  35. package/dist/types/src/app/components/form-actions.d.ts +1 -0
  36. package/dist/types/src/app/components/form.d.ts +1 -0
  37. package/dist/types/src/app/components/grid.d.ts +1 -1
  38. package/dist/types/src/app/components/icon.d.ts +1 -1
  39. package/dist/types/src/app/components/metric-tiles.d.ts +3 -0
  40. package/dist/types/src/app/components/page-header.d.ts +2 -0
  41. package/dist/types/src/app/components/page.d.ts +1 -0
  42. package/dist/types/src/app/components/reveal.d.ts +1 -0
  43. package/dist/types/src/app/components/stack.d.ts +1 -1
  44. package/dist/types/src/app/components/tabs.d.ts +3 -1
  45. package/dist/types/src/app/context/hds-theme.d.ts +1 -1
  46. package/dist/types/src/app/design-system/generated-token-refs.d.ts +13 -0
  47. package/dist/types/src/app/design-system/generated-token-values.d.ts +16 -3
  48. package/dist/types/src/app/hooks/useInteractionState.d.ts +7 -1
  49. package/dist/types/src/index.d.ts +47 -0
  50. package/dist/variables.css +35 -24
  51. package/docs/CONSUMING.md +5 -5
  52. package/hirobius.tokens.json +91 -44
  53. package/llms.txt +29 -7
  54. package/package.json +12 -7
  55. package/public/hds-manifest.json +277 -119
  56. package/public/llms/components.txt +1 -1
  57. package/public/llms-full.txt +56 -34
  58. package/public/llms.txt +29 -7
  59. package/src/app/data/component-api.json +53 -18
  60. package/upgrade/index.json +15 -1
  61. package/upgrade/releases/0.23.0.json +259 -0
  62. package/upgrade/releases/0.23.1.json +108 -0
  63. package/upgrade/schema.json +114 -1
  64. package/dist/fonts/geist-mono-400.woff2 +0 -0
  65. package/dist/fonts/satoshi-400.woff2 +0 -0
  66. package/dist/fonts/satoshi-500.woff2 +0 -0
  67. package/dist/fonts/satoshi-700.woff2 +0 -0
package/AGENTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTS.md — @hirobius/design-system
2
2
 
3
- <!-- Generated by scripts/generate-agents-md.mjs from mcp/guide.mjs and src/app/data/component-api.json. Do not hand-edit above the repo-notes marker: pnpm agents:generate -->
3
+ <!-- Generated by scripts/generate-agents-md.mjs from mcp/guide.mjs, src/app/data/component-api.json and content/docs/voice.mdx. Do not hand-edit above the repo-notes marker: pnpm agents:generate -->
4
4
 
5
5
  For agents building UI with `@hirobius/design-system`. Read this first. It settles the choices the rest of the docs leave open, so two agents given the same screen build it the same way.
6
6
 
@@ -79,6 +79,16 @@ One answer per need. Use the components after the arrow; what follows "Not:" is
79
79
  - Every control has an accessible name: fields take `label`, a repeated row action takes an `aria-label` naming its row.
80
80
  - Section headings come from the pattern that owns the section (`title` props). Do not add a `Text` heading the screen does not ask for.
81
81
 
82
+ ## Voice
83
+
84
+ How these docs speak. Every page, and every agent writing for HDS, follows it. Source: `content/docs/voice.mdx` (published at `/docs/voice`).
85
+
86
+ - Use plain words a reader already knows. Name a thing by what it does, not by how it is built.
87
+ - Keep sentences short, one idea each.
88
+ - Tell the reader what to do. Leave out brand adjectives.
89
+ - Keep maintainer references off public pages: issue and ADR numbers, script names, internal counts.
90
+ - Don't use: "systems-first".
91
+
82
92
  ## Finish with the lint plugin
83
93
 
84
94
  The ESLint plugin ships in this package. Pass its `recommended` rules before you report done:
package/CHANGELOG.md CHANGED
@@ -1,5 +1,106 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.23.1
4
+
5
+ ### Upgrade
6
+
7
+ ```sh
8
+ npx @hirobius/design-system@latest upgrade
9
+ ```
10
+
11
+ - Looks different: The scoped HDS font variable now names Plus Jakarta Sans first instead of Satoshi.
12
+ - Looks different: Display and title text now renders in Plus Jakarta Sans instead of Satoshi.
13
+ - Looks different: Body, UI and caption text now renders in Plus Jakarta Sans instead of Satoshi.
14
+ - Looks different: fonts.css no longer declares Satoshi 400; it declares Plus Jakarta Sans 400 instead, so drop any font-family: Satoshi of your own.
15
+ - And 2 more: see [UPGRADING.md](https://github.com/hirobius/hds/blob/main/UPGRADING.md#0231).
16
+
17
+ ### Patch Changes
18
+
19
+ - d907e73: CONSUMING.md points agents at the docs site (https://hirobius-hds-components.vercel.app/llms.txt), which now serves the llms files, the manifest, DESIGN.md and component-api.json.
20
+ - 29af78f: feat(brand): the primary and display typeface is now Plus Jakarta Sans.
21
+
22
+ Satoshi's license (the Fontshare FF EULA) does not allow the font files to be redistributed, so HDS could not keep shipping them in the package or a public repo. Plus Jakarta Sans (Tokotype, SIL Open Font License 1.1) replaces it in the same three weights: 400 body, 500 UI and captions, 700 display and titles.
23
+ - `primitive.typography.family.primary` and `.display` now start with `"Plus Jakarta Sans"`, with the same system fallback stack.
24
+ - `@hirobius/design-system/fonts.css` now declares Plus Jakarta Sans 400/500/700, as Latin-subset woff2 files of about 15 KB each (Satoshi's were about 26 KB). The OFL license text ships beside the fonts in `dist/fonts/`.
25
+ - `package.json` `license` is now `MIT AND OFL-1.1`, since every bundled font is OFL.
26
+ - `ch`-based widths read a little wider in Figma, because the "0" advance is 0.732em instead of 0.683em.
27
+
28
+ Visual-only, with no API changes. If you import `fonts.css`, the new face loads with nothing else to do.
29
+
30
+ ## 0.23.0
31
+
32
+ ### Upgrade
33
+
34
+ ```sh
35
+ npx @hirobius/design-system@latest upgrade
36
+ ```
37
+
38
+ - Looks different: Accent-intent text and icons (such as links) now render in a dark apple green instead of a dark neutral.
39
+ - Looks different: Hovered accent text now shifts to a darker apple green instead of a darker neutral.
40
+ - Looks different: The accent fill on hover is now a deeper apple green instead of a dark neutral.
41
+ - Looks different: The accent fill while pressed is now a darker apple green instead of a near-black neutral.
42
+ - And 10 more: see [UPGRADING.md](https://github.com/hirobius/hds/blob/main/UPGRADING.md#0230).
43
+
44
+ ### Minor Changes
45
+
46
+ - 8edd926: The code font is now IBM Plex Mono 400 (OFL-1.1), replacing Geist Mono. The `primitive.typography.family.mono` token value changes (names unchanged), `fonts.css` ships `ibm-plex-mono-400.woff2` instead of `geist-mono-400.woff2`, and the 13px mono role is unchanged. Figma needs the IBM Plex Mono font installed before `figma:push`.
47
+
48
+ ### Patch Changes
49
+
50
+ - 66cb4e2: fix(a11y): Tier-2 accessibility fixes across the primitives.
51
+ - **Radio / Checkbox / Toggle** show a keyboard focus ring only on `:focus-visible` (not on mouse click), and focus is no longer masked by hover (focus now outranks hover in `useInteractionState`).
52
+ - **Input / Textarea / FormField** no longer point `aria-describedby` at a description that isn't rendered (error replaces helper); `Input`'s `loading` uses `readOnly` + `aria-busy` instead of `disabled`, so a search-as-you-type field keeps focus.
53
+ - **Select** renders a real `<label htmlFor>` wired to the trigger, so clicking the label focuses it.
54
+ - **Combobox** keyboard: options are not tab stops, Arrow keys skip disabled options and scroll the active one into view, option ids are index-based (no break on special chars), and the active index resets on open / option change.
55
+ - **Tabs** focus ring is `ring-inset` so it isn't clipped by the scroll container.
56
+ - **InlineLink** only treats a single-leading-slash path as an internal router link (not `//host`); `mailto:`/`tel:`/`#hash` are plain same-tab links; external links keep `target=_blank` + a visually-hidden "(opens in new tab)"; the internal branch gains `hds-focus`.
57
+
58
+ - c88ab39: fix(feedback): unify Alert + Callout on one tinted-fill tone language.
59
+
60
+ The two feedback components carried tone in opposite ways — Alert by a tinted fill (`bg-feedback-bg-*`), Callout by a 3px colored left stripe — reading as two systems, and the stripe was the lone >1px colored side-rule anti-pattern left in the set. DESIGN.md also still claimed Alert carries tone "by left-border color, not by tinted fills", which the shipped Alert already contradicted.
61
+ - **Callout** now uses the same tinted feedback fill as Alert (rounded, no stripe); `accent` (not a feedback state) takes a neutral `bg-muted` fill. It stays distinct from Alert by role — no icon, no status role, optional `italic` — not by mechanism.
62
+ - **Alert** unchanged (already fill-based).
63
+ - **DESIGN.md** (via build-design-md.mjs) corrected: tone is carried by a tinted feedback fill, not a left-border stripe.
64
+
65
+ Visual change to Callout; no API change.
66
+
67
+ - c88ab39: feat(brand): set the default accent to a bright apple green.
68
+
69
+ The base brand accent moves from a neutral (monochrome) to a bright apple green. A
70
+ new `primitive.color.apple` scale backs it, kept distinct from the emerald `green`
71
+ feedback/success scale so an accent and a success state never read as the same hue.
72
+ - `semantic.accent.{rest,hover,pressed,content,contentHover,subtle}`, `semantic.color.surface.accent`/`accentSubtle`, `semantic.color.content.accent`, and `semantic.color.border.accent` now resolve through `primitive.color.apple.*`.
73
+ - `semantic.color.content.onAccent` flips to a dark neutral (`neutral.900`) in both modes, since a bright accent fill needs dark text to clear AA — `content.onAccent / surface.accent` is 7.2:1 light / 9.3:1 dark.
74
+ - Per-tenant accents are unchanged: `accent-lilac` and `concrete-creations` set their own accent (and their own white `onAccent`); `brutalist-demo` inherits the new green base.
75
+
76
+ Visual-only; no API changes. The accent remains a single per-tenant knob — consumers who set their own accent overlay are unaffected.
77
+
78
+ - c88ab39: docs(card): reconcile DESIGN.md with the shipped borderless-default Card.
79
+
80
+ The Card Anatomy / elevation tables said a resting card carries a 1px border, contradicting the 12d-3 outline rule (and DESIGN.md's own "don't default to outlined cards" guidance) that made the default `Card` variant borderless, with a resting border opt-in via `bordered` / a feedback `tone` / `accent`. Updated the elevation-role table, the component table, and the (mandatory) Card Anatomy Border row to document the borderless default + opt-in border, and corrected the stale card.tsx module docstring that claimed depth comes from a resting border. No component behavior change.
81
+
82
+ - 0a6b830: fix(components): five Tier-1 component bugs from the audit.
83
+ - **Select** no longer crashes the page when `options` is empty (async list mid-load) or when `value` matches no option; the trigger label degrades to the field name.
84
+ - **Combobox** can now be closed by clicking its trigger again (the trigger was a `Popover.Anchor`, so Radix dismissed on pointerdown and the onClick reopened).
85
+ - **Button `asChild`** now enforces the disabled/loading contract on a slotted element (e.g. an `<a>`): non-interactive (`pointer-events-none`, `tabIndex=-1`) and dimmed, since native `disabled:` utilities can't apply to it.
86
+ - **AssetImg** and **Avatar** recover when `src` changes to a working image after a prior load error, instead of staying stuck on the fallback.
87
+
88
+ - b43d6bc: The package now ships `dist/css-contract.json` (hds#449): for each stylesheet it exports, every CSS custom property with its value per context (`:root`, dark, compact, each `[data-brand]`, each `@media`), the class names, the `@font-face` entries and the `@layer` names, plus `publicClasses` (the classes you may write yourself: `hds-focus` and the `static.css` set, also listed in `public/hds-manifest.json`). The upgrade ledger reads it, so from the next release a removed CSS variable or `hds-*` class needs a breaking upgrade step, and a changed token value a look step that `npx @hirobius/design-system upgrade` reports where your code uses it. Nothing changes in the stylesheets themselves.
89
+ - c88ab39: fix(disabled): unify the disabled state onto per-component tokens, off the global opacity multiplier.
90
+
91
+ DESIGN.md forbids a global disabled-state rule (opacity multiplier); disabled presentation must be governed per-component through its dedicated disabled tokens. Button, Combobox, Input, Textarea, Tabs and Tag were dimming with `disabled:opacity-50`/`opacity-70` — now they use `content.disabled` text (and a neutral `bg-muted` surface where a fill is needed), matching Checkbox/Radio/Toggle/SegmentedControl.
92
+ - **Button** — disabled is now `bg-muted` + `content-disabled` text for every variant AND tone (a disabled danger/success/… button now reads as disabled instead of fully coloured). Note: the pre-existing `component-button-primary-bgDisabled`/`textDisabled` tokens resolve to `accentSubtle` + `content-onAccent`, which render near-white-on-near-white under the neutral accent, so the component uses the neutral `bg-muted` pair instead (token fix tracked separately).
93
+ - **Input / Textarea** — drop the redundant `disabled:opacity-70`; keep `bg-muted`, switch disabled text to `content-disabled`.
94
+ - **Combobox / Tabs / Tag** — `disabled:opacity-50` → `content-disabled` text.
95
+
96
+ Visual-only; no API changes.
97
+
98
+ - 2d2a874: Plain-language `@usage` lines for Button, Grid, Surface, Divider, Icon, Stack and every pattern. Docs pages now open with that line instead of the code note.
99
+ - 8016b7a: AGENTS.md and llms.txt carry a Voice section generated from the Voice page (`content/docs/voice.mdx`, published at `/docs/voice`): how HDS docs and agents writing for HDS should speak, and the words not to use.
100
+ - c88ab39: fix(polish): Table cell alignment + caption spacing, and reduced-motion guards (docs-site rubric findings).
101
+ - **Table**: data cells now `items-center` (was `items-start`), so a badge/status slot lines up on a shared vertical center with its text siblings instead of floating above them; the caption/description block gains a token gap so it no longer touches the table's header band.
102
+ - **Reduced motion**: the Button and Input loading spinners (`animate-spin`) and the Progress bar's width transition now carry a `motion-reduce:` guard, matching Spinner/Progress's existing policy, so they stop animating under `prefers-reduced-motion`.
103
+
3
104
  ## 0.22.0
4
105
 
5
106
  ### Upgrade
package/CONSUMING.md CHANGED
@@ -29,7 +29,7 @@ version keeps the `LucideIcon` type identical).
29
29
  ```tsx
30
30
  import { Button, Card, Dialog } from '@hirobius/design-system';
31
31
  import '@hirobius/design-system/tokens.css'; // required — design tokens as CSS vars
32
- import '@hirobius/design-system/fonts.css'; // optional — the HDS brand fonts (Satoshi, Geist Mono)
32
+ import '@hirobius/design-system/fonts.css'; // optional — the HDS brand fonts (Plus Jakarta Sans, IBM Plex Mono)
33
33
 
34
34
  export function Example() {
35
35
  return (
@@ -45,7 +45,7 @@ Available subpaths:
45
45
  | Import | What |
46
46
  | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
47
47
  | `@hirobius/design-system` | The 43-component core set ([README → What belongs in the system](README.md#what-belongs-in-the-system)), the rest of the allow-list and the templates; the `pattern` tier is only in `/patterns` |
48
- | `@hirobius/design-system/fonts.css` | Optional brand fonts (Satoshi, Geist Mono); woff2 files ship in the package, relative URLs, `font-display: swap` |
48
+ | `@hirobius/design-system/fonts.css` | Optional brand fonts (Plus Jakarta Sans, IBM Plex Mono); woff2 files ship in the package, relative URLs, `font-display: swap` |
49
49
  | `@hirobius/design-system/tokens.css` | Token CSS variables (import once at app root) |
50
50
  | `@hirobius/design-system/tokens` | Token values as TS constants |
51
51
  | `@hirobius/design-system/cn` | `cn()` class-merge helper |
@@ -103,7 +103,7 @@ them without network access. Under `node_modules/@hirobius/design-system/`:
103
103
  - `DESIGN.md` - the lean visual spec
104
104
  - `src/app/data/component-api.json` - full prop reference
105
105
 
106
- The same files are served at <https://hirobius-design-system.vercel.app/llms.txt>
106
+ The same files are served at <https://hirobius-hds-components.vercel.app/llms.txt>
107
107
  (and `/llms-full.txt`, `/llms/components.txt`, `/DESIGN.md`, `/component-api.json`).
108
108
 
109
109
  ## 3. Receiving updates
package/DESIGN.md CHANGED
@@ -6,14 +6,14 @@ A machine- and human-readable specification of the Hirobius Design System for AI
6
6
 
7
7
  ## Overview
8
8
 
9
- Hirobius is a clean, systems-first visual language that bridges digital precision and physical fabrication through a high-contrast monochromatic palette and a single accent that each tenant sets — neutral by default (#208). Its personality is disciplined, tactile, and quietly technical: structure is explicit, motion is purposeful, and visual noise is stripped away. Whitespace is treated as material, not leftover space, so every screen should feel deliberate, breathable, and exact.
9
+ Hirobius is a clean, systems-first visual language that bridges digital precision and physical fabrication through a high-contrast monochromatic neutral palette and a single accent that each tenant sets — a bright apple green by default. Its personality is disciplined, tactile, and quietly technical: structure is explicit, motion is purposeful, and visual noise is stripped away. Whitespace is treated as material, not leftover space, so every screen should feel deliberate, breathable, and exact.
10
10
 
11
11
  ## Colors
12
12
 
13
13
  <!-- auto:start:colors -->
14
14
  **One accent — one neutral system.**
15
15
 
16
- - **Accent** (`#111111`): CTAs, active states, selected focus rings, and the single brand accent. `semantic.accent.rest` — a per-tenant knob, not a fixed hue (#208).
16
+ - **Accent** (`#66B239`): CTAs, active states, selected focus rings, and the single brand accent. `semantic.accent.rest` — a per-tenant knob, not a fixed hue (#208).
17
17
  - **Neutral**: backgrounds, surfaces, borders, text. True monochromatic — `primitive.color.neutral.50` through `950`. Use `semantic.color.surface.*`, `semantic.color.content.*`, `semantic.color.border.*`; never reach directly for primitives in components.
18
18
  - **Feedback — Error** (`#B91C1C`): destructive confirms, error banners, validation failures. `semantic.color.feedback.error`.
19
19
  - **Feedback — Success** (`#047857`): positive confirmations, completed states. `semantic.color.feedback.success`.
@@ -28,9 +28,9 @@ Feedback hues are never decorative; do not use them as accents. Light and dark m
28
28
  <!-- auto:start:typography -->
29
29
  HDS ships three typefaces — each with a distinct and exclusive role:
30
30
 
31
- - **Display / Heading font**: Satoshi. Bound exclusively to the `display` and `title` styles. Never used for body copy or UI labels.
32
- - **Body / UI font**: Satoshi. All prose, labels, small text, captions, and UI copy.
33
- - **Mono font**: Geist Mono. Reserved for tokens, code, technical callouts, and metric readouts.
31
+ - **Display / Heading font**: Plus Jakarta Sans. Bound exclusively to the `display` and `title` styles. Never used for body copy or UI labels.
32
+ - **Body / UI font**: Plus Jakarta Sans. All prose, labels, small text, captions, and UI copy.
33
+ - **Mono font**: IBM Plex Mono. Reserved for tokens, code, technical callouts, and metric readouts.
34
34
 
35
35
  Weights declared: `400` regular, `500` medium, `700` bold. Heading styles (display · title) use `700` bold; body, UI, and caption use `400` regular / `500` medium.
36
36
 
@@ -92,14 +92,14 @@ Depth is communicated through 4 elevation roles bundled by `semantic.elevation.*
92
92
 
93
93
  ### Elevation roles
94
94
 
95
- | Surface | Role token | Background | Shadow | Border |
96
- | -------------------------------------- | ----------------------------- | ----------------- | ----------------- | ------------------- |
97
- | Card / panel resting | `semantic.elevation.flat` | `surface.page` | none | `border.subtle` 1px |
98
- | Card / panel lifted (interactive only) | `semantic.elevation.raised` | `surface.raised` | `shadow.subtle` | none |
99
- | Popover / dropdown / tooltip | `semantic.elevation.floating` | `surface.raised` | `shadow.floating` | none |
100
- | Dialog / sheet / modal | `semantic.elevation.overlay` | `surface.overlay` | `shadow.overlay` | none |
95
+ | Surface | Role token | Background | Shadow | Border |
96
+ | -------------------------------------- | ----------------------------- | ----------------- | ----------------- | -------------------------------------------------------- |
97
+ | Card / panel resting | `semantic.elevation.flat` | `surface.page` | none | none by default; opt-in 1px (`bordered`/`tone`/`accent`) |
98
+ | Card / panel lifted (interactive only) | `semantic.elevation.raised` | `surface.raised` | `shadow.subtle` | none |
99
+ | Popover / dropdown / tooltip | `semantic.elevation.floating` | `surface.raised` | `shadow.floating` | none |
100
+ | Dialog / sheet / modal | `semantic.elevation.overlay` | `surface.overlay` | `shadow.overlay` | none |
101
101
 
102
- Cards default to `flat`. They lift to `raised` only on interactive hover or when explicitly elevated above siblings. Never combine `raised` with a border — depth is one mechanism (border OR shadow), not both stacked.
102
+ Cards default to `flat`. They lift to `raised` only on interactive hover or when explicitly elevated above siblings. Never combine `raised` with a border — depth is one mechanism (border OR shadow), not both stacked. The default `Card` variant is **borderless** (12d-3 outline rule: repeated outlined cards crowd a layout, so the edge is not the default) — a resting 1px border is **opt-in** via `bordered`, a feedback `tone`, or the `accent` variant (`border.default` / feedback color / `border.accent` respectively). Rely on whitespace, dividers, and rails for grouping; reach for `bordered` only for a genuinely discrete standalone object.
103
103
 
104
104
  Overlays (Dialog, AlertDialog, Menu, Popover, Select, Tooltip) portal into the nearest `data-hds` scope, so they inherit its theme (for example `<div data-hds data-theme="dark">`); pass `container` on the Content part to override.
105
105
 
@@ -142,9 +142,9 @@ Default most interactive feedback to `productive` (150ms, decelerate). Reserve `
142
142
  | --- | --- | --- | --- |
143
143
  | **Buttons** (`Button`) | `8px` (`semantic.radius.action`) | default · hover · focus · active · disabled · loading | Three variants: primary (accent-filled), secondary (outline), tertiary (ghost). Primary uses `semantic.accent.*` ramp per state. Pressed is a 5% `semantic.color.state.pressed.overlay` wash over the fill (`role.pressed-overlay`: black in light, white in dark), not a brightness filter. Icon-only buttons (`iconOnly`) follow the same token surface. Icon-only actions use `Button iconOnly` with a `label` and an `Icon` from `@hirobius/design-system/icons` in `iconLeft`. |
144
144
  | **Inputs** (`Input`) | `8px` (`semantic.radius.action`) | default · focus · filled · error · disabled · loading | Border-driven treatment; no filled background by default. Focus uses `semantic.color.border.accent` plus a 2px outline offset. Error swaps to `component.input.borderError`. |
145
- | **Cards** (`Card`) | `12px` (`rounded-lg`, role radius + 4px) | default · hover (optional parallax) · pressed (when interactive) | Cards default to `elevation.flat` (1px border `border.subtle`, no shadow). Interactive cards lift to `elevation.raised` (shadow.subtle, no border) on hover. Bind via `semantic.elevation.{role}` — never raw box-shadow values. Radius: `rounded-lg` (role radius + 4 px, follows the tenant knob) — never a hard-coded value. Padding: `var(--semantic-space-surface-padding)`. Title: `heading3`. Meta: `caption` + `var(--semantic-color-content-secondary)`. Hover (interactive): `scale(1.02)` transform + lift to raised. Never: gradients, glow, frosted glass, tinted surfaces, decorative overlays, or inner shadows. |
145
+ | **Cards** (`Card`) | `12px` (`rounded-lg`, role radius + 4px) | default · hover (optional parallax) · pressed (when interactive) | Cards default to `elevation.flat` (borderless by default; an opt-in 1px border via `bordered`/`tone`/`accent`, no shadow). Interactive cards lift to `elevation.raised` (shadow.subtle, no border) on hover. Bind via `semantic.elevation.{role}` — never raw box-shadow values. Radius: `rounded-lg` (role radius + 4 px, follows the tenant knob) — never a hard-coded value. Padding: `var(--semantic-space-surface-padding)`. Title: `heading3`. Meta: `caption` + `var(--semantic-color-content-secondary)`. Hover (interactive): `scale(1.02)` transform + lift to raised. Never: gradients, glow, frosted glass, tinted surfaces, decorative overlays, or inner shadows. |
146
146
  | **Badges** (`Badge`) | `8px` (`primitive.radius.4`) | neutral · accent · feedback (error/success/warning/info) | Single-line status markers. Feedback colors come from `semantic.color.feedback.*`. Never used as decorative chrome. |
147
- | **Alerts** (`Alert`) | `8px` (via `hds.borderRadius.4`) | info · success · warning · error | Inline banner pattern with icon + message + optional action. Tone is carried by left-border color, not by tinted fills. |
147
+ | **Alerts** (`Alert`) | `8px` (via `hds.borderRadius.4`) | info · success · warning · error | Inline banner pattern with icon + message + optional action. Tone is carried by a tinted feedback fill (`bg-feedback-bg-*`, matching Badge), NOT a left-border stripe. Callout shares this fill language and differs only by role (no icon, no status role, optional italic). |
148
148
  | **Disclosures** (`Disclosure`) | `8px` (`hds.borderRadius.action`) | collapsed · expanded · hover · focus | Accordion primitive. Expansion uses `semantic.motion.productive`; no spring bounce. Dividers follow `semantic.color.border.subtle`. |
149
149
  | **Toggles** (`Toggle`) | `full` (pill track + circular thumb) | off · on · focus · disabled | Accent-filled track in the on state; neutral track otherwise. Track + thumb transitions share `semantic.motion.productive`. |
150
150
  | **Segmented Control** (`SegmentedControl`) | Outer `12px` · inner segments `8px` | rest · hover · selected · disabled | Selected segment fills with the accent; unselected segments are transparent. Use for 2–5 mutually exclusive options; beyond that, prefer `Select`. |
@@ -156,16 +156,16 @@ See `public/hds-manifest.json` and `src/app/data/component-api.json` for the ful
156
156
 
157
157
  Every HDS card surface must conform to this anatomy exactly. No creative interpretation is permitted on any of these properties.
158
158
 
159
- | Property | Required value | Forbidden |
160
- | ------------------------ | -------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
161
- | Background | `var(--semantic-color-surface-raised)` | Any gradient, tinted fill, or custom color |
162
- | Border | `1px solid var(--semantic-color-border-default)` | `box-shadow` as an elevation substitute |
163
- | Border radius | `rounded-lg` (`role.radius` + 4 px: 12 px by default, follows the tenant) | `var(--component-card-radius)`, `rounded-full`, or any hard-coded value |
164
- | Padding | `var(--semantic-space-component-padding)` or `<HdsSurface padding="component">` | Raw pixel values or ad hoc insets |
165
- | Shadow | Resting cards: none (`elevation.flat`). Interactive lifted state: `shadow.subtle` via `elevation.raised` | Raw `box-shadow` values, `drop-shadow`, glow, or any depth effect not bound to a role token |
166
- | Title | `hds.typeStyles.title` / `<Text variant="title">` | Any other type style for the primary card heading |
167
- | Subtitle / meta | `hds.typeStyles.caption` + `var(--semantic-color-content-secondary)` | Primary content color or body size for secondary text |
168
- | Hover (interactive only) | `transform: scale(1.02)` | Background fill change, border color shift, or opacity fade on hover |
159
+ | Property | Required value | Forbidden |
160
+ | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
161
+ | Background | `var(--semantic-color-surface-raised)` | Any gradient, tinted fill, or custom color |
162
+ | Border | Default variant: **borderless**. Opt-in (`bordered`/`tone`/`accent`): 1px solid the matching token (`border.default` / feedback color / `border.accent`). Never border + shadow together. | `box-shadow` as an elevation substitute; a border on the default variant (use `bordered`) |
163
+ | Border radius | `rounded-lg` (`role.radius` + 4 px: 12 px by default, follows the tenant) | `var(--component-card-radius)`, `rounded-full`, or any hard-coded value |
164
+ | Padding | `var(--semantic-space-component-padding)` or `<HdsSurface padding="component">` | Raw pixel values or ad hoc insets |
165
+ | Shadow | Resting cards: none (`elevation.flat`). Interactive lifted state: `shadow.subtle` via `elevation.raised` | Raw `box-shadow` values, `drop-shadow`, glow, or any depth effect not bound to a role token |
166
+ | Title | `hds.typeStyles.title` / `<Text variant="title">` | Any other type style for the primary card heading |
167
+ | Subtitle / meta | `hds.typeStyles.caption` + `var(--semantic-color-content-secondary)` | Primary content color or body size for secondary text |
168
+ | Hover (interactive only) | `transform: scale(1.02)` | Background fill change, border color shift, or opacity fade on hover |
169
169
 
170
170
  Never use on any card surface: gradient backgrounds, glow effects, frosted glass (`backdrop-filter: blur`), decorative overlays, gradient borders, colored or tinted backgrounds, inner shadows, patterned fills, shimmer or noise effects.
171
171
 
@@ -209,7 +209,7 @@ Three more needs are props on an existing component, not components of their own
209
209
  ## Do's and Don'ts
210
210
 
211
211
  - Don't invent new corner behavior for interactive controls; buttons, inputs, disclosures, and similar action surfaces should follow the shared action radius (`semantic.radius.action`).
212
- - Don't introduce additional accent hues; Hirobius uses exactly one accent, resolved from `semantic.accent.rest`, over a true monochromatic neutral system. The accent is a per-tenant knob (#208) and defaults to neutral — read the token, never assume a hue.
212
+ - Don't introduce additional accent hues; Hirobius uses exactly one accent, resolved from `semantic.accent.rest`, over a true monochromatic neutral system. The accent is a per-tenant knob (#208) and defaults to a bright apple green — read the token, never assume a hue.
213
213
  - Don't tint neutrals warm or cool; greys should remain genuinely neutral and high-contrast.
214
214
  - Don't reach for shadow values directly — bind to a `semantic.elevation.*` role so surface + shadow + border stay paired. Cards default to `flat` (border, no shadow). Popovers/tooltips/dropdowns use `floating`. Dialogs/sheets use `overlay`.
215
215
  - Don't hardcode colors, spacing, radius, or typography values when governed tokens already exist.
@@ -228,6 +228,6 @@ Unresolved rules that the live repo cannot yet answer confidently are tracked in
228
228
  <!-- auto:start:build-meta -->
229
229
  ---
230
230
 
231
- > Generated from `hirobius.tokens.json` (389 tokens) and `public/hds-manifest.json` by `scripts/build-design-md.mjs`.
231
+ > Generated from `hirobius.tokens.json` (400 tokens) and `public/hds-manifest.json` by `scripts/build-design-md.mjs`.
232
232
  > Hand-edit `DESIGN.source.md`; this file (`DESIGN.md`) is overwritten by `pnpm tokens`.
233
233
  <!-- auto:end:build-meta -->
package/NOTICE.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # License notice
2
2
 
3
- `@hirobius/design-system` is not under a single license.
3
+ `@hirobius/design-system` is under two licenses: MIT for the code, and the SIL Open Font License 1.1 for the bundled fonts.
4
4
 
5
5
  - **HDS code** (components, compiled JavaScript, types, CSS, and token files): MIT. See [LICENSE](LICENSE).
6
- - **Satoshi** (weights 400, 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.
6
+ - **Plus Jakarta Sans** (weights 400, 500 and 700, by Tokotype, [source](https://github.com/tokotype/PlusJakartaSans), Latin subset): SIL Open Font License 1.1.
7
+ - **IBM Plex Mono** (weight 400, by IBM, [source](https://github.com/IBM/plex)): SIL Open Font License 1.1.
8
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.
9
+ Both fonts ship as woff2 files in `dist/fonts/`, declared by the opt-in `dist/fonts.css`; each font's license text ships beside it as `dist/fonts/<family>-LICENSE.txt`. The MIT license does not cover the fonts. `dist/tokens.css`, `dist/styles.css` and `dist/variables.css` embed no fonts.
package/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # Hirobius Design System
2
2
 
3
- [![CI](https://github.com/hirobius/hds/actions/workflows/ci.yml/badge.svg)](https://github.com/hirobius/hds/actions/workflows/ci.yml) [![npm](https://img.shields.io/npm/v/@hirobius/design-system)](https://www.npmjs.com/package/@hirobius/design-system) [![Storybook](https://img.shields.io/badge/Storybook-live-ff4785)](https://hirobius-design-system.vercel.app)
3
+ [![CI](https://github.com/hirobius/hds/actions/workflows/ci.yml/badge.svg)](https://github.com/hirobius/hds/actions/workflows/ci.yml) [![npm](https://img.shields.io/npm/v/@hirobius/design-system)](https://www.npmjs.com/package/@hirobius/design-system) [![Docs](https://img.shields.io/badge/Docs-live-000000)](https://hirobius-hds-components.vercel.app)
4
4
 
5
- React + TypeScript component library on a governed design-token pipeline. Live Storybook: **<https://hirobius-design-system.vercel.app>**
5
+ **A governed, token-first React design system.** Components plus the system
6
+ around them: a DTCG token pipeline (CSS variables + TypeScript constants),
7
+ quality gates in git hooks and CI, one-way Figma sync, and WCAG-checked contrast
8
+ and focus. Live docs: **<https://hirobius-hds-components.vercel.app>**
6
9
 
7
10
  ```bash
8
11
  pnpm add @hirobius/design-system
@@ -10,18 +13,23 @@ pnpm add @hirobius/design-system
10
13
 
11
14
  Upgrading: [UPGRADING.md](UPGRADING.md) lists what each release asks of you. From 0.22.0, `npx @hirobius/design-system@latest upgrade` does it for you.
12
15
 
13
- [![Buttons under the Brand and Theme dials: base and accent-lilac, light and dark](docs/images/storybook-brand-theme-dials.png)](https://hirobius-design-system.vercel.app)
16
+ [![Buttons under the Brand and Theme dials: base and accent-lilac, light and dark](docs/images/storybook-brand-theme-dials.png)](https://hirobius-hds-components.vercel.app)
14
17
 
15
18
  <!-- auto:start:front-door-counts -->
16
19
 
17
20
  - **53** public component modules, exported from `src/index.ts`
18
- - **389** DTCG tokens in `hirobius.tokens.json`, compiled to CSS variables and TypeScript constants
21
+ - **400** DTCG tokens in `hirobius.tokens.json`, compiled to CSS variables and TypeScript constants
19
22
  - **341** Storybook stories in **71** story files
20
23
 
21
24
  <!-- auto:end:front-door-counts -->
22
25
 
23
- - Theming through four root attributes and CSS variables (theme, density, brand, font) that need no JavaScript
24
- - 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
26
+ What the system includes:
27
+
28
+ - **Token pipeline.** DTCG tokens in `hirobius.tokens.json` compile to CSS variables and TypeScript constants through a validated alias chain, with AA-contrast gates in light and dark.
29
+ - **Gates with proof-of-firing.** Typecheck, zero-warning ESLint, token validity and contrast, Vitest unit and contract tests, bundle budgets, a consumer smoke build, and a Storybook build — run in git hooks and CI. Many gates carry a passing and a violating fixture that demonstrate the gate catches what it describes.
30
+ - **Upgrade path.** A release ledger and one consumer command: `npx @hirobius/design-system@latest upgrade`.
31
+ - **One-way Figma sync.** Code is the source of truth; tokens project into Figma, and `pnpm check:figma-drift` compares a committed snapshot against the model.
32
+ - **Theming without JavaScript.** Four root attributes — theme, density, brand, font — re-skin HDS descendants through CSS variables.
25
33
 
26
34
  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.
27
35
 
@@ -120,12 +128,12 @@ HDS theming is driven by root attributes + CSS variables, so it works with **zer
120
128
  JavaScript** — set them on any element (React, Astro, plain HTML) and every HDS
121
129
  descendant re-skins:
122
130
 
123
- | Dial | Attribute / var | Values | Default |
124
- | ------- | ---------------------------------------------- | --------------- | -------------------- |
125
- | theme | `data-theme` | `dark` | light (unset) |
126
- | density | `data-density` | `compact` | comfortable (unset) |
127
- | brand | `data-brand` (+ `data-tenant` alias) | overlay slug | base (unset) |
128
- | font | `--hds-font-family` / `--hds-font-family-mono` | any font-family | Satoshi / Geist Mono |
131
+ | Dial | Attribute / var | Values | Default |
132
+ | ------- | ---------------------------------------------- | --------------- | --------------------------------- |
133
+ | theme | `data-theme` | `dark` | light (unset) |
134
+ | density | `data-density` | `compact` | comfortable (unset) |
135
+ | brand | `data-brand` (+ `data-tenant` alias) | overlay slug | base (unset) |
136
+ | font | `--hds-font-family` / `--hds-font-family-mono` | any font-family | Plus Jakarta Sans / IBM Plex Mono |
129
137
 
130
138
  ```html
131
139
  <!-- zero-JS: static markup (e.g. an Astro layout) -->
@@ -212,12 +220,13 @@ What CI and the hooks check today, and nothing more:
212
220
  - **Lint:** `jsx-a11y` rules run inside ESLint with zero warnings allowed.
213
221
  - **Focus:** `scripts/check-focus-states.mjs` (`pnpm check:focus`) audits focus styles on interactive components. It runs in `pretest` under `pnpm test`, so in the pre-push hook and in CI, and passes with 0 violations.
214
222
  - **Storybook:** the `addon-a11y` panel shows axe results for each story while you review it. The gate is `scripts/check-storybook-axe.mjs`: CI scans every built story in light and dark, including the open Select and Combobox, and fails on serious or critical violations outside its allowlist (`scripts/axe-allowlist.json`). The allowlist has one entry: `aria-hidden-focus` on the open Select story, where Radix Select hides the page around its listbox while focus stays trapped inside it (hds#407).
223
+ - **Docs site:** `scripts/check-docs-axe.mjs` (`pnpm check:docs-axe`, after `pnpm docs:publish`) scans the live demo of every `/docs/components/*` and `/docs/patterns/*` page of the built docs site in light and dark with the same axe rules, scoped to the demo frame so the Fumadocs chrome does not count. CI runs it and fails on serious or critical violations outside `scripts/docs-axe-allowlist.json`, which is empty.
215
224
 
216
225
  Screen-reader output is checked by `tests/primitive-contracts/screen-reader.contract.test.tsx`, which runs in `pnpm test` and walks Dialog, Menu, Select, Combobox, Table and Alert with a virtual screen-reader (`@guidepup/virtual-screen-reader`) under jsdom, asserting the role, name and state phrases it reads and the alert's live-region announcement; it reads the jsdom accessibility tree, not what a desktop or mobile screen-reader says.
217
226
 
218
227
  ## Visual direction: Editorial Enterprise
219
228
 
220
- 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:
229
+ The governing direction is "Editorial Enterprise" — enterprise rigor with editorial pacing. It favors sharp hierarchy, open whitespace, monochrome neutrals, and a single tenant-set accent. In practice:
221
230
 
222
231
  - documentation reads like a designed publication, not a component dump
223
232
  - cards are used sparingly; whitespace, rails, dividers, and bands carry structure first
@@ -276,4 +285,4 @@ public/
276
285
 
277
286
  ## License
278
287
 
279
- 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).
288
+ The HDS code is MIT ([LICENSE](LICENSE)). The package CSS also embeds the Plus Jakarta Sans and IBM Plex Mono fonts, which keep their own licenses and are not covered by MIT. See [NOTICE.md](NOTICE.md).
package/UPGRADING.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Upgrading @hirobius/design-system
2
2
 
3
- This file only knows the releases up to the version you have installed, 0.22.0. For newer releases, run `npx @hirobius/design-system@latest upgrade`: it always fetches the newest steps.
3
+ This file only knows the releases up to the version you have installed, 0.23.1. For newer releases, run `npx @hirobius/design-system@latest upgrade`: it always fetches the newest steps.
4
4
 
5
5
  ## How to upgrade
6
6
 
@@ -10,6 +10,40 @@ npx @hirobius/design-system@latest upgrade
10
10
 
11
11
  It finds the version you have, moves you to the newest release, runs each release's codemods (Fixed for you) and lists what is left for you (Do by hand). It works from 0.16.0 on; from an older version, first reach 0.16.0 with the notes in CHANGELOG.md. MIGRATIONS.md has longer guides for the big releases.
12
12
 
13
+ ## 0.23.1
14
+
15
+ Released 2026-10-11 (patch). 6 that look different.
16
+
17
+ ### Looks different
18
+
19
+ - The scoped HDS font variable now names Plus Jakarta Sans first instead of Satoshi.
20
+ - Display and title text now renders in Plus Jakarta Sans instead of Satoshi.
21
+ - Body, UI and caption text now renders in Plus Jakarta Sans instead of Satoshi.
22
+ - fonts.css no longer declares Satoshi 400; it declares Plus Jakarta Sans 400 instead, so drop any font-family: Satoshi of your own.
23
+ - fonts.css no longer declares Satoshi 500; it declares Plus Jakarta Sans 500 instead, so drop any font-family: Satoshi of your own.
24
+ - fonts.css no longer declares Satoshi 700; it declares Plus Jakarta Sans 700 instead, so drop any font-family: Satoshi of your own.
25
+
26
+ ## 0.23.0
27
+
28
+ Released 2026-10-10 (minor). 14 that look different.
29
+
30
+ ### Looks different
31
+
32
+ - Accent-intent text and icons (such as links) now render in a dark apple green instead of a dark neutral.
33
+ - Hovered accent text now shifts to a darker apple green instead of a darker neutral.
34
+ - The accent fill on hover is now a deeper apple green instead of a dark neutral.
35
+ - The accent fill while pressed is now a darker apple green instead of a near-black neutral.
36
+ - Interactive accent fills at rest (primary buttons, selected controls) now render in a bright apple green instead of a dark neutral, paired with dark on-accent text.
37
+ - The low-emphasis accent tint (hover and selection backgrounds) is now a faint apple green instead of a neutral tint.
38
+ - Accent borders now render in apple green instead of a dark neutral.
39
+ - Accent-intent text and icons on page and card surfaces now render in a dark apple green instead of a neutral.
40
+ - Text and icons on accent fills are now a dark neutral instead of white, because the accent fill is a bright apple green that needs dark text for contrast.
41
+ - Accent background surfaces now render in a bright apple green instead of a dark neutral.
42
+ - Faint accent background surfaces are now a pale apple green instead of a neutral tint.
43
+ - Callout now renders as a tinted feedback fill (rounded, no left stripe) matching Alert, with the accent tone using a neutral muted fill.
44
+ - Code text now draws in IBM Plex Mono instead of Geist Mono, so if you preload or self-host geist-mono-400.woff2, point it at ibm-plex-mono-400.woff2 from fonts.css instead.
45
+ - Table data cells vertically center their content (badge/status slots no longer float above text) and the caption gains spacing above the table; loading spinners and the progress bar stop animating under prefers-reduced-motion.
46
+
13
47
  ## 0.22.0
14
48
 
15
49
  Released 2026-10-08 (minor). 3 changes to make by hand (1 breaking), 1 that looks different and 2 deprecations.