@nadicodeai/ui 8.0.1 → 8.2.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 (67) hide show
  1. package/LICENSES/SHADCN-HEATMAP-MIT.txt +21 -0
  2. package/NOTICE +9 -0
  3. package/dist/components/activity-calendar.d.ts +27 -0
  4. package/dist/components/activity-calendar.d.ts.map +1 -0
  5. package/dist/components/activity-calendar.js +56 -0
  6. package/dist/components/agent-orb.d.ts +22 -0
  7. package/dist/components/agent-orb.d.ts.map +1 -0
  8. package/dist/components/agent-orb.js +28 -0
  9. package/dist/components/chart-area-stacked.d.ts +1 -1
  10. package/dist/components/chart-area-stacked.d.ts.map +1 -1
  11. package/dist/components/chart-area-stacked.js +2 -2
  12. package/dist/components/chart-bar-multiple.d.ts +1 -1
  13. package/dist/components/chart-bar-multiple.d.ts.map +1 -1
  14. package/dist/components/chart-bar-multiple.js +2 -2
  15. package/dist/components/chart-bar-stacked.d.ts +1 -1
  16. package/dist/components/chart-bar-stacked.d.ts.map +1 -1
  17. package/dist/components/chart-bar-stacked.js +2 -2
  18. package/dist/components/chart-card.d.ts +24 -3
  19. package/dist/components/chart-card.d.ts.map +1 -1
  20. package/dist/components/chart-card.js +8 -3
  21. package/dist/components/heatmap/calendar-heatmap.d.ts +138 -0
  22. package/dist/components/heatmap/calendar-heatmap.d.ts.map +1 -0
  23. package/dist/components/heatmap/calendar-heatmap.js +449 -0
  24. package/dist/components/model-identity.d.ts +8 -0
  25. package/dist/components/model-identity.d.ts.map +1 -0
  26. package/dist/components/model-identity.js +8 -0
  27. package/dist/components/object-workspace.d.ts +36 -0
  28. package/dist/components/object-workspace.d.ts.map +1 -0
  29. package/dist/components/object-workspace.js +19 -0
  30. package/dist/components/progress.d.ts +2 -1
  31. package/dist/components/progress.d.ts.map +1 -1
  32. package/dist/components/progress.js +5 -4
  33. package/dist/components/settings-facts.d.ts +2 -1
  34. package/dist/components/settings-facts.d.ts.map +1 -1
  35. package/dist/components/settings-facts.js +6 -3
  36. package/dist/components/settings-section.d.ts +3 -1
  37. package/dist/components/settings-section.d.ts.map +1 -1
  38. package/dist/components/settings-section.js +2 -2
  39. package/dist/components/table-value.d.ts +7 -0
  40. package/dist/components/table-value.d.ts.map +1 -0
  41. package/dist/components/table-value.js +6 -0
  42. package/dist/components/table.d.ts +2 -1
  43. package/dist/components/table.d.ts.map +1 -1
  44. package/dist/components/table.js +4 -1
  45. package/dist/index.d.ts +5 -0
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +5 -0
  48. package/dist/internal/agent-orb-motion.d.ts +14 -0
  49. package/dist/internal/agent-orb-motion.d.ts.map +1 -0
  50. package/dist/internal/agent-orb-motion.js +120 -0
  51. package/dist/internal/agent-orb.d.ts +19 -0
  52. package/dist/internal/agent-orb.d.ts.map +1 -0
  53. package/dist/internal/agent-orb.js +151 -0
  54. package/dist/internal/object-identity-support.d.ts +6 -0
  55. package/dist/internal/object-identity-support.d.ts.map +1 -0
  56. package/dist/internal/object-identity-support.js +10 -0
  57. package/dist/lib/format-token-count.d.ts +4 -0
  58. package/dist/lib/format-token-count.d.ts.map +1 -0
  59. package/dist/lib/format-token-count.js +31 -0
  60. package/dist/styles/components.css +126 -0
  61. package/dist/styles/globals.css +4 -104
  62. package/docs/activity.md +3 -1
  63. package/docs/agent-orb.md +82 -0
  64. package/docs/agent-visual.md +5 -0
  65. package/docs/contract.md +49 -6
  66. package/docs/model-identity.md +18 -0
  67. package/package.json +8 -2
