@lerianstudio/sindarian-ui 1.4.0-beta.2 → 1.4.0-beta.4

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 (120) hide show
  1. package/dist/components/entity-box/index.d.ts +11 -2
  2. package/dist/components/entity-box/index.d.ts.map +1 -1
  3. package/dist/components/entity-box/index.js +3 -3
  4. package/dist/components/form/input-field/index.d.ts +12 -2
  5. package/dist/components/form/input-field/index.d.ts.map +1 -1
  6. package/dist/components/form/input-field/index.js +29 -5
  7. package/dist/components/form/select-field/index.d.ts +29 -5
  8. package/dist/components/form/select-field/index.d.ts.map +1 -1
  9. package/dist/components/form/select-field/index.js +33 -10
  10. package/dist/components/page-header/index.d.ts +8 -2
  11. package/dist/components/page-header/index.d.ts.map +1 -1
  12. package/dist/components/page-header/index.js +4 -4
  13. package/dist/components/ui/badge/index.d.ts +8 -0
  14. package/dist/components/ui/badge/index.d.ts.map +1 -1
  15. package/dist/components/ui/badge/index.js +9 -1
  16. package/dist/components/ui/form.d.ts +4 -4
  17. package/dist/components/ui/form.d.ts.map +1 -1
  18. package/dist/components/ui/form.js +12 -6
  19. package/dist/components/ui/multiple-select/index.d.ts +11 -3
  20. package/dist/components/ui/multiple-select/index.d.ts.map +1 -1
  21. package/dist/components/ui/select/index.d.ts +5 -0
  22. package/dist/components/ui/select/index.d.ts.map +1 -1
  23. package/dist/components/ui/select/index.js +24 -1
  24. package/dist/domain/blotter/index.d.ts +2 -2
  25. package/dist/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
  26. package/dist/domain/delinquency-aging/aging-buckets.js +1 -1
  27. package/dist/domain/delinquency-aging/index.d.ts.map +1 -1
  28. package/dist/domain/delinquency-aging/index.js +1 -1
  29. package/dist/domain/figure/index.d.ts +11 -9
  30. package/dist/domain/figure/index.d.ts.map +1 -1
  31. package/dist/domain/figure/index.js +8 -8
  32. package/dist/domain/key-id/index.d.ts +1 -1
  33. package/dist/domain/key-id/index.d.ts.map +1 -1
  34. package/dist/domain/key-id/index.js +1 -1
  35. package/dist/domain/section-label/index.d.ts +10 -7
  36. package/dist/domain/section-label/index.d.ts.map +1 -1
  37. package/dist/domain/status-rail/index.d.ts +1 -1
  38. package/dist/domain/status-rail/index.d.ts.map +1 -1
  39. package/dist/domain/status-rail/index.js +8 -4
  40. package/dist/enterprise/alert-banner/index.d.ts +5 -3
  41. package/dist/enterprise/alert-banner/index.d.ts.map +1 -1
  42. package/dist/enterprise/alert-banner/index.js +2 -2
  43. package/dist/enterprise/data-table/column-size.d.ts +70 -0
  44. package/dist/enterprise/data-table/column-size.d.ts.map +1 -0
  45. package/dist/enterprise/data-table/column-size.js +103 -0
  46. package/dist/enterprise/data-table/index.d.ts.map +1 -1
  47. package/dist/enterprise/data-table/index.js +22 -2
  48. package/dist/enterprise/date-range-picker/index.d.ts.map +1 -1
  49. package/dist/enterprise/date-range-picker/index.js +1 -2
  50. package/dist/enterprise/stat-card/index.d.ts +3 -3
  51. package/dist/enterprise/stat-card/index.d.ts.map +1 -1
  52. package/dist/enterprise/stat-card/index.js +1 -1
  53. package/dist/enterprise/status-badge/index.js +1 -1
  54. package/dist/enterprise/virtualized-table/index.d.ts +18 -2
  55. package/dist/enterprise/virtualized-table/index.d.ts.map +1 -1
  56. package/dist/enterprise/virtualized-table/index.js +31 -4
  57. package/dist/esm/components/entity-box/index.d.ts +11 -2
  58. package/dist/esm/components/entity-box/index.d.ts.map +1 -1
  59. package/dist/esm/components/entity-box/index.js +3 -3
  60. package/dist/esm/components/form/input-field/index.d.ts +12 -2
  61. package/dist/esm/components/form/input-field/index.d.ts.map +1 -1
  62. package/dist/esm/components/form/input-field/index.js +29 -5
  63. package/dist/esm/components/form/select-field/index.d.ts +29 -5
  64. package/dist/esm/components/form/select-field/index.d.ts.map +1 -1
  65. package/dist/esm/components/form/select-field/index.js +33 -10
  66. package/dist/esm/components/page-header/index.d.ts +8 -2
  67. package/dist/esm/components/page-header/index.d.ts.map +1 -1
  68. package/dist/esm/components/page-header/index.js +4 -4
  69. package/dist/esm/components/ui/badge/index.d.ts +8 -0
  70. package/dist/esm/components/ui/badge/index.d.ts.map +1 -1
  71. package/dist/esm/components/ui/badge/index.js +9 -1
  72. package/dist/esm/components/ui/form.d.ts +4 -4
  73. package/dist/esm/components/ui/form.d.ts.map +1 -1
  74. package/dist/esm/components/ui/form.js +12 -6
  75. package/dist/esm/components/ui/multiple-select/index.d.ts +11 -3
  76. package/dist/esm/components/ui/multiple-select/index.d.ts.map +1 -1
  77. package/dist/esm/components/ui/select/index.d.ts +5 -0
  78. package/dist/esm/components/ui/select/index.d.ts.map +1 -1
  79. package/dist/esm/components/ui/select/index.js +24 -1
  80. package/dist/esm/domain/blotter/index.d.ts +2 -2
  81. package/dist/esm/domain/delinquency-aging/aging-buckets.d.ts.map +1 -1
  82. package/dist/esm/domain/delinquency-aging/aging-buckets.js +1 -1
  83. package/dist/esm/domain/delinquency-aging/index.d.ts.map +1 -1
  84. package/dist/esm/domain/delinquency-aging/index.js +1 -1
  85. package/dist/esm/domain/figure/index.d.ts +11 -9
  86. package/dist/esm/domain/figure/index.d.ts.map +1 -1
  87. package/dist/esm/domain/figure/index.js +8 -8
  88. package/dist/esm/domain/key-id/index.d.ts +1 -1
  89. package/dist/esm/domain/key-id/index.d.ts.map +1 -1
  90. package/dist/esm/domain/key-id/index.js +1 -1
  91. package/dist/esm/domain/section-label/index.d.ts +10 -7
  92. package/dist/esm/domain/section-label/index.d.ts.map +1 -1
  93. package/dist/esm/domain/status-rail/index.d.ts +1 -1
  94. package/dist/esm/domain/status-rail/index.d.ts.map +1 -1
  95. package/dist/esm/domain/status-rail/index.js +8 -4
  96. package/dist/esm/enterprise/alert-banner/index.d.ts +5 -3
  97. package/dist/esm/enterprise/alert-banner/index.d.ts.map +1 -1
  98. package/dist/esm/enterprise/alert-banner/index.js +2 -2
  99. package/dist/esm/enterprise/data-table/column-size.d.ts +70 -0
  100. package/dist/esm/enterprise/data-table/column-size.d.ts.map +1 -0
  101. package/dist/esm/enterprise/data-table/column-size.js +97 -0
  102. package/dist/esm/enterprise/data-table/index.d.ts.map +1 -1
  103. package/dist/esm/enterprise/data-table/index.js +22 -2
  104. package/dist/esm/enterprise/date-range-picker/index.d.ts.map +1 -1
  105. package/dist/esm/enterprise/date-range-picker/index.js +1 -2
  106. package/dist/esm/enterprise/stat-card/index.d.ts +3 -3
  107. package/dist/esm/enterprise/stat-card/index.d.ts.map +1 -1
  108. package/dist/esm/enterprise/stat-card/index.js +1 -1
  109. package/dist/esm/enterprise/status-badge/index.js +1 -1
  110. package/dist/esm/enterprise/virtualized-table/index.d.ts +18 -2
  111. package/dist/esm/enterprise/virtualized-table/index.d.ts.map +1 -1
  112. package/dist/esm/enterprise/virtualized-table/index.js +31 -4
  113. package/dist/esm/lib/typography.d.ts +21 -6
  114. package/dist/esm/lib/typography.d.ts.map +1 -1
  115. package/dist/esm/lib/typography.js +20 -5
  116. package/dist/globals.css +51 -16
  117. package/dist/lib/typography.d.ts +21 -6
  118. package/dist/lib/typography.d.ts.map +1 -1
  119. package/dist/lib/typography.js +20 -5
  120. package/package.json +1 -1
