@nadicodeai/design-system 7.1.4 → 8.0.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 (2) hide show
  1. package/DESIGN.md +48 -36
  2. package/package.json +1 -1
package/DESIGN.md CHANGED
@@ -333,12 +333,12 @@ Every value a role needs is carried by the role token itself; there is no numeri
333
333
  - **Semantic feedback** (`{colors.success}` = verde with `{colors.success-soft}`/`{colors.success-deep}`; `{colors.error}` = rosso funzionale `#d3302f` with `{colors.error-soft}`/`{colors.error-deep}`; `{colors.warning}` = giallo `#ffc220` with `{colors.warning-soft}`/`{colors.warning-deep}`; `{colors.info}` = cobalto `#1e3cff` with `{colors.info-soft}`/`{colors.info-deep}`): validation, caution, approval, and operational feedback. In each pair the `-soft` value is the tinted tag/banner ground and the `-deep` value is the AA-clearing text on it. On a solid `error` fill (the shadcn `destructive` role) text is white; on a solid `warning` or `success` fill text is ink. The success pair intentionally reuses the link pair's AA-safe verde values; its feedback meaning remains distinct from inline navigation and entity-status semantics.
334
334
  - **Accent** (`{colors.accent}` = arancio `#ff5a1f`): a small emphasis mark for exception flags and highlights; it appears as a mark, carries no text, and paints no fill or background. The identically-named shadcn surface role is a different thing — a neutral (`{colors.canvas-soft-2}` light, `{colors.dark-canvas-soft-2}` dark) with no hue.
335
335
  - **Verde vivo** (`{colors.verde-vivo}` = `#008c45`, dark `{colors.dark-verde-vivo}` = `#62d494`): Nadia's presence accent. It paints the marks that say *Nadia herself is here*, such as the success beat over her silhouette on Nadia's entry screen. It is a mark colour, never a control fill, a text colour, a link, or a status; `action`, `link`, and `success` keep their jobs. It clears the 3:1 non-text floor on `{colors.canvas}` (4.3:1) and `{colors.dark-canvas}` (11.4:1) and carries no text of its own. White on it is 4.34:1, below AA for normal text, so a label never sits on a `verde-vivo` fill; the ring, halo, or portrait sits on it and the words sit on the canvas.
336
- - **Workflow States** (`{colors.state-ready}` neutral, `{colors.state-running}` cobalto, `{colors.state-review}` giallo, `{colors.state-blocked}` rosso, `{colors.state-complete}` verde): the left-border/state vocabulary for agentic work surfaces — cobalto means in motion, verde means done. The dark counterparts (`{colors.dark-state-ready}`, `{colors.dark-state-running}`, `{colors.dark-state-review}`, `{colors.dark-state-blocked}`, `{colors.dark-state-complete}`) keep the same functional identity. These colours are carried by non-text state accents only — meter and bullet segments, delta marks, and the brand book's own rails; label text stays on the neutral foreground roles for contrast in both themes. Status is not one of their jobs: every status the product renders is the Badge status vocabulary (see `## Status Vocabulary`), which reads from the semantic feedback and link pairs, and the two token sets never cross.
336
+ - **Workflow States** (`{colors.state-ready}` neutral, `{colors.state-running}` cobalto, `{colors.state-review}` giallo, `{colors.state-blocked}` rosso, `{colors.state-complete}` verde): the left-border/state vocabulary for agentic work surfaces — cobalto means in motion, verde means done. The dark counterparts (`{colors.dark-state-ready}`, `{colors.dark-state-running}`, `{colors.dark-state-review}`, `{colors.dark-state-blocked}`, `{colors.dark-state-complete}`) keep the same functional identity. These colours are carried by non-text state accents only — meter fills, delta marks, and the brand book's own rails; label text stays on the neutral foreground roles for contrast in both themes. Status is not one of their jobs: every status the product renders is the Badge status vocabulary (see `## Status Vocabulary`), which reads from the semantic feedback and link pairs, and the two token sets never cross.
337
337
 
338
338
  ### Chart categoricals (functional tier)
339
339
 