@@ -0,0 +1,126 @@
1
+ /*
2
+ * @nadicodeai/ui/components.css — what the components need from a stylesheet,
3
+ * and nothing that styles a page.
4
+ *
5
+ * `globals.css` owns an application: it imports Tailwind, the complete design
6
+ * system with its reset and base layer, and this file. A host that already
7
+ * runs Tailwind over base styles of its own cannot take it, because the reset
8
+ * and the base layer would restyle the host. Such a host takes this file
9
+ * instead, after its own `@import "tailwindcss"`:
10
+ *
11
+ * @import "@nadicodeai/design-system/css/host";
12
+ * @import "@nadicodeai/ui/components.css";
13
+ *
14
+ * It carries the three things without which a component renders unstyled: the
15
+ * `@source` lines that let the host's Tailwind see the components' class names
16
+ * (Tailwind never scans node_modules), the `nc-*` utilities those names use,
17
+ * and the few rules that belong to a component and not to a page.
18
+ *
19
+ * What the host must already have: the shadcn role names in its own theme
20
+ * (`--color-popover`, `--color-border`, `--color-muted-foreground`, …), mapped
21
+ * to whatever it likes. The components name those roles (`bg-popover`), and a
22
+ * host without them gets no CSS for those classes. The roles are the host's so
23
+ * that its theming, skins included, reaches our components unchanged.
24
+ */
25
+
26
+ /*
27
+ * The one glass material (DESIGN.md "Elevation & Depth"): floating chrome —
28
+ * menus, popovers, selects, comboboxes, the command palette, and bars — may
29
+ * carry it; content surfaces stay solid. Glass composites only over our own
30
+ * content, and its elevation falloff's edge ring stays its one separator.
31
+ * Declared as a utility so variant prefixes can gate it (navigation-menu's
32
+ * non-viewport popup). Reduced transparency falls back to the same solid
33
+ * surface at the same elevation.
34
+ */
35
+ @utility nc-glass {
36
+ background: color-mix(in srgb, var(--popover) var(--nc-material-glass-opacity), transparent);
37
+ backdrop-filter: blur(var(--nc-material-glass-blur)) saturate(var(--nc-material-glass-saturation));
38
+
39
+ @media (prefers-reduced-transparency: reduce) {
40
+ background: var(--popover);
41
+ backdrop-filter: none;
42
+ }
43
+ }
44
+
45
+ /*
46
+ * The four elevation rungs. Each utility paints the whole recipe of its rung
47
+ * from the generated --nc-elevation-* token, whose last layer is the rung's
48
+ * own optical ring in the current mode (design-system DESIGN.md
49
+ * "core.elevation"). An elevated surface therefore draws no second edge:
50
+ * never pair one of these with border-*, ring-*, or another box-shadow
51
+ * (`nadicodeai/no-elevated-edge` enforces it). Declared as utilities so
52
+ * variant prefixes can gate them.
53
+ */
54
+ @utility nc-elevation-resting {
55
+ box-shadow: var(--nc-elevation-resting);
56
+ }
57
+
58
+ @utility nc-elevation-raised {
59
+ box-shadow: var(--nc-elevation-raised);
60
+ }
61
+
62
+ @utility nc-elevation-floating {
63
+ box-shadow: var(--nc-elevation-floating);
64
+ }
65
+
66
+ @utility nc-elevation-modal {
67
+ box-shadow: var(--nc-elevation-modal);
68
+ }
69
+
70
+ /*
71
+ * The proxy focus outline: the one restatement of the canonical treatment
72
+ * above, for an element that carries the indicator on another element's
73
+ * behalf (the input group around its control, the OTP slot for the hidden
74
+ * input, the chart wrapper for its svg, the slider thumb). The call site adds
75
+ * the hue with outline-ring or outline-destructive and nothing else.
76
+ * Declared as a utility so variant prefixes can gate it, and so the style is
77
+ * literally `solid` rather than Tailwind's `--tw-outline-style`, which any
78
+ * outline-none or outline-hidden on the same element sets to `none` for good.
79
+ */
80
+ @utility nc-focus-outline {
81
+ outline-style: solid;
82
+ outline-width: var(--outline-width-focus);
83
+ outline-offset: var(--outline-offset-focus);
84
+ }
85
+
86
+ @layer components {
87
+ .nc-toast {
88
+ border: 0 !important;
89
+ }
90
+ }
91
+
92
+ /*
93
+ * The canonical design-system module owns raw --nc-* mode aliases, semantic
94
+ * roles, and their Tailwind utility bridge for both root and scoped `.dark`
95
+ * surfaces.
96
+ */
97
+
98
+ .toaster [data-sonner-toast][data-styled="true"] [data-description] {
99
+ color: var(--muted-foreground);
100
+ }
101
+
102
+ .toaster [data-sonner-toast][data-styled="true"] [data-button] {
103
+ background: var(--popover-foreground);
104
+ color: var(--popover);
105
+ }
106
+
107
+ .toaster [data-sonner-toast][data-styled="true"] [data-cancel] {
108
+ background: var(--muted);
109
+ color: var(--popover-foreground);
110
+ }
111
+
112
+ .toaster [data-sonner-toast][data-styled="true"] [data-close-button] {
113
+ background: var(--popover);
114
+ border-color: var(--border);
115
+ color: var(--popover-foreground);
116
+ }
117
+
118
+ .toaster [data-sonner-toast][data-styled="true"] [data-close-button]:hover {
119
+ background: var(--accent);
120
+ border-color: var(--border);
121
+ color: var(--accent-foreground);
122
+ }
123
+
124
+ @source "../components";
125
+ @source "../internal";
126
+ @source "../lib";
@@ -1,8 +1,9 @@
1
1
  /*
2
2
  * @nadicodeai/ui — Tailwind v4 + shadcn entry stylesheet.
3
3
  *
4
- * Tailwind and the complete design-system CSS module are composed here, behind
5
- * the package's one public stylesheet interface. The generated raw-token theme,
4
+ * Tailwind and the complete design-system CSS module are composed here, for an
5
+ * application this package styles whole. A host with base styles of its own
6
+ * takes `components.css`, which this file imports, and never this file. The generated raw-token theme,
6
7
  * :root/.dark semantic role maps, and Tailwind semantic bridge come from
7
8
  * DESIGN.md, so shadcn utilities (bg-background, text-foreground,
8
9
  * border-border, …) resolve to brand tokens through one generated owner.
@@ -19,6 +20,7 @@
19
20
  @import "@assistant-ui/react-markdown/styles/dot.css";
20
21
  @import "./shadcn.tailwind.css";
21
22
  @import "@nadicodeai/design-system/css";
23
+ @import "./components.css";
22
24
 
23
25
  /*
24
26
  * Tailwind v4's dark: variant defaults to an OS media query. Match shadcn's
@@ -76,105 +78,3 @@
76
78
  stroke-linejoin: round;
77
79
  }
78
80
  }
79
-
80
- /*
81
- * The one glass material (DESIGN.md "Elevation & Depth"): floating chrome —
82
- * menus, popovers, selects, comboboxes, the command palette, and bars — may
83
- * carry it; content surfaces stay solid. Glass composites only over our own
84
- * content, and its elevation falloff's edge ring stays its one separator.
85
- * Declared as a utility so variant prefixes can gate it (navigation-menu's
86
- * non-viewport popup). Reduced transparency falls back to the same solid
87
- * surface at the same elevation.
88
- */
89
- @utility nc-glass {
90
- background: color-mix(in srgb, var(--popover) var(--nc-material-glass-opacity), transparent);
91
- backdrop-filter: blur(var(--nc-material-glass-blur)) saturate(var(--nc-material-glass-saturation));
92
-
93
- @media (prefers-reduced-transparency: reduce) {
94
- background: var(--popover);
95
- backdrop-filter: none;
96
- }
97
- }
98
-
99
- /*
100
- * The four elevation rungs. Each utility paints the whole recipe of its rung
101
- * from the generated --nc-elevation-* token, whose last layer is the rung's
102
- * own optical ring in the current mode (design-system DESIGN.md
103
- * "core.elevation"). An elevated surface therefore draws no second edge:
104
- * never pair one of these with border-*, ring-*, or another box-shadow
105
- * (`nadicodeai/no-elevated-edge` enforces it). Declared as utilities so
106
- * variant prefixes can gate them.
107
- */
108
- @utility nc-elevation-resting {
109
- box-shadow: var(--nc-elevation-resting);
110
- }
111
-
112
- @utility nc-elevation-raised {
113
- box-shadow: var(--nc-elevation-raised);
114
- }
115
-
116
- @utility nc-elevation-floating {
117
- box-shadow: var(--nc-elevation-floating);
118
- }
119
-
120
- @utility nc-elevation-modal {
121
- box-shadow: var(--nc-elevation-modal);
122
- }
123
-
124
- /*
125
- * The proxy focus outline: the one restatement of the canonical treatment
126
- * above, for an element that carries the indicator on another element's
127
- * behalf (the input group around its control, the OTP slot for the hidden
128
- * input, the chart wrapper for its svg, the slider thumb). The call site adds
129
- * the hue with outline-ring or outline-destructive and nothing else.
130
- * Declared as a utility so variant prefixes can gate it, and so the style is
131
- * literally `solid` rather than Tailwind's `--tw-outline-style`, which any
132
- * outline-none or outline-hidden on the same element sets to `none` for good.
133
- */
134
- @utility nc-focus-outline {
135
- outline-style: solid;
136
- outline-width: var(--outline-width-focus);
137
- outline-offset: var(--outline-offset-focus);
138
- }
139
-
140
- @layer components {
141
- .nc-toast {
142
- border: 0 !important;
143
- }
144
- }
145
-
146
- /*
147
- * The canonical design-system module owns raw --nc-* mode aliases, semantic
148
- * roles, and their Tailwind utility bridge for both root and scoped `.dark`
149
- * surfaces.
150
- */
151
-
152
- .toaster [data-sonner-toast][data-styled="true"] [data-description] {
153
- color: var(--muted-foreground);
154
- }
155
-
156
- .toaster [data-sonner-toast][data-styled="true"] [data-button] {
157
- background: var(--popover-foreground);
158
- color: var(--popover);
159
- }
160
-
161
- .toaster [data-sonner-toast][data-styled="true"] [data-cancel] {
162
- background: var(--muted);
163
- color: var(--popover-foreground);
164
- }
165
-
166
- .toaster [data-sonner-toast][data-styled="true"] [data-close-button] {
167
- background: var(--popover);
168
- border-color: var(--border);
169
- color: var(--popover-foreground);
170
- }
171
-
172
- .toaster [data-sonner-toast][data-styled="true"] [data-close-button]:hover {
173
- background: var(--accent);
174
- border-color: var(--border);
175
- color: var(--accent-foreground);
176
- }
177
-
178
- @source "../components";
179
- @source "../internal";
180
- @source "../lib";
package/docs/activity.md CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  The system activity family has three motions. They describe ongoing system
4
4
  operations across the website, Portal and Nadia. They do not represent an