@@ -112,5 +112,5 @@ export function StatusBadge({ status, label, variantMap, withIcon = false, unkno
112
112
  // The glyph follows the resolved variant; an unknown/non-severity variant has
113
113
  // no cue, so the badge gracefully renders label-only even with withIcon set.
114
114
  const cue = withIcon ? SEVERITY_CUE[variant] : undefined;
115
- return (_jsxs(Badge, { variant: variant, className: cn('gap-1', className), children: [cue ? (_jsxs(_Fragment, { children: [_jsx(cue.Icon, { "aria-hidden": true, className: "size-3.5 shrink-0" }), _jsxs("span", { className: "sr-only", children: [cue.word, ": "] })] })) : null, label ?? humanize(status)] }));
115
+ return (_jsxs(Badge, { variant: variant, className: className, children: [cue ? (_jsxs(_Fragment, { children: [_jsx(cue.Icon, { "aria-hidden": true, className: "size-3.5 shrink-0" }), _jsxs("span", { className: "sr-only", children: [cue.word, ": "] })] })) : null, label ?? humanize(status)] }));
116
116
  }
@@ -1,6 +1,16 @@
1
1
  import { type ColumnDef } from '@tanstack/react-table';
2
2
  export type VirtualizedTableProps<TData> = {
3
- /** Same shape as DataTable: standard TanStack `ColumnDef<T>`. */
3
+ /**
4
+ * Same shape as DataTable: standard TanStack `ColumnDef<T>`. A column that
5
+ * declares none keeps its equal share of the row.
6
+ *
7
+ * Declared sizing does NOT mean the same thing in the kit's two table paths.
8
+ * Here, flex rows PIN all three: `size`, `minSize` and `maxSize` are honoured
9
+ * exactly as declared. DataTable renders real `<th>`/`<td>` under CSS auto
10
+ * table layout, where `size` is only a PREFERRED width, `minSize` a floor,
11
+ * and `maxSize` is ignored outright. A column that must not grow past a width
12
+ * belongs here.
13
+ */
4
14
  columns: ColumnDef<TData, unknown>[];
5
15
  /** The full dataset, already in memory. Only the visible window renders. */
6
16
  data: TData[];
@@ -21,6 +31,12 @@ export type VirtualizedTableProps<TData> = {
21
31
  scrollAreaLabel?: string;
22
32
  /** Applied to the outer wrapper (the scroll container's parent). */
23
33
  className?: string;
34
+ /**
35
+ * Extra classes merged onto every header cell, after the kit label voice —
36
+ * the same seam DataTable exposes, so a screen that switches between the two
37
+ * render paths quiets both column heads with one prop instead of one.
38
+ */
39
+ headClassName?: string;
24
40
  };
25
- export declare function VirtualizedTable<TData>({ columns, data, rowHeight, maxHeight, scrollAreaLabel, className }: VirtualizedTableProps<TData>): import("react").JSX.Element;
41
+ export declare function VirtualizedTable<TData>({ columns, data, rowHeight, maxHeight, scrollAreaLabel, className, headClassName }: VirtualizedTableProps<TData>): import("react").JSX.Element;
26
42
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/virtualized-table/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,uBAAuB,CAAA;AAK9B,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC,iEAAiE;IACjE,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAA;IACpC,4EAA4E;IAC5E,IAAI,EAAE,KAAK,EAAE,CAAA;IACb;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3B,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAKD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,EACtC,OAAO,EACP,IAAI,EACJ,SAAc,EACd,SAAe,EACf,eAAyC,EACzC,SAAS,EACV,EAAE,qBAAqB,CAAC,KAAK,CAAC,+BAiM9B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/enterprise/virtualized-table/index.tsx"],"names":[],"mappings":"AA+BA,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,uBAAuB,CAAA;AAW9B,MAAM,MAAM,qBAAqB,CAAC,KAAK,IAAI;IACzC;;;;;;;;;;OAUG;IACH,OAAO,EAAE,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAA;IACpC,4EAA4E;IAC5E,IAAI,EAAE,KAAK,EAAE,CAAA;IACb;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;IAC3B,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AAKD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,EACtC,OAAO,EACP,IAAI,EACJ,SAAc,EACd,SAAe,EACf,eAAyC,EACzC,SAAS,EACT,aAAa,EACd,EAAE,qBAAqB,CAAC,KAAK,CAAC,+BAkO9B"}
@@ -31,10 +31,12 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
31
31
  import { useEffect, useRef, useState } from 'react';
32
32
  import { flexRender, getCoreRowModel, useReactTable } from '@tanstack/react-table';
33
33
  import { useVirtualizer } from '@tanstack/react-virtual';
34
+ import { LABEL_VOICE_CLASS } from '../../lib/typography.js';
34
35
  import { cn } from '../../lib/utils.js';
36
+ import { readDeclaredColumnSize, readDeclaredGroupSize, UNSIZED_DEFAULT_COLUMN } from '../data-table/column-size.js';
35
37
  /** Rows rendered just outside the viewport to keep fast scrolls smooth. */
36
38
  const OVERSCAN = 8;
37
- export function VirtualizedTable({ columns, data, rowHeight = 40, maxHeight = 480, scrollAreaLabel = 'Scrollable table rows', className }) {
39
+ export function VirtualizedTable({ columns, data, rowHeight = 40, maxHeight = 480, scrollAreaLabel = 'Scrollable table rows', className, headClassName }) {
38
40
  const scrollRef = useRef(null);
39
41
  const [isScrollable, setIsScrollable] = useState(false);
40
42
  // A number is px; a string is used verbatim (e.g. '60vh').
@@ -42,6 +44,10 @@ export function VirtualizedTable({ columns, data, rowHeight = 40, maxHeight = 48
42
44
  const table = useReactTable({
43
45
  data,
44
46
  columns,
47
+ // Keeps `columnDef.size`/`minSize`/`maxSize` meaning "declared" — see
48
+ // ../data-table/column-size. `getSize()` is unaffected; it falls back to
49
+ // the library defaults itself.
50
+ defaultColumn: UNSIZED_DEFAULT_COLUMN,
45
51
  getCoreRowModel: getCoreRowModel()
46
52
  });
47
53
  const rows = table.getRowModel().rows;
@@ -94,11 +100,23 @@ export function VirtualizedTable({ columns, data, rowHeight = 40, maxHeight = 48
94
100
  // its position among its siblings.
95
101
  const firstLeaf = header.column.getLeafColumns()[0];
96
102
  const start = leafPosition.get(firstLeaf?.id ?? header.column.id);
97
- return (_jsx("div", { role: "columnheader", "aria-colindex": (start ?? 0) + 1, "aria-colspan": header.colSpan > 1 ? header.colSpan : undefined, style: { flex: `${header.colSpan} 1 0%` },
103
+ // A group header spans leaf columns whose body cells carry
104
+ // their own widths, so its size comes from those leaves, not
105
+ // from the group def (which declares nothing). A leaf header
106
+ // reads its own column, as before.
107
+ const size = header.subHeaders.length > 0
108
+ ? readDeclaredGroupSize(header.column.getLeafColumns())
109
+ : readDeclaredColumnSize(header.column);
110
+ return (_jsx("div", { role: "columnheader", "aria-colindex": (start ?? 0) + 1, "aria-colspan": header.colSpan > 1 ? header.colSpan : undefined,
111
+ // A declared width must not be flexed away; without one the
112
+ // cell keeps its colSpan share of the row, as before.
113
+ style: size?.width === undefined
114
+ ? { flex: `${header.colSpan} 1 0%`, ...size }
115
+ : { flex: '0 0 auto', ...size },
98
116
  // Header height is independent of rowHeight: pinning it to a
99
117
  // small rowHeight (32) clipped the uppercase label against its
100
118
  // own padding. Padding sizes it; min-h keeps a stable rule.
101
- className: "text-muted-foreground min-h-10 px-4 py-2.5 text-left text-xs font-medium tracking-wide uppercase", children: header.isPlaceholder
119
+ className: cn('min-h-10 px-4 py-2.5 text-left', LABEL_VOICE_CLASS, headClassName), children: header.isPlaceholder
102
120
  ? null
103
121
  : flexRender(header.column.columnDef.header, header.getContext()) }, header.id));
104
122
  }) }, headerGroup.id))) }), _jsx("div", { ref: scrollRef, role: "rowgroup", "data-testid": "virtualized-table-viewport", "aria-label": isScrollable ? scrollAreaLabel : undefined, tabIndex: isScrollable ? 0 : undefined, className: "focus-visible:ring-ring relative overflow-auto focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none", style: { maxHeight: viewportMaxHeight }, children: _jsx("div", { role: "presentation", className: "relative w-full", style: { height: totalSize }, children: virtualRows.map((virtualItem) => {
@@ -106,6 +124,15 @@ export function VirtualizedTable({ columns, data, rowHeight = 40, maxHeight = 48
106
124
  return (_jsx("div", { role: "row", "aria-rowindex": virtualItem.index + headerRowCount + 1, "data-index": virtualItem.index, className: "border-border absolute left-0 flex w-full items-center border-b text-sm", style: {
107
125
  height: virtualItem.size,
108
126
  transform: `translateY(${virtualItem.start}px)`
109
- }, children: row.getVisibleCells().map((cell, i) => (_jsx("div", { role: "cell", "aria-colindex": i + 1, className: "flex-1 truncate px-4", children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))) }, row.id));
127
+ }, children: row.getVisibleCells().map((cell, i) => {
128
+ const size = readDeclaredColumnSize(cell.column);
129
+ return (_jsx("div", { role: "cell", "aria-colindex": i + 1,
130
+ // An inline `flex` beats the class, so a sized column
131
+ // stops flexing while every other column renders
132
+ // exactly as it did before.
133
+ style: size?.width === undefined
134
+ ? size
135
+ : { flex: '0 0 auto', ...size }, className: "flex-1 truncate px-4", children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id));
136
+ }) }, row.id));
110
137
  }) }) })] }) }));