340
- - **Charts** (`{colors.chart-1}`…`{colors.chart-6}`): the categorical series palette — cobalto, verde, giallo, rosso, plus a functional-only teal and viola. Chart colours belong to data surfaces only; identity planes and generated imagery draw from the Agent identity palette. Two light slots are series-tuned so the set clears the categorical data bands on the white data surface: `chart-3` steps the giallo darker (the identity giallo `{colors.identity-giallo}` overshoots the categorical lightness band and reads too pale as a mark) and `chart-5` makes the teal more chromatic (the raw functional teal otherwise sits under the chroma floor and reads gray). The darker giallo still falls below the 3:1 mark-contrast line and is carried by the always-on legend/direct-label/table relief the charting method already mandates — never a per-surface patch. On the dark canvas all six series carry dark-tuned steps (`{colors.dark-chart-1}`…`{colors.dark-chart-6}`), remapped in the `.dark` scope so any consumer reading the semantic token gets the right hue in both modes. Clearing the 3:1 WCAG 1.4.11 data-mark floor is necessary but not sufficient on the black canvas: full-strength hues read as loud blocks there, so each dark step lightens or desaturates while keeping series identity — the dark giallo and teal deliberately stay bright to hold their per-series deuteranopia separation from rosso — and all six clear 3:1 against `{colors.dark-canvas}`.
341
- - **Categorical distinguishability**: the same-family neighbours are held apart — `chart-3`/`chart-4` (giallo/rosso) and `chart-2`/`chart-5` (verde/teal) each clear a CIEDE2000 ≥ 20 normal / ≥ 15 deuteranopia-simulated floor, in the light set and the dark-tuned set alike. Two proximities are brand-locked and exempt from the numeric floor: `chart-2`/`chart-4` (verde/rosso, the flag pair, which collapses under red-green deficiency by identity) and `chart-1`/`chart-6` (cobalto/viola, adjacent blue-violet). Charts using the full six carry redundant encoding (direct labels, position, or pattern), never hue alone, so these two pairs stay readable under colour-vision deficiency.
340
+ - **Charts** (`{colors.chart-1}`…`{colors.chart-6}`): the categorical series palette — cobalto, verde, giallo, rosso, plus a functional-only teal and viola. Chart colours belong to data surfaces only; identity planes and generated imagery draw from the Agent identity palette. Two light slots are series-tuned so the set clears the categorical data bands on the white data surface: `chart-3` steps the giallo darker (the identity giallo `{colors.identity-giallo}` overshoots the categorical lightness band and reads too pale as a mark) and `chart-5` makes the teal more chromatic (the raw functional teal otherwise sits under the chroma floor and reads gray). The darker giallo still falls below the 3:1 mark-contrast line and is carried by the always-on legend and the paired table the charting method already mandates — never a per-surface patch. On the dark canvas all six series carry dark-tuned steps (`{colors.dark-chart-1}`…`{colors.dark-chart-6}`), remapped in the `.dark` scope so any consumer reading the semantic token gets the right hue in both modes. Clearing the 3:1 WCAG 1.4.11 data-mark floor is necessary but not sufficient on the black canvas: full-strength hues read as loud blocks there, so each dark step lightens or desaturates while keeping series identity — the dark giallo and teal deliberately stay bright to hold their per-series deuteranopia separation from rosso — and all six clear 3:1 against `{colors.dark-canvas}`.
341
+ - **Categorical distinguishability**: the same-family neighbours are held apart — `chart-3`/`chart-4` (giallo/rosso) and `chart-2`/`chart-5` (verde/teal) each clear a CIEDE2000 ≥ 20 normal / ≥ 15 deuteranopia-simulated floor, in the light set and the dark-tuned set alike. Two proximities are brand-locked and exempt from the numeric floor: `chart-2`/`chart-4` (verde/rosso, the flag pair, which collapses under red-green deficiency by identity) and `chart-1`/`chart-6` (cobalto/viola, adjacent blue-violet). Charts using the full six carry redundant encoding (the legend, position, or the paired table), never hue alone, so these two pairs stay readable under colour-vision deficiency.
342
342
 
343
343
  ### Agent identity palette
344
344
 
@@ -356,6 +356,24 @@ This achromatic-neutral discipline is not dark-specific: it governs the generate
356
356
 
357
357
  ## Data Visualization
358
358
 