5
- Agent's identity, attention or personality.
5
+ Agent's identity, attention or personality. The separate [AgentOrb](agent-orb.md)
6
+ uses seven of the same upstream geometries for persistent identity, with one
7
+ chosen pigment instead of the system activity palette.
6
8
 
7
9
  | Activity | Use when | Library motion |
8
10
  | --- | --- | --- |
@@ -0,0 +1,82 @@
1
+ # Agent orbs
2
+
3
+ `AgentOrb` is the abstract Agent identity family requested on 2026-09-19:
4
+ seven structures from `thinking-orbs` 0.3.1, each painted in one configurable
5
+ colour. These are persistent appearance choices, not activity states. They
6
+ apply equally to Nadia and other Agents; this family assigns no face or
7
+ special character to Nadia. Existing Forma consumers are not migrated by
8
+ this component slice.
9
+
10
+ | Form | Structure | Upstream preset |
11
+ | --- | --- | --- |
12
+ | `ribbon` | Flowing dotted bands | `composing` |
13
+ | `lattice` | Rotating particle bands | `solving` |
14
+ | `orbit` | Particles on tilted orbits | `working` |
15
+ | `globe` | Dotted globe and scanning meridian | `searching` |
16
+ | `network` | Connected constellation | `connecting` |
17
+ | `braid` | Interwoven strands | `weaving` |
18
+ | `morph` | Changing geometric contour | `shaping` |
19
+
20
+ The form does not select a job, tools or runtime status. Do not switch it when
21
+ an Agent starts searching or solving. Applications own the persisted form,
22
+ colour, name and status; names beside avatars provide exact identification.
23
+
24
+ ## Component
25
+
26
+ ```tsx
27
+ import { AgentOrb } from "@nadicodeai/ui/components/agent-orb";
28
+
29
+ <AgentOrb form="ribbon" color="var(--nc-identity-cobalto)" size={32} label="Nadia" />;
30
+ ```
31
+
32
+ `form` is required. `color` accepts one CSS colour, including a customer-chosen
33
+ colour or a canonical token. Omit it to inherit text colour. This configurable
34
+ artwork is not a new palette for controls or status. Every particle and line
35
+ uses the same pigment; opacity, not another colour, creates depth. Working
36
+ releases occasional coloured flourishes; Done repeats the same arcs,
37
+ arrowheads, rings and sparkles in a short celebration around
38
+ that single-colour identity, using the existing chart and warning tokens. Choose a
39
+ colour visible on the intended background. A deliberately black pigment on a
40
+ black surface is not automatically recoloured.
41
+
42
+ Sizes are 20, 24, 32, 40, 64, 96 and 160 CSS pixels. Menu sizes through 32 use
43
+ the upstream compact density; larger sizes use its detailed profile. `paused`
44
+ holds the current frame and resumes without resetting the appearance. An
45
+ accessible image requires `label`; use `decorative` beside an existing name.
46
+ The component is Canvas 2D, not WebGL. It reuses the vendor's portable geometry
47
+ API because the stock React component only offers monochrome light/dark ink,
48
+ not a configurable pigment.
49
+
50
+ Motion is limited to 30 painted frames per second. Offscreen and hidden orbs
51
+ stop scheduling animation. Reduced motion freezes the current frame and is
52
+ observed live. Unmount removes the frame request and observers. DPR is capped
53
+ at two. Without Canvas 2D, the accessible name remains available.
54
+
55
+ `state` accepts idle, working, waiting, blocked, thinking and done. Geometry
56
+ and state gestures have separate clocks: slowing a gesture must not make the
57
+ idle form appear frozen. Each form has its own geometry pace, shared across
58
+ avatar sizes; Morph holds a contour for about 1.6 seconds and changes it over
59
+ one second at idle. Working and Thinking keep the form's base pace.
60
+ Waiting holds its pose; Blocked makes one gentle interrupted effort and stops.
61
+ V7 keeps the material free-standing and intact:
62
+ no gear, thought bubble, pause, exclamation mark or check is cut into the form.
63
+ Working and Thinking preserve the native geometry: do not stretch, flatten,
64
+ fold or emit copies of the orb to convey either state. Working uses one open,
65
+ tapered multicoloured ribbon passing behind and in front of the orb on a
66
+ 7.2-second loop. Thinking uses three persistent coloured dots above the orb,
67
+ with sequential opacity and slight size pulses on a 3.6-second loop.
68
+ The distinct symbols remain visible throughout both cycles. Done repeats
69
+ the ribbon in three celebratory sweeps and then rests. Changing `motionKey`
70
+ replays it. These exterior cues use the celebration palette; the body keeps
71
+ its configured pigment. Reduced motion holds both cues still.
72
+ No state has an enclosing circle. Keep a nearby status label where exact
73
+ state identification matters, including reduced motion and compact sizes.
74
+ Reduced motion holds the state pose and skips the celebration.
75
+
76
+ The [Portal Agent workspace](../../../apps/portal/src/components/agent-workspace/agent-workspace.tsx)
77
+ uses the shared component. Inspect its Agent list and detail views in the
78
+ running local Portal for compact and full-size appearances. Development
79
+ profiles provide example orb choices; their preview edits do not change
80
+ stored Agent records.
81
+
82
+ [Upstream library and presets](https://libraries.dev/orbs), MIT licensed.
@@ -1,5 +1,10 @@
1
1
  # Agent Visual System
2
2
 
3
+ Legacy API for existing consumers. New Agent workspace surfaces use
4
+ [AgentOrb](agent-orb.md) and the shared
5
+ [product language](../../design-system/PRODUCT_LANGUAGE.md#agent-section-contract).
6
+ The multicolour recipes below do not govern new Portal agent representations.
7
+
3
8
  The Agent visual is the decorative identity for a persistent Agent in Nadia.
4
9
  It is a living, multicolour metaball form whose recipe is assigned by Agent
5
10
  type. It does not represent status, capability, runtime activity, or work
package/docs/contract.md CHANGED
@@ -6,7 +6,7 @@ The normative invariants for the `@nadicodeai/ui` package: what may live here, h
6
6
 
7
7
  - **Token-only, no raw literals or shadow aliases.** Components style through semantic shadcn utilities (`bg-background`, `text-foreground`, `border-input`, and the rest), or a canonical generated design-system token when no standard role is precise enough. The UI package does not mint screen-, component-, or product-specific color aliases. No raw `#hex` / `rgb()` / `hsl()` may appear in `.tsx`; a new source value goes to `packages/design-system/DESIGN.md` first and flows through generated output. A narrow protocol adapter may translate third-party classes directly to canonical tokens in `globals.css`, but it must not create another token vocabulary. Enforced by the raw-colour `no-restricted-syntax` selectors in the library ESLint config, `packages/ui/tests/guards/dark-semantic-roles.test.ts`, and `packages/ui/tests/guards/token-reference-integrity.test.ts`.
8
8
  - **Dark-ready semantics, no component dark implementation.** Components use the same semantic role or canonical mode-aware token in every mode. They must not ship Tailwind `dark:` color utilities, component-local `.dark` blocks, OS dark-mode branching, or raw dark palette utilities such as `dark:bg-slate-950` and `dark:text-white`. An intentionally fixed-presentation technology surface, such as the dark terminal console, selects canonical fixed-mode tokens as one coherent component treatment rather than branching by app theme. Enforced by `packages/ui/tests/guards/no-dark.test.ts`, `packages/ui/tests/guards/dark-semantic-roles.test.ts`, and `packages/ui/tests/guards/token-reference-integrity.test.ts`. The generated mode and theme architecture lives only in [`packages/design-system/DESIGN.md`](../../design-system/DESIGN.md#css-architecture--token-pipeline).
9
- - **Components inherit one complete React style interface.** `@nadicodeai/ui/globals.css` composes every style dependency owned by this package, including the complete design-system CSS module. Components carry no theme of their own, and React callers do not compose design-system stylesheets or partials beside it. Installation and source-scanning setup live in the [consumer setup guide](consuming-cross-repo.md). `@nadicodeai/ui/globals.css` is the only stylesheet this package ships; a surface that loads no Tailwind layer takes the design system's token artifact and writes its own rules against it.
9
+ - **Components inherit one complete React style interface.** `@nadicodeai/ui/globals.css` composes every style dependency owned by this package, including the complete design-system CSS module. Components carry no theme of their own, and React callers do not compose design-system stylesheets or partials beside it. Installation and source-scanning setup live in the [consumer setup guide](consuming-cross-repo.md). The package ships two stylesheets, split by who owns the page. `@nadicodeai/ui/globals.css` is for an application this design system styles whole: it imports Tailwind, the complete design system with its reset and base layer, and the second file. `@nadicodeai/ui/components.css` is for a host that already runs Tailwind over base styles of its own, such as the Nadia desktop inside Hermes's shell: it carries the `@source` lines, the `nc-*` utilities and the component-owned rules, and nothing that lands on a page. That host imports `@nadicodeai/design-system/css/host` before it, which adds the Tailwind keys only this design system names and leaves the host its shadcn roles, its radius scale and its palette. The components render in both from one source, which is what keeps the products consistent. A surface that loads no Tailwind layer takes the design system's token artifact and writes its own rules against it.
10
10
  - **Design-system geometry remains the foundation.** React components compose the kept `nc-*` page grammar and display CSS components; they do not redefine frame math, marker placement, token values, or raw CSS geometry. Use parent-paints-plus-gap for bordered cell grids and keep every visible seam single-owner (doctrine home: `packages/design-system/DESIGN.md` "## Layout").
11
11
 
12
12
  ### Persistent notices
@@ -21,7 +21,7 @@ read-only and stale-data notices use this shared composition directly.
21
21
 
22
22
  ### Material surfaces
23
23
 
24
- `globals.css` declares the four elevation utilities, `nc-elevation-resting`,
24
+ `components.css`, which `globals.css` imports, declares the four elevation utilities, `nc-elevation-resting`,
25
25
  `nc-elevation-raised`, `nc-elevation-floating`, and `nc-elevation-modal`. Each
26
26
  sets `box-shadow` to the generated `--nc-elevation-<rung>` token, pinned by
27
27
  `packages/design-system/DESIGN.md` "core.elevation": one recipe per rung per
@@ -148,11 +148,11 @@ states to the orb.
148
148
  - **Charts are stock shadcn charts.** Every chart and KPI here is a registry item, changed as little as possible: `chart.tsx` is shadcn's `chart` over Recharts; `chart-bar-stacked`, `chart-area-stacked`, and `chart-bar-multiple` are the blocks of those names; `chart-sparkline` is `chart-line-linear` stripped of its card, axes, grid and tooltip; `kpi-card` is the `dashboard-01` block's section card; `chart-card` is their shared Card frame. Each pulled file names its registry item on line one. `base-nova` does not publish the chart gallery and the CLI search does not list it, so a chart the kit lacks is pulled from `https://ui.shadcn.com/r/styles/new-york-v4/<name>.json` (`files[0].content`) and added here. What deviates from stock, and why, is listed once in [`DESIGN.md`, "Chart source"](../../design-system/DESIGN.md#chart-source); a change to a pulled chart that is not on that list is drift. There is no hidden table twin, no mark inside a legend, and no second axis. Every chart component renders the whole card — `Card > CardHeader(CardTitle, CardDescription, CardAction) > CardContent(ChartContainer) > CardFooter?` — at a fixed plot height (`h-64`, `h-80` at `size="lg"`), legend below the plot, left-aligned and wrapping. An app composes these, never builds a chart card frame by hand, and never imports `recharts`, which this package alone declares. Which chart a reading question deserves is owned by [`skills/design/product-design/references/charts.md`](../../../skills/design/product-design/references/charts.md).
149
149
 
150
150
  - **Named shadcn blocks stay named.** When a user, plan, or issue selects a shadcn block/example such as `login-02`, `signup-02`, `dashboard-01`, or `sidebar-*`, use that registry item as the source of truth through shadcn CLI/MCP. Do not replace it with a package-authored abstraction unless the plan explicitly records the substitution, the reason, and the true consumer route that proves it.
151
- - **A change to what the package ships bumps the version.** Any change to exported components, `src/index.ts`, package `exports`, `globals.css`, theme behavior, package docs, or design-system token, CSS, or theme output this package consumes bumps both package versions in lockstep before handoff, and `npm pack --dry-run -w @nadicodeai/ui` shows exactly what consumers receive (procedure: `../../../docs/agents/publish.md`).
151
+ - **A change to what the package ships bumps the version.** Any change to exported components, `src/index.ts`, package `exports`, `globals.css`, `components.css`, theme behavior, package docs, or design-system token, CSS, or theme output this package consumes bumps both package versions in lockstep before handoff, and `npm pack --dry-run -w @nadicodeai/ui` shows exactly what consumers receive (procedure: `../../../docs/agents/publish.md`).
152
152
 
153
153
  ## Admission Rules
154
154
 
155
- Assistant conversation and runtime APIs enter through `@nadicodeai/ui/agents`; Agent identity enters through `@nadicodeai/ui/components/agent-card`, `@nadicodeai/ui/components/agent-visual`, and the Forma avatars in `@nadicodeai/ui/components/forma-avatar` (owned by [`forma-avatar.md`](forma-avatar.md)). The consuming application still constructs the runtime and owns transport, persistence, permissions, tools, approvals, and failure policy. Shared non-Agent product components (a shell, a settings surface, a generic section, a diff, or a file preview) are admitted only with a named consuming surface landing in the same change. App-bespoke UI and behavior (window chrome, PTY/xterm embeds, queues, approvals, and persistence) stay in the consuming app; they never become package abstractions. A component left unconsumed after its target migration ships gets removed.
155
+ Assistant conversation and runtime APIs enter through `@nadicodeai/ui/agents`; Agent identity enters through `@nadicodeai/ui/components/agent-card`, `@nadicodeai/ui/components/agent-orb`, `@nadicodeai/ui/components/agent-visual`, and the Forma avatars in `@nadicodeai/ui/components/forma-avatar` (owned by [`forma-avatar.md`](forma-avatar.md)). The consuming application still constructs the runtime and owns transport, persistence, permissions, tools, approvals, and failure policy. Shared non-Agent product components (a shell, a settings surface, a generic section, a diff, or a file preview) are admitted only with a named consuming surface landing in the same change. App-bespoke UI and behavior (window chrome, PTY/xterm embeds, queues, approvals, and persistence) stay in the consuming app; they never become package abstractions. A component left unconsumed after its target migration ships gets removed.
156
156
 
157
157
  ### Placement
158
158
 
@@ -166,6 +166,17 @@ where [`apps/nadia/docs/entry-screen.md`](../../../apps/nadia/docs/entry-screen.
166
166
  owns their contract. `packages/ui/tests/guards/product-placement.test.ts`
167
167
  refuses a product's name in either package.
168
168
 
169
+ ### Abstract Agent identities
170
+
171
+ `AgentOrb` is the seven-form, single-colour abstract family in
172
+ [`agent-orb.md`](agent-orb.md), exposed through
173
+ `@nadicodeai/ui/components/agent-orb`. Its consuming validation surface is
174
+ `examples/agent-orbs`: the built component at detail, menu and conversation
175
+ sizes, with independently editable colours. The application stores appearance;
176
+ upstream activity names select geometry only and never infer an Agent role or
177
+ change its identity with runtime work. Customer-selected artwork colours are
178
+ inputs, not component palette literals or interface colour roles.
179
+
169
180
  ### Agent identity presentation
170
181
 
171
182
  The visual system (the closed recipes, motion, fallbacks, and licensing) is
@@ -190,7 +201,6 @@ product-domain `agent` object prop in the shared package.
190
201
  - **Reusable sections and compositions live here after proof.** Bento grids, media mounts, demo surfaces, page frames, section intros, CTA bands, proof slots, benefits grids, generic shells, and homepage/use-case sections belong in `@nadicodeai/ui` when a second concrete consumer, a plan-approved shared component, or a named validation slice proves the package boundary. Website, portal, and sibling Nadia routes pass data and media children into existing compositions instead of rebuilding layout locally.
191
202
  - **Brand renderers live here for React consumers.** Logo geometry, asset generation, and usage semantics are owned by [`packages/design-system/DESIGN.md`, "Brand media authority"](../../design-system/DESIGN.md#brand-media-authority). `BrandLockup` supplies the approved horizontal lockup. `BrandMark` serves tight spaces and `BrandWordmark` serves placements where the name must read by itself. All three render the package's public neutral geometry seam with React-scoped SVG ids, dynamic theme paint, and accessible names. Consuming routes use these adapters; they never import raw logo assets, draw brand SVG inline, mask or recolor assets, or create another lockup rule.
192
203
  - **Third-party brand marks are generated, never hand-drawn and never hand-edited.** Other companies' marks live in `packages/ui/src/components/brand-icons/`, emitted from an explicit allow-list by `packages/ui/scripts/build-brand-icons.mjs` and exported through the `@nadicodeai/ui/components/brand-icons` subpath. They are identity images, not UI icons: a brand mark is exempt from the currentColor stroke system and from the raw-literal rule, it never stands in for a UI icon, and a UI icon never stands in for a brand. Marks drawn as one silhouette are stripped to `currentColor` by the generator; every other mark keeps its official colors verbatim. To add a brand, edit the generator's allow-list and run `npm run generate:brand-icons -w @nadicodeai/ui`; hand edits to the generated directory are lost and `packages/ui/tests/guards/brand-icons-codegen.test.ts` fails on them. Use is nominative only — naming a platform, an integration, or a provider — never adjacent to endorsement or partnership wording; that nominative posture is the licensing and trademark position, so a mark never appears where the copy implies endorsement.
193
-
194
204
  The one script reads two explicit allow-lists: platform marks out of the Iconify `logos` set (CC0-1.0), and model makers' marks out of the LobeHub icon set (MIT, `@lobehub/icons-static-svg`), both as `devDependencies`. The emitted components are plain SVG, so neither icon data package belongs in the runtime dependency set or reaches a consumer bundle. The artwork itself does ship, so every upstream whose licence asks for one travels with a notice in `LICENSES/` and `NOTICE`, and `tests/guards/brand-icons-codegen.test.ts` holds the allow-list to that: a new source cannot ship unattributed.
195
205
  - **No fake proof APIs.** Components may support future testimonials, logos, stats, and proof slots, but they must render nothing public when the proof is absent. Do not ship placeholder customer names, metrics, or logos.
196
206
 
@@ -230,7 +240,9 @@ comparison line and a note, both in the caller's language. There is no grouped o
230
240
  row of KPIs is a `CardRow` of `KpiCard`s, each its own card. Apps supply the
231
241
  figures and bind links through `render`. Charts expose `size` (`default` or
232
242
  `lg`), which selects a fixed plot height, so consumers never select internal
233
- chart elements.
243
+ chart elements. `ChartSummary` owns a chart's measured value, trend badge,
244
+ status and comparison line inside the chart card; consumers provide typed
245
+ content instead of rebuilding that presentation beside the plot.
234
246
 
235
247
  `CollectionToolbar` owns the collection-control layout: compact filters at the
236
248
  leading edge, a flexible search field, and trailing actions. Its slot order is
@@ -284,9 +296,24 @@ and status retain their column headers. Missing values retain their place.
284
296
  `standard` retains full columns at 768px of container width, `wide` at 1024px,
285
297
  and `spacious` at 1152px for schemas with additional operational columns.
286
298
  The same owner switches column visibility, detail visibility, and row boundaries.
299
+ `TableRecordGroup` wraps the primary row and its compact detail row in one
300
+ native row group, so hovering, focusing, expanding, or selecting either half
301
+ highlights one record. A consumer does not render the two rows as independent
302
+ siblings. Portal `DataTable` chooses a layout from its column count by default;
303
+ a comparison whose columns remain readable longer may select one of these
304
+ shared layouts instead of adding route-owned width rules.
287
305
  Two supporting facts use two columns; additional facts can use three when they fit.
288
306
  The cell renderer supplies the value, leaving the label to the detail row.
289
307
 
308
+ ### Missing table values
309
+
310
+ `TableValue` owns the [cross-product missing-value convention](../../design-system/PRODUCT_LANGUAGE.md#missing-values-in-collections).
311
+ Pass the actual scalar or rendered value and a required localized `missingLabel`.
312
+ Null, undefined and empty strings render a muted, visually fixed `—` plus
313
+ screen-reader text; zero and present values pass through unchanged. No custom
314
+ visible fallback is exposed. Do not prefill `value` with absence copy.
315
+ Loading, failure, permission and actionable states remain outside this component.
316
+
290
317
  ## Consumer Boundary
291
318
 
292
319
  Consumers own routing, auth, app data, server actions, runtime construction and adapters, permission decisions, analytics, and app-specific copy. The package owns reusable React presentation and the public Agent UI dependency boundary. Agent state and behavior come through the Agents interface; non-React and TUI contracts belong to their consuming products.
@@ -342,3 +369,19 @@ The identity row names who is signed in and carries one `DropdownMenuItem
342
369
  iconOnly` gear at its trailing edge, linking to the account section; the menu
343
370
  does not repeat that section's pages as commands. Consumers bind preference
344
371
  persistence, routing, and localized labels.
372
+
373
+ ## Object workspace compositions
374
+
375
+ `ObjectIdentity`, `ObjectOverview`, `ObjectSection` and `ObjectFacts` compose the
376
+ [shared IA patterns](../../design-system/PRODUCT_LANGUAGE.md#reusable-information-architecture)
377
+ from existing Card and typography foundations. They own identity/action alignment,
378
+ primary/supporting responsive columns, summary boundaries and semantic definition
379
+ pairs. They take slots and values, never domain stores, URLs, permissions or save
380
+ functions. Portal's agent workspace binds them to its scoped routes; Nadia may
381
+ reuse the same presentation within its own shell. Do not ship a second complete
382
+ Agent application inside this package.
383
+
384
+ `ObjectIdentity.support` adds a small set of stable, labelled context facts to
385
+ the identity header. The facts sit beside the identity when space allows and
386
+ collapse behind the caller's localized disclosure label on compact screens.
387
+ Operational warnings and changing report readings remain in the page body.
@@ -0,0 +1,18 @@
1
+ # Model identity compatibility adapter
2
+
3
+ `ModelIdentity` is a compatibility adapter for consumers that still pass one
4
+ `provider/model` string. It derives the author prefix and delegates all visual
5
+ rendering to the canonical `ModelMark`; it has no provider registry, generated
6
+ artwork, or presentation of its own. Unknown authors therefore receive the
7
+ same neutral tile as every other `ModelMark` consumer.
8
+
9
+ ```tsx
10
+ import { ModelIdentity } from "@nadicodeai/ui/components/model-identity";
11
+
12
+ <ModelIdentity model="anthropic/claude-sonnet-5" />;
13
+ ```
14
+
15
+ New consumers should import `ModelMark` and pass its `author` and `name`
16
+ properties directly. The adapter keeps the older `model`, `label`, and
17
+ `markSize` call shape while consumers migrate; a string `label` becomes the
18
+ canonical model name, otherwise the model segment after the slash is shown.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nadicodeai/ui",
3
- "version": "8.0.1",
3
+ "version": "8.2.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -14,6 +14,7 @@
14
14
  "import": "./dist/index.js"
15
15
  },
16
16
  "./globals.css": "./dist/styles/globals.css",
17
+ "./components.css": "./dist/styles/components.css",
17
18
  "./eslint": "./dist/eslint/index.js",
18
19
  "./agents": {
19
20
  "types": "./dist/agents.d.ts",
@@ -35,6 +36,10 @@
35
36
  "types": "./dist/lib/theme-mode.d.ts",
36
37
  "import": "./dist/lib/theme-mode.js"
37
38
  },
39
+ "./lib/format-token-count": {
40
+ "types": "./dist/lib/format-token-count.d.ts",
41
+ "import": "./dist/lib/format-token-count.js"
42
+ },
38
43
  "./components/*": {
39
44
  "types": "./dist/components/*.d.ts",
40
45
  "import": "./dist/components/*.js"
@@ -65,11 +70,12 @@
65
70
  "@assistant-ui/react": "0.15.20",
66
71
  "@assistant-ui/react-markdown": "0.14.15",
67
72
  "@base-ui/react": "^1.8.0",
68
- "@nadicodeai/design-system": "8.0.1",
73
+ "@nadicodeai/design-system": "8.2.0",
69
74
  "@paper-design/shaders": "0.0.81",
70
75
  "class-variance-authority": "^0.7.1",
71
76
  "clsx": "^2.1.1",
72
77
  "cmdk": "^1.1.1",
78
+ "date-fns": "^4.4.0",
73
79
  "embla-carousel-react": "^8.6.0",
74
80
  "input-otp": "^1.5.0",
75
81
  "lucide-react": "1.47.0",