111
138
  }
@@ -1,17 +1,32 @@
1
1
  /**
2
- * THE canonical quiet-label voice: the recessive uppercase-tracked small-caps
3
- * label that lets the loud mono figures dominate. Used by panel headings,
4
- * column heads, key/value labels, captions — anywhere the console needs a
5
- * quiet label.
2
+ * THE canonical quiet-label voice: sentence-case, one step down in size,
3
+ * medium weight, muted ink. Used by column heads, panel headings, key/value
4
+ * labels, captions — anywhere the console needs a quiet label.
5
+ *
6
+ * This is product-console's table-head voice, copied rather than invented. The
7
+ * kit's own `TableHead` paints `text-muted-foreground … font-medium` inside a
8
+ * `text-sm` `Table` (`components/ui/table/index.tsx:20,90`), and
9
+ * product-console renders every data table through that primitive
10
+ * (`src/components/table/data-table.tsx:14`). It replaced the retired "Ledger"
11
+ * voice — `text-[11px] uppercase tracking-[0.08em]` — which shouted a register
12
+ * no sibling console speaks.
6
13
  *
7
14
  * Do NOT re-state the cluster by hand; compose extra classes via
8
15
  * `cn(LABEL_VOICE_CLASS, ...)`.
9
16
  */
10
- export declare const LABEL_VOICE_CLASS = "text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground";
17
+ export declare const LABEL_VOICE_CLASS = "text-sm font-medium text-muted-foreground";
11
18
  /**
12
19
  * Alias of {@link LABEL_VOICE_CLASS} for section headings. Kept as a distinct
13
20
  * name so section-level headings can diverge later without touching every
14
21
  * quiet-label call site.
22
+ *
23
+ * It stays an alias on purpose. product-console's panel/section TITLE voice is
24
+ * `text-muted-foreground text-lg font-medium` (`EntityBoxHeaderTitle`,
25
+ * `components/entity-box/index.tsx:108`) — but that voice already ships as a
26
+ * component, and every live `SectionLabel` call site is a caption or a small
27
+ * heading (a stat-card label, an inline rate label), not an EntityBox-scale
28
+ * panel title. Promoting this constant to `text-lg` would duplicate a voice the
29
+ * kit already owns and inflate those captions.
15
30
  */