359
+ ### Chart source
360
+
361
+ Every chart and KPI card is a stock shadcn component. They are pulled from the registry at `https://ui.shadcn.com/r/styles/new-york-v4/<name>.json`, because the `base-nova` style this system uses publishes no chart gallery. The KPI card is the `dashboard-01` block's `section-cards`. `@nadicodeai/ui` owns the pulled files and the card frame each one renders; a page never assembles a chart card by hand and never reaches into a chart's internals from its call site.
362
+
363
+ These are the deviations from what the registry ships. The list is complete: a change to a pulled chart that is not here is drift, and `packages/ui/tests/guards/chart-kit.test.ts` holds each one.
364
+
365
+ 1. **Value formatting.** `valueFormatter` prints the exact figure in the tooltip, in the units the surface uses. `axisFormatter` prints the axis as a scale (`1.6B`, `800M`, `$7.5`), because an axis is read for magnitude and a full figure on every tick crowds it.
366
+ 2. **Color by entity.** A series takes its color from the entity-color map below, never from its position in the series array. See "Entity-color assignment".
367
+ 3. **Value axis.** Always drawn, with five ticks handed to the axis on a 1, 2, 2.5, 5, or 10 step. Left to itself Recharts chooses its own count, and a rounded label then sits on an unrounded position.
368
+ 4. **Bar width.** Bars cap at 48px. Stock has no cap, and one category drew a bar the width of the card.
369
+ 5. **Reading aids.** The grid is dashed in both directions. The tooltip uses the stock line indicator, with a gap between a row's name and its value so a long name cannot run into the figure. Every multi-series chart has a legend below the plot, left-aligned, a round dot and a name, in the order of the series it names; the stock area and grouped-bar blocks ship without one, and Recharts sorts legend items by key.
370
+ 6. **Share of a total.** `chart-bar-stacked` has a `share` layout: one bar split to 100% (`stackOffset="expand"`), for a breakdown with no time axis.
371
+ 7. **A chart is a named section.** The card title is a heading at the level the page gives it, and it names the plot through `aria-labelledby`. The plot shows a focus ring while it has keyboard focus: stock hides the outline of the svg that Recharts' `accessibilityLayer` makes focusable.
372
+
373
+ Two things beside the charts also differ from stock. `Progress` takes a `tone` (default, warning, critical) and paints over-cap as a full critical bar. The pulled charts share one card frame, `chart-card`, in place of each file repeating it.
374
+
375
+ Everything else is the registry's: bar geometry and corner radius, tooltip and legend content, animation, and the recharts `accessibilityLayer` as shadcn ships it. This contract mandates no custom mark geometry, no segment gap, and no hidden table twin of a chart.
376
+
359
377
  ### Entity-color assignment
360
378
 
361
379
  - **Entity-color assignment**: categorical hues (`{colors.chart-1}`…`{colors.chart-6}`) assign in fixed order to entities per page context, and the assignment follows the entity identity, never rank, sort position, or array index. One assignment map exists per surface: the same entity keeps the same color in a chart and its paired table, whether the chart uses one categorical bar per entity or a time series per entity. A filter or re-sort never repaints the entities that remain on screen. Beyond six entities, fold the tail into a single neutral "other" slot (`{colors.muted}` register), never a seventh hue.
@@ -365,39 +383,33 @@ This achromatic-neutral discipline is not dark-specific: it governs the generate
365
383
  - **Sequential ramp** (`{colors.chart-seq-1}`…`{colors.chart-seq-5}`, a single cobalto hue running light→dark): ordered magnitude on one hue, never nominal categories, never a rainbow. `{colors.dark-chart-seq-1}`…`{colors.dark-chart-seq-5}` remap in the `.dark` scope like the categorical set, anchor flipped so `dark-chart-seq-1` is the dimmest step and `dark-chart-seq-5` the brightest, each clearing the 3:1 WCAG 1.4.11 data-mark floor against `{colors.dark-canvas}`.
366
384
  - **Diverging pair** (`{colors.chart-div-warm}` giallo/amber, `{colors.chart-div-mid}` a neutral mid, `{colors.chart-div-cool}` cobalto; dark counterparts `{colors.dark-chart-div-warm}`, `{colors.dark-chart-div-mid}`, `{colors.dark-chart-div-cool}` remapped in the `.dark` scope the same way): the warm and cool poles carry the sign, the neutral midpoint never carries hue. Meter tracks use a lighter step of the same ramp as their fill.
367
385
 
368
- ### Meter and bullet grammar
369
-
370
- A meter describes magnitude. The product defines its tone's semantic scope:
371
- the condition of the measured allowance, for example, or an operational access
372
- state. Those meanings are not interchangeable. Keep the measure, tone, label,
373
- and explanation consistent with the chosen scope; a ratio reaching its end
374
- does not independently establish the state of another capability. The
375
- foundation does not choose a product's colour entry screens or reinterpret a
376
- recorded balance as an access guarantee.
386
+ ### Meter grammar
377
387
 
378
- At panel scale, show the product-configured entry screen and cap ticks. Overflow
379
- continues past the cap as a distinct segment. At row scale, use a percentage and thin
380
- bar on one line, omitting ticks and tip labels that cannot read at that size.
381
- Row scale is comparison geometry, not a warning-only variant. Both scales keep
382
- an accessible name, the real textual value, and `aria` values bounded to the
383
- meter maximum. Colour reinforces its defined meaning; it is never the
384
- only explanation.
388
+ A meter describes magnitude. The carrier is the stock shadcn `Progress`, with
389
+ one `tone` variant: default, warning, or critical. There is no second meter
390
+ geometry, no cap tick, and no separate overflow segment. A value over its cap
391
+ reads as a full bar in the critical tone beside the printed figure, which is
392
+ what states the overage.
385
393
 