16
- export declare const SECTION_LABEL_CLASS = "text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground";
31
+ export declare const SECTION_LABEL_CLASS = "text-sm font-medium text-muted-foreground";
17
32
  //# sourceMappingURL=typography.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"typography.d.ts","sourceRoot":"","sources":["../../../src/lib/typography.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,8EAC+C,CAAA;AAE7E;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,8EAAoB,CAAA"}
1
+ {"version":3,"file":"typography.d.ts","sourceRoot":"","sources":["../../../src/lib/typography.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,8CAA8C,CAAA;AAE5E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,8CAAoB,CAAA"}
@@ -1,16 +1,31 @@
1
1
  /**
2
- * THE canonical quiet-label voice: the recessive uppercase-tracked small-caps
3
- * label that lets the loud mono figures dominate. Used by panel headings,
4
- * column heads, key/value labels, captions — anywhere the console needs a
5
- * quiet label.
2
+ * THE canonical quiet-label voice: sentence-case, one step down in size,
3
+ * medium weight, muted ink. Used by column heads, panel headings, key/value
4
+ * labels, captions — anywhere the console needs a quiet label.
5
+ *
6
+ * This is product-console's table-head voice, copied rather than invented. The
7
+ * kit's own `TableHead` paints `text-muted-foreground … font-medium` inside a
8
+ * `text-sm` `Table` (`components/ui/table/index.tsx:20,90`), and
9
+ * product-console renders every data table through that primitive
10
+ * (`src/components/table/data-table.tsx:14`). It replaced the retired "Ledger"
11
+ * voice — `text-[11px] uppercase tracking-[0.08em]` — which shouted a register
12
+ * no sibling console speaks.
6
13
  *
7
14
  * Do NOT re-state the cluster by hand; compose extra classes via
8
15
  * `cn(LABEL_VOICE_CLASS, ...)`.
9
16
  */
10
- export const LABEL_VOICE_CLASS = 'text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground';
17
+ export const LABEL_VOICE_CLASS = 'text-sm font-medium text-muted-foreground';
11
18
  /**
12
19
  * Alias of {@link LABEL_VOICE_CLASS} for section headings. Kept as a distinct
13
20
  * name so section-level headings can diverge later without touching every
14
21
  * quiet-label call site.
22
+ *
23
+ * It stays an alias on purpose. product-console's panel/section TITLE voice is
24
+ * `text-muted-foreground text-lg font-medium` (`EntityBoxHeaderTitle`,
25
+ * `components/entity-box/index.tsx:108`) — but that voice already ships as a
26
+ * component, and every live `SectionLabel` call site is a caption or a small
27
+ * heading (a stat-card label, an inline rate label), not an EntityBox-scale
28
+ * panel title. Promoting this constant to `text-lg` would duplicate a voice the
29
+ * kit already owns and inflate those captions.
15
30
  */
16
31
  export const SECTION_LABEL_CLASS = LABEL_VOICE_CLASS;
package/dist/globals.css CHANGED
@@ -138,27 +138,27 @@
138
138
  --color-system-error-surface: hsl(var(--system-error-surface));
139
139
  --color-system-error-h1a: hsl(var(--system-error-h1a));
140
140
  --color-system-error-border: hsl(var(--system-error-border));
141
- --color-system-error-text: hsl(var(--system-error-text) / 0.7);
141
+ --color-system-error-text: hsl(var(--system-error-text));
142
142
  --color-system-success: hsl(var(--system-success));
143
143
  --color-system-success-surface: hsl(var(--system-success-surface));
144
144
  --color-system-success-h1a: hsl(var(--system-success-h1a));
145
145
  --color-system-success-border: hsl(var(--system-success-border));
146
- --color-system-success-text: hsl(var(--system-success-text) / 0.7);
146
+ --color-system-success-text: hsl(var(--system-success-text));
147
147
  --color-system-info: hsl(var(--system-info));
148
148
  --color-system-info-surface: hsl(var(--system-info-surface));
149
149
  --color-system-info-h1a: hsl(var(--system-info-h1a));
150
150
  --color-system-info-border: hsl(var(--system-info-border));
151
- --color-system-info-text: hsl(var(--system-info-text) / 0.7);
151
+ --color-system-info-text: hsl(var(--system-info-text));
152
152
  --color-system-alert: hsl(var(--system-alert));
153
153
  --color-system-alert-surface: hsl(var(--system-alert-surface));
154
154
  --color-system-alert-h1a: hsl(var(--system-alert-h1a));
155
155
  --color-system-alert-border: hsl(var(--system-alert-border));
156
- --color-system-alert-text: hsl(var(--system-alert-text) / 0.7);
156
+ --color-system-alert-text: hsl(var(--system-alert-text));
157
157
  --color-system-purple: hsl(var(--system-purple));
158
158
  --color-system-purple-surface: hsl(var(--system-purple-surface));
159
159
  --color-system-purple-h1a: hsl(var(--system-purple-h1a));
160
160
  --color-system-purple-border: hsl(var(--system-purple-border));
161
- --color-system-purple-text: hsl(var(--system-purple-text) / 0.7);
161
+ --color-system-purple-text: hsl(var(--system-purple-text));
162
162
 
163
163
  /* Ledger + reconciliation tokens */
164
164
  --color-credit: hsl(var(--credit));
@@ -243,7 +243,14 @@
243
243
  --muted-foreground: 240 5% 34%; /* base/600 = #52525B */
244
244
  --accent: 56 99% 50%; /* #FEED02 (sunglow) */
245
245
  --accent-foreground: 240 10% 4%; /* base/800 for contrast on yellow */
246
- --destructive: 0 84% 60%; /* red/500 = #EF4444 */
246
+ /*
247
+ Shadcn — Destructive. Darkened one step to red/600. red/500 under white
248
+ was 3.78:1, under AA, for both roles this token plays: the fill beneath
249
+ `--destructive-foreground` (the Critical badge, every destructive
250
+ button) and the plain body ink of a field/form error message on white.
251
+ red/600 lifts both to 4.80:1. The hue is unchanged; only the step moved.
252
+ */
253
+ --destructive: 0 72% 51%; /* red/600 = #DC2626 */
247
254
  --destructive-foreground: 0 0% 100%; /* white */
248
255
  --border: 240 5% 90%; /* base/200 = #E4E4E7 */
249
256
  --input: 0 0% 100%; /* base/white */
@@ -263,27 +270,27 @@
263
270
  --system-error-surface: 0 86% 97%; /* red/50 = #FEF2F2 */
264
271
  --system-error-h1a: 0 74% 35%; /* red/800 = #991B1B */
265
272
  --system-error-border: 0 84% 60% / 0.5; /* #EF4444 50% */
266
- --system-error-text: 0 74% 35%; /* #991B1B - opacity via /70 */
273
+ --system-error-text: 0 74% 35%; /* #991B1B */
267
274
  --system-success: 142 76% 36%; /* green/600 = #16A34A */
268
275
  --system-success-surface: 139 76% 97%; /* green/50 = #F0FDF4 */
269
276
  --system-success-h1a: 143 64% 24%; /* green/800 = #166534 */
270
277
  --system-success-border: 142 76% 36% / 0.5; /* #16A34A 50% */
271
- --system-success-text: 143 64% 24%; /* #166534 - opacity via /70 */
278
+ --system-success-text: 143 64% 24%; /* #166534 */
272
279
  --system-info: 221 83% 53%; /* blue/600 = #2563EB */
273
280
  --system-info-surface: 214 100% 97%; /* blue/50 = #EFF6FF */
274
281
  --system-info-h1a: 224 76% 40%; /* blue/800 = #1E40AF */
275
282
  --system-info-border: 221 83% 53% / 0.5; /* #2563EB 50% */
276
- --system-info-text: 224 76% 40%; /* #1E40AF - opacity via /70 */
283
+ --system-info-text: 224 76% 40%; /* #1E40AF */
277
284
  --system-alert: 48 96% 47%; /* yellow/500 = #EAB308 */
278
285
  --system-alert-surface: 55 92% 95%; /* yellow/50 = #FEFCE8 */
279
286
  --system-alert-h1a: 36 92% 29%; /* yellow/800 = #854D0E */
280
287
  --system-alert-border: 48 96% 47% / 0.5; /* #EAB308 50% */
281
- --system-alert-text: 36 92% 29%; /* #854D0E - opacity via /70 */
288
+ --system-alert-text: 36 92% 29%; /* #854D0E */
282
289
  --system-purple: 271 81% 56%; /* purple/600 = #9333EA */
283
290
  --system-purple-surface: 270 100% 98%; /* purple/50 = #FAF5FF */
284
291
  --system-purple-h1a: 273 67% 39%; /* purple/800 = #6B21A8 */
285
292
  --system-purple-border: 271 81% 56% / 0.5; /* #9333EA 50% */
286
- --system-purple-text: 273 67% 39%; /* #6B21A8 - opacity via /70 */
293
+ --system-purple-text: 273 67% 39%; /* #6B21A8 */
287
294
 
288
295
  /* Shadow color token for dark mode adaptation */
289
296
  --shadow-color: 0 0% 0%;
@@ -377,35 +384,35 @@
377
384
  /* Shadcn — System Error */
378
385
  --system-error: 0 91% 71%; /* red/400 = #F87171 */
379
386
  --system-error-surface: 0 75% 15%; /* red/950 = #450A0A */
380
- --system-error-text: 0 94% 82%; /* red/300 = #FCA5A5 - opacity via /70 */
387
+ --system-error-text: 0 94% 82%; /* red/300 = #FCA5A5 */
381
388
  --system-error-h1a: 0 96% 89%; /* red/200 = #FECACA */
382
389
  --system-error-border: 0 94% 82% / 0.3; /* #FCA5A5 30% */
383
390
 
384
391
  /* Shadcn — System Success */
385
392
  --system-success: 142 69% 58%; /* green/400 = #4ADE80 */
386
393
  --system-success-surface: 145 80% 10%; /* green/950 = #052E16 */
387
- --system-success-text: 142 77% 73%; /* green/300 = #86EFAC - opacity via /70 */
394
+ --system-success-text: 142 77% 73%; /* green/300 = #86EFAC */
388
395
  --system-success-h1a: 141 79% 85%; /* green/200 = #BBF7D0 */
389
396
  --system-success-border: 142 69% 58% / 0.3; /* #4ADE80 30% */
390
397
 
391
398
  /* Shadcn — System Info */
392
399
  --system-info: 213 94% 68%; /* blue/400 = #60A5FA */
393
400
  --system-info-surface: 226 57% 21%; /* blue/950 = #172554 */
394
- --system-info-text: 212 96% 78%; /* blue/300 = #93C5FD - opacity via /70 */
401
+ --system-info-text: 212 96% 78%; /* blue/300 = #93C5FD */
395
402
  --system-info-h1a: 213 97% 87%; /* blue/200 = #BFDBFE */
396
403
  --system-info-border: 213 94% 68% / 0.3; /* #60A5FA 30% */
397
404
 
398
405
  /* Shadcn — System Alert */
399
406
  --system-alert: 48 96% 53%; /* yellow/400 = #FACC15 */
400
407
  --system-alert-surface: 26 83% 14%; /* yellow/950 = #422006 */
401
- --system-alert-text: 48 97% 77%; /* yellow/300 = #FDE68A - opacity via /70 */
408
+ --system-alert-text: 48 97% 77%; /* yellow/300 = #FDE68A */
402
409
  --system-alert-h1a: 53 98% 77%; /* yellow/200 = #FEF08A */
403
410
  --system-alert-border: 48 96% 53% / 0.3; /* #FACC15 30% */
404
411
 
405
412
  /* Shadcn — System Purple */
406
413
  --system-purple: 270 95% 75%; /* purple/400 = #C084FC */
407
414
  --system-purple-surface: 266 86% 13%; /* purple/950 = #3B0764 */
408
- --system-purple-text: 269 97% 85%; /* purple/300 = #D8B4FE - opacity via /70 */
415
+ --system-purple-text: 269 97% 85%; /* purple/300 = #D8B4FE */
409
416
  --system-purple-h1a: 269 100% 92%; /* purple/200 = #E9D5FF */
410
417
  --system-purple-border: 270 95% 75% / 0.3; /* #C084FC 30% */
411
418
 
@@ -604,3 +611,31 @@
604
611
  mask: radial-gradient(21px 13px at 50% 102%, #0000 98%, #000) 50%
605
612
  calc(100% - 16px) / 64px 100% repeat-x;
606
613
  }
614
+
615
+ /*
616
+ Reduced-motion floor.
617
+
618
+ Every animated surface in the kit already carries a `motion-safe:` variant,
619
+ but that variant is a Tailwind utility: it only becomes
620
+ `@media (prefers-reduced-motion: no-preference)` after the CONSUMER compiles
621
+ Tailwind over the kit's dist. A consumer whose content globs miss a file, one
622
+ on an older kit, or one who writes `animate-in` in its own code gets no guard
623
+ at all — which is why `grep prefers-reduced-motion` over the shipped
624
+ stylesheet found nothing to point at.
625
+
626
+ This block is plain CSS with no variant and no build step between it and the
627
+ reader, and it ships verbatim (`copy:styles` copies every .css under src).
628
+ Animation
629
+ is dropped rather than shortened, so an overlay renders its final geometry
630
+ immediately; Radix reads a computed `animation-name: none` as "nothing to wait
631
+ for" and unmounts on close instead of hanging on an `animationend` that never
632
+ fires. Transitions are deliberately left alone: hover and focus affordances
633
+ are feedback, not motion effects.
634
+ */
635
+ @media (prefers-reduced-motion: reduce) {
636
+ [class*='animate-'],
637
+ [data-state='open'],
638
+ [data-state='closed'] {
639
+ animation: none !important;
640
+ }
641
+ }
@@ -1,17 +1,32 @@
1
1
  /**
2
- * THE canonical quiet-label voice: the recessive uppercase-tracked small-caps
3
- * label that lets the loud mono figures dominate. Used by panel headings,
4
- * column heads, key/value labels, captions — anywhere the console needs a
5
- * quiet label.
2
+ * THE canonical quiet-label voice: sentence-case, one step down in size,
3
+ * medium weight, muted ink. Used by column heads, panel headings, key/value
4
+ * labels, captions — anywhere the console needs a quiet label.
5
+ *
6
+ * This is product-console's table-head voice, copied rather than invented. The
7
+ * kit's own `TableHead` paints `text-muted-foreground … font-medium` inside a
8
+ * `text-sm` `Table` (`components/ui/table/index.tsx:20,90`), and
9
+ * product-console renders every data table through that primitive
10
+ * (`src/components/table/data-table.tsx:14`). It replaced the retired "Ledger"
11
+ * voice — `text-[11px] uppercase tracking-[0.08em]` — which shouted a register
12
+ * no sibling console speaks.
6
13
  *
7
14
  * Do NOT re-state the cluster by hand; compose extra classes via
8
15
  * `cn(LABEL_VOICE_CLASS, ...)`.
9
16
  */
10
- export declare const LABEL_VOICE_CLASS = "text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground";
17
+ export declare const LABEL_VOICE_CLASS = "text-sm font-medium text-muted-foreground";
11
18
  /**
12
19
  * Alias of {@link LABEL_VOICE_CLASS} for section headings. Kept as a distinct
13
20
  * name so section-level headings can diverge later without touching every
14
21
  * quiet-label call site.
22
+ *
23
+ * It stays an alias on purpose. product-console's panel/section TITLE voice is
24
+ * `text-muted-foreground text-lg font-medium` (`EntityBoxHeaderTitle`,
25
+ * `components/entity-box/index.tsx:108`) — but that voice already ships as a
26
+ * component, and every live `SectionLabel` call site is a caption or a small
27
+ * heading (a stat-card label, an inline rate label), not an EntityBox-scale
28
+ * panel title. Promoting this constant to `text-lg` would duplicate a voice the
29
+ * kit already owns and inflate those captions.
15
30
  */
16
- export declare const SECTION_LABEL_CLASS = "text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground";
31
+ export declare const SECTION_LABEL_CLASS = "text-sm font-medium text-muted-foreground";
17
32
  //# sourceMappingURL=typography.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"typography.d.ts","sourceRoot":"","sources":["../../src/lib/typography.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,iBAAiB,8EAC+C,CAAA;AAE7E;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,8EAAoB,CAAA"}
1
+ {"version":3,"file":"typography.d.ts","sourceRoot":"","sources":["../../src/lib/typography.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,8CAA8C,CAAA;AAE5E;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,8CAAoB,CAAA"}
@@ -2,18 +2,33 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SECTION_LABEL_CLASS = exports.LABEL_VOICE_CLASS = void 0;
4
4
  /**
5
- * THE canonical quiet-label voice: the recessive uppercase-tracked small-caps
6
- * label that lets the loud mono figures dominate. Used by panel headings,
7
- * column heads, key/value labels, captions — anywhere the console needs a
8
- * quiet label.
5
+ * THE canonical quiet-label voice: sentence-case, one step down in size,
6
+ * medium weight, muted ink. Used by column heads, panel headings, key/value
7
+ * labels, captions — anywhere the console needs a quiet label.
8
+ *
9
+ * This is product-console's table-head voice, copied rather than invented. The
10
+ * kit's own `TableHead` paints `text-muted-foreground … font-medium` inside a
11
+ * `text-sm` `Table` (`components/ui/table/index.tsx:20,90`), and
12
+ * product-console renders every data table through that primitive
13
+ * (`src/components/table/data-table.tsx:14`). It replaced the retired "Ledger"
14
+ * voice — `text-[11px] uppercase tracking-[0.08em]` — which shouted a register
15
+ * no sibling console speaks.
9
16
  *
10
17
  * Do NOT re-state the cluster by hand; compose extra classes via
11
18
  * `cn(LABEL_VOICE_CLASS, ...)`.
12
19
  */
13
- exports.LABEL_VOICE_CLASS = 'text-[11px] font-medium uppercase tracking-[0.08em] text-muted-foreground';
20
+ exports.LABEL_VOICE_CLASS = 'text-sm font-medium text-muted-foreground';
14
21
  /**
15
22
  * Alias of {@link LABEL_VOICE_CLASS} for section headings. Kept as a distinct
16
23
  * name so section-level headings can diverge later without touching every
17
24
  * quiet-label call site.
25
+ *
26
+ * It stays an alias on purpose. product-console's panel/section TITLE voice is
27
+ * `text-muted-foreground text-lg font-medium` (`EntityBoxHeaderTitle`,
28
+ * `components/entity-box/index.tsx:108`) — but that voice already ships as a
29
+ * component, and every live `SectionLabel` call site is a caption or a small
30
+ * heading (a stat-card label, an inline rate label), not an EntityBox-scale
31
+ * panel title. Promoting this constant to `text-lg` would duplicate a voice the
32
+ * kit already owns and inflate those captions.
18
33
  */
19
34
  exports.SECTION_LABEL_CLASS = exports.LABEL_VOICE_CLASS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lerianstudio/sindarian-ui",
3
- "version": "1.4.0-beta.2",
3
+ "version": "1.4.0-beta.4",
4
4
  "description": "Sindarian UI - A UI library for Midaz Console",
5
5
  "license": "ISC",
6
6
  "author": {