386
- ### Mark specs
394
+ The product defines its tone's semantic scope: the condition of the measured
395
+ allowance, for example, or an operational access state. Those meanings are not
396
+ interchangeable. Keep the measure, tone, label, and explanation consistent with
397
+ the chosen scope; a ratio reaching its end does not independently establish the
398
+ state of another capability. The foundation does not choose a product's color
399
+ entry screens or reinterpret a recorded balance as an access guarantee.
387
400
 
388
- - **Mark specs**: bars and columns run at most 24px thick with 4px rounded data-ends anchored square at the baseline. Stacked segments and adjacent marks keep a 2px surface gap, one consistent gap width per chart. Lines run at least 2px with round joins and caps; point markers run at least 8px with a 2px surface ring. Area fills read as a light wash (roughly 10% opacity) under a full-strength line. Gridlines and axes are recessive 1px solid hairlines one step off the surface, never dashed. Chart text always carries ink tokens (`{colors.ink}`, `{colors.muted}`), never the series color. Marks render in real pixel space; a chart never scales its viewBox non-uniformly.
401
+ A meter keeps an accessible name, the real textual value beside it, and `aria`
402
+ values bounded to the meter maximum. Color reinforces its defined meaning; it
403
+ is never the only explanation.
389
404
 
390
405
  ### Delta and trend encoding
391
406
 
392
- - **Delta and trend encoding**: a change reads as a direction glyph plus a tone token, never bare signed text and never color alone. The glyph is ▲ ▼ in running text and a trend arrow in a KPI card's top-right badge. Tone follows direction crossed with whether up is good in that context. Sparklines normalize against a meaningful baseline, never the visible min-max span alone. A ranked "what moved" list uses the same arrow-and-tone encoding as the KPI badge, and a figure with no comparison shows no badge rather than a zero change.
407
+ - **Delta and trend encoding**: a change reads as a shadcn `Badge` in its `outline` variant carrying a lucide trend icon (`TrendingUp`, `TrendingDown`, or `Minus`) and the signed value, followed by the muted phrase "vs {period}" that names what the change is measured against. Never bare signed text, never color alone, and never a ▲ or ▼ glyph. The icon carries the direction; tone follows direction crossed with whether up is good in that context, and a delta whose direction means nothing good or bad stays neutral. Sparklines normalize against a meaningful baseline, never the visible min-max span alone. A ranked "what moved" list uses the same badge as the KPI card, and a figure with no comparison shows no badge rather than a zero change.
393
408
 
394
409
  ### Legends and labels
395
410
 
396
- - **Legends and labels**: at two or more series, every series is identified — up to four series prefer direct labels, which then replace the legend; beyond four, or whenever direct labels are not feasible, a legend is required (ink-token text beside a color swatch; text never wears the series color). A single series is titled, not legended. Every chart names a table alternative. Tooltips enhance a chart and never gate a value.
397
-
398
- ### Texture fallback
399
-
400
- - **Texture fallback**: under forced-colors, print, or an accessibility setting, series distinguish by one directional line texture at 45 or 135 degrees (tone-on-tone, a darker step of the fill's own ramp), ordered with magnitude on value scales, with the arm angle carrying the diverging sign. Texture is never on by default. The two brand-locked categorical pairs (`chart-2`/`chart-4`, `chart-1`/`chart-6`) always require redundant encoding, never hue alone, restating the Chart categoricals distinguishability rule.
411
+ - **Legends and labels**: at two or more series the legend is the registry's `ChartLegendContent`, placed below the chart, left-aligned, and wrapping to a second line. It carries a color dot and the entity name, and nothing else: no maker's mark, no logo tile, no value, no share. A model's mark appears beside its name in tables and lists, where the mark identifies the model (rule `model-shown-with-logo`), never inside a legend. Legend, axis, and label text carries ink tokens (`{colors.ink}`, `{colors.muted}`) and never wears the series color. A single series is titled, not legended. Tooltips enhance a chart and never gate a value.
412
+ - **Accessible alternative**: the chart's accessibility comes from the stock `accessibilityLayer`. A chart ships no visually hidden table twin of itself. Where a page needs the numbers as text, it shows a real table or list that the reader can see, built from the same result the chart reads.
401
413
 
402
414
  ## Typography
403
415
 
@@ -563,10 +575,10 @@ The material and elevation values are authored in the one `json design-tokens` f
563
575
  | Material role | Construction | Use |
564
576
  | ------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
565
577
  | Workspace | `dotted-field` on `{colors.material-workspace}` / `{colors.dark-material-workspace}`; no edge or shadow | The continuous work area behind product objects |
566
- | Resting | Solid fill; `nc-elevation-resting` with its own ring; `{rounded.3xl}` (16 px) | KPI, card, table, setting, and persistent content surfaces |
567
- | Raised | Same solid fill; `nc-elevation-raised`; `{rounded.3xl}` (16 px) | Active work, a selected object, or an attached inspector above resting siblings |
568
- | Floating | Same solid fill; `nc-elevation-floating`; role-specific corner radius | Compact menus, popovers, dropdowns, and anchored surfaces use `{rounded.2xl}` (12 px); small artifacts such as tooltips and toasts keep `{rounded.md}` (6 px); detached product surfaces may use `{rounded.3xl}` (16 px) |
569
- | Modal | Same solid fill; `nc-elevation-modal`; `{rounded.3xl}` (16 px) | Dialog, sheet, drawer, and takeover |
578
+ | Resting | Solid fill; `nc-elevation-resting` with its own ring; `{rounded.md}` (6 px) | KPI, card, chart card, table, setting, and persistent content surfaces |
579
+ | Raised | Same solid fill; `nc-elevation-raised`; `{rounded.md}` (6 px) | Active work, a selected object, or an attached inspector above resting siblings |
580
+ | Floating | Same solid fill; `nc-elevation-floating`; `{rounded.md}` (6 px) | Menus, popovers, dropdowns, selects, anchored surfaces, tooltips, and toasts |
581
+ | Modal | Same solid fill; `nc-elevation-modal`; `{rounded.md}` (6 px) | Dialog, sheet, drawer, and takeover |
570
582
  | Glass control | Translucent solid fill at 76%, 28 px backdrop blur, and the rung for its physical level with that rung's ring | Floating chrome above our own content: menus, popovers, selects, comboboxes, the command palette, and bars; never a content container |
571
583
 
572
584
  `Card` is the fundamental product container. Its content does not create a second material family: KPIs, Agent cards, settings, and ordinary grouped content use the resting role unless the object is physically raised. Interaction variants may change state or emphasis without changing the material role.
@@ -581,14 +593,14 @@ On coarse or non-hover input capability, every interactive target is at least 44
581
593
 
582
594
  ## Shapes
583
595
 
584
- Corners are restrained and assigned by material role.
596
+ One radius rounds every surface. The reference is the search field: `{rounded.md}` (6 px). A surface never earns a larger corner by sitting higher on the elevation ladder, and no register may reintroduce a second surface radius.
585
597
 
586
- - Use `{rounded.none}` for page rows, frame edges, grid cells, and structural modules.
587
- - Use `{rounded.md}` (6 px) for controls, buttons, chips, status tags, and small artifacts.
588
- - Use `{rounded.2xl}` (12 px) for compact menus, popovers, dropdowns, and anchored floating surfaces.
589
- - Use `{rounded.3xl}` (16 px) for resting and raised product content surfaces, detached inspectors, modal dialogs, inset sheets, and takeovers.
598
+ - Use `{rounded.md}` (6 px) for every surface and every control: resting, raised, outlined, floating, and modal surfaces; cards, KPI cards, chart cards, tables, menus, selects, popovers, dropdowns, dialogs, sheets, drawers, takeovers, tooltips, toasts, inspectors; and buttons, inputs, chips, status tags, and small artifacts.
599
+ - Use `{rounded.none}` for structural page rows, frame edges, grid cells, and structural modules.
590
600
  - Use `{rounded.full}` only for intrinsically circular identity/avatar chrome and compact control marks whose geometry is inherently round or pill-shaped. It never turns a content surface, button, badge, or navigation item into a pill by default.
591
601
 
602
+ The radius scale itself is unchanged: `{rounded.xs}` through `{rounded.3xl}` stay exported for inner marks and for geometry a component owns, such as a progress track or a bar end. Only the rung that surfaces take is fixed.
603
+
592
604
  Public page-grammar cells are not cards and remain square because their parent frame supplies the visual system. Product cards use the resting material role. A details composition may divide its header and bound individual facts with the outlined role; each edge has one owner and fact cells add no elevation. Grouping does not justify another ring around the same container or a stronger shadow.
593
605
 
594
606
  ## Motion
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nadicodeai/design-system",
3
- "version": "7.1.4",
3
+ "version": "8.0.1",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"