@loworbitstudio/visor 1.5.0 → 1.6.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "0.4.0",
3
- "generated_at": "2026-06-04T00:42:59.544Z",
3
+ "generated_at": "2026-06-11T14:53:30.668Z",
4
4
  "components": {
5
5
  "accessibility-specimen": {
6
6
  "category": "specimen",
@@ -164,15 +164,16 @@
164
164
  "variant": [
165
165
  "default",
166
166
  "compact",
167
- "timeline"
167
+ "timeline",
168
+ "compact-3col"
168
169
  ]
169
170
  },
170
171
  "props": [
171
172
  {
172
173
  "name": "variant",
173
- "type": "'default' | 'compact' | 'timeline'",
174
+ "type": "'default' | 'compact' | 'timeline' | 'compact-3col'",
174
175
  "default": "default",
175
- "description": "Display mode. Default is padded rows with borders, compact is denser, timeline adds a connecting rail between leading indicators."
176
+ "description": "Display mode. Default is padded rows with borders, compact is denser, timeline adds a connecting rail between leading indicators, compact-3col pins timestamp to the leftmost column with [time][dot][text] layout."
176
177
  },
177
178
  {
178
179
  "name": "children",
@@ -182,6 +183,7 @@
182
183
  ],
183
184
  "dependencies": [],
184
185
  "tokens_used": [
186
+ "--af-time-col",
185
187
  "--border-default",
186
188
  "--border-muted",
187
189
  "--font-size-sm",
@@ -378,6 +380,7 @@
378
380
  "class-variance-authority"
379
381
  ],
380
382
  "tokens_used": [
383
+ "--badge-text-transform",
381
384
  "--border-default",
382
385
  "--border-focus",
383
386
  "--color-neutral-600",
@@ -899,6 +902,12 @@
899
902
  "default": "false",
900
903
  "description": "Render inline (non-sticky) instead of fixed to the viewport bottom."
901
904
  },
905
+ {
906
+ "name": "flat",
907
+ "type": "boolean",
908
+ "default": "false",
909
+ "description": "Render flat — no shadow, no border-radius, border-top only. Use inside table cards or panels where the floating card look is wrong."
910
+ },
902
911
  {
903
912
  "name": "label",
904
913
  "type": "(count: number) => React.ReactNode",
@@ -1039,7 +1048,7 @@
1039
1048
  "--interactive-secondary-text",
1040
1049
  "--motion-duration-150",
1041
1050
  "--motion-easing-default",
1042
- "--opacity-50",
1051
+ "--opacity-40",
1043
1052
  "--primary",
1044
1053
  "--radius-md",
1045
1054
  "--spacing-2",
@@ -1538,6 +1547,12 @@
1538
1547
  "type": "\"primary\" | \"neutral\"",
1539
1548
  "default": "\"neutral\"",
1540
1549
  "description": "Tone for the count pill. \"neutral\" uses muted surface; \"primary\" uses accent surface. Auto re-tones on selected state."
1550
+ },
1551
+ {
1552
+ "name": "selectedTreatment",
1553
+ "type": "\"accent\" | \"neutral\"",
1554
+ "default": "\"accent\"",
1555
+ "description": "Selected-state visual treatment. \"accent\" (default) uses accent-tinted bg + accent border + link text. \"neutral\" uses --surface-card bg + neutral border + primary text; the count pill renders as a solid mint pill (--surface-success-default) when selected. Use in editorial/admin contexts where accent bleed is undesirable.\n"
1541
1556
  }
1542
1557
  ]
1543
1558
  }
@@ -1549,6 +1564,7 @@
1549
1564
  "tokens_used": [
1550
1565
  "--border-default",
1551
1566
  "--border-focus",
1567
+ "--border-strong",
1552
1568
  "--focus-ring-offset",
1553
1569
  "--focus-ring-width",
1554
1570
  "--font-body",
@@ -1570,6 +1586,8 @@
1570
1586
  "--surface-card",
1571
1587
  "--surface-interactive-hover",
1572
1588
  "--surface-muted",
1589
+ "--surface-success-default",
1590
+ "--text-inverse",
1573
1591
  "--text-link",
1574
1592
  "--text-primary",
1575
1593
  "--text-secondary"
@@ -2642,7 +2660,7 @@
2642
2660
  "name": "density",
2643
2661
  "type": "\"compact\" | \"default\" | \"editorial\"",
2644
2662
  "default": "\"default\"",
2645
- "description": "Vertical row padding step. Maps to a `data-density` attribute on the root, which sets the `--dt-row-py` custom property the table's cells consume. `\"compact\"` = 8px (sub-content density: long lists, narrow viewports). `\"default\"` = 12px (current behaviour; backward-compatible with consumers that don't pass the prop). `\"editorial\"` = 20px (generous; each row reads as a card; high-design admin patterns). Themes can override per-density values without forking the component by targeting `[data-density=\"…\"]` from their own selector.\n"
2663
+ "description": "Vertical row padding step. Maps to a `data-density` attribute on the root, which sets the `--dt-row-py` custom property the table's cells consume. `\"compact\"` = 8px (sub-content density: long lists, narrow viewports). `\"default\"` = 12px (current behaviour; backward-compatible with consumers that don't pass the prop). `\"editorial\"` = 20px (generous; each row reads as a card; high-design admin patterns) — column headers also receive the editorial treatment: uppercase, `--font-size-xs` (~11px), `--text-tertiary` color, and `letter-spacing: 0.08em`. Themes can override per-density values without forking the component by targeting `[data-density=\"…\"]` from their own selector.\n"
2646
2664
  },
2647
2665
  {
2648
2666
  "name": "rowTone",
@@ -2663,6 +2681,7 @@
2663
2681
  "tokens_used": [
2664
2682
  "--border-default",
2665
2683
  "--border-strong",
2684
+ "--data-table-sort-bar-radius",
2666
2685
  "--dt-row-py",
2667
2686
  "--focus-ring-color",
2668
2687
  "--focus-ring-offset",
@@ -2674,6 +2693,7 @@
2674
2693
  "--line-height-tight",
2675
2694
  "--motion-duration-fast",
2676
2695
  "--motion-easing-standard",
2696
+ "--radius-lg",
2677
2697
  "--radius-md",
2678
2698
  "--radius-sm",
2679
2699
  "--spacing-1",
@@ -3969,6 +3989,103 @@
3969
3989
  ],
3970
3990
  "example": "<Image\n src=\"/photos/hero.jpg\"\n alt=\"Mountain landscape\"\n aspectRatio=\"video\"\n/>\n\n<Image\n src={user.avatar}\n alt={user.name}\n aspectRatio=\"square\"\n objectFit=\"cover\"\n fallback={<span>No photo</span>}\n/>\n"
3971
3991
  },
3992
+ "infographic-bar": {
3993
+ "category": "admin",
3994
+ "description": "Composable continuous stat-card band. Lays out N stat-cards as a single infographic strip — outer corners rounded, inner corners square, hairline dividers, no full per-card borders.",
3995
+ "when_to_use": [
3996
+ "Rendering a KPI/metric row that should read as ONE continuous band, not separate bordered cards",
3997
+ "Admin dashboard summary strips where several metrics share a single framed surface",
3998
+ "Theme-portable metric rows that must look right in both bordered and borderless palettes"
3999
+ ],
4000
+ "when_not_to_use": [
4001
+ "Showing a single metric (use StatCard directly)",
4002
+ "Metrics that each need their own card with its own border and elevation (compose StatCards in a grid instead)",
4003
+ "Tabular metrics across many rows (use DataTable)",
4004
+ "Marketing feature tiles (use a marketing card pattern)"
4005
+ ],
4006
+ "props": [
4007
+ {
4008
+ "name": "stats",
4009
+ "type": "InfographicBarStat[]",
4010
+ "required": true,
4011
+ "description": "Ordered stat cells, rendered left-to-right as a single continuous band. Each item is a subset of StatCardProps."
4012
+ },
4013
+ {
4014
+ "name": "stats[].label",
4015
+ "type": "React.ReactNode",
4016
+ "required": true,
4017
+ "description": "Small uppercase label describing the metric."
4018
+ },
4019
+ {
4020
+ "name": "stats[].value",
4021
+ "type": "React.ReactNode",
4022
+ "required": true,
4023
+ "description": "Prominent metric value."
4024
+ },
4025
+ {
4026
+ "name": "stats[].delta",
4027
+ "type": "StatCardDelta",
4028
+ "description": "Change indicator with value, direction (\"up\" | \"down\" | \"flat\"), and optional label."
4029
+ },
4030
+ {
4031
+ "name": "stats[].trend",
4032
+ "type": "React.ReactNode",
4033
+ "description": "Slot for a sparkline, chart, or icon."
4034
+ },
4035
+ {
4036
+ "name": "stats[].trendPosition",
4037
+ "type": "'header' | 'footer'",
4038
+ "default": "footer",
4039
+ "description": "Where the trend slot renders within the cell."
4040
+ },
4041
+ {
4042
+ "name": "stats[].footer",
4043
+ "type": "React.ReactNode",
4044
+ "description": "Sublabel or link rendered beneath the value."
4045
+ },
4046
+ {
4047
+ "name": "stats[].variant",
4048
+ "type": "'default' | 'highlight'",
4049
+ "default": "default",
4050
+ "description": "Per-cell visual emphasis. Highlight tints that cell's surface."
4051
+ },
4052
+ {
4053
+ "name": "stats[].valueAs",
4054
+ "type": "'default' | 'hero' | 'compact'",
4055
+ "default": "default",
4056
+ "description": "Typography scale for the cell value."
4057
+ },
4058
+ {
4059
+ "name": "stats[].id",
4060
+ "type": "string",
4061
+ "description": "Stable React key for the cell. Falls back to the array index when omitted."
4062
+ },
4063
+ {
4064
+ "name": "size",
4065
+ "type": "'sm' | 'md'",
4066
+ "default": "md",
4067
+ "description": "Dimensional density forwarded to every cell."
4068
+ },
4069
+ {
4070
+ "name": "className",
4071
+ "type": "string",
4072
+ "description": "Additional CSS class names merged onto the band element."
4073
+ }
4074
+ ],
4075
+ "dependencies": [
4076
+ "stat-card"
4077
+ ],
4078
+ "tokens_used": [
4079
+ "--border-default",
4080
+ "--hairline",
4081
+ "--infographic-bar-divider",
4082
+ "--radius-lg",
4083
+ "--shadow-xs",
4084
+ "--stroke-width-thin",
4085
+ "--surface-card"
4086
+ ],
4087
+ "example": "<InfographicBar\n stats={[\n { label: \"Total Revenue\", value: \"$48,120\", delta: { value: \"+12.4%\", direction: \"up\", label: \"vs last month\" } },\n { label: \"Active Users\", value: \"892\", delta: { value: \"+3.1%\", direction: \"up\" } },\n { label: \"Churn Rate\", value: \"3.2%\", delta: { value: \"-0.4%\", direction: \"down\" } },\n { label: \"Signups\", value: \"412\", variant: \"highlight\" },\n ]}\n/>\n"
4088
+ },
3972
4089
  "inline": {
3973
4090
  "category": "layout",
3974
4091
  "description": "Horizontal flex container with token-driven gap, alignment, optional wrap, and `as` polymorphism.",
@@ -4425,6 +4542,73 @@
4425
4542
  ],
4426
4543
  "example": "<Marquee\n items={['Acme Corp', 'Vercel', 'Low Orbit Studio', 'Figma', 'Notion']}\n durationSec={20}\n separator=\"·\"\n/>\n\n<Marquee\n bands={[\n { items: clients, direction: 'left', durationSec: 40, separator: '●' },\n { items: clientsReversed, direction: 'right', durationSec: 50, separator: '○' },\n ]}\n pauseOnHover\n gap=\"2.5rem\"\n/>\n"
4427
4544
  },
4545
+ "matrix-table": {
4546
+ "category": "admin",
4547
+ "description": "A fixed assignment grid component for members×roles patterns. Sticky-left identity column, centered boolean cells (22px filled-success check when active / muted empty when not), and multi-line centered column headers (label over count) that opt out of the uppercase header treatment. No list machinery — no selection column, no sort buttons, no pagination footer.",
4548
+ "when_to_use": [
4549
+ "Displaying a members × roles assignment matrix in organization settings",
4550
+ "Any fixed grid where rows are identities (users, items) and columns are boolean attributes (permissions, roles, features)",
4551
+ "When the shape is a matrix, not a sortable/pageable list — where DataTable's list machinery would fight the layout"
4552
+ ],
4553
+ "when_not_to_use": [
4554
+ "Sortable, paginated lists of records (use DataTable)",
4555
+ "Editable grids with input cells (extend or build a dedicated grid)",
4556
+ "Simple key-value tables (use the Table primitive directly)"
4557
+ ],
4558
+ "variants": {},
4559
+ "props": [
4560
+ {
4561
+ "name": "columns",
4562
+ "type": "MatrixColumn[]",
4563
+ "required": true,
4564
+ "description": "Column definitions. Each column has an `id`, `label`, and optional `count` sub-label rendered below the label in the header."
4565
+ },
4566
+ {
4567
+ "name": "rows",
4568
+ "type": "MatrixRow<TIdentity>[]",
4569
+ "required": true,
4570
+ "description": "Row data. Each row has an `id`, an `identity` value passed to `renderIdentity`, an `activeColumns` set/array of column ids that should show the active check indicator, and an optional `cells` map of per-column values. A `cells` entry (`string | boolean`) overrides `activeColumns` for that column — `true`/`false` render the boolean indicator, a `string` renders as plain text in the standard cell style."
4571
+ },
4572
+ {
4573
+ "name": "renderIdentity",
4574
+ "type": "(identity: TIdentity) => React.ReactNode",
4575
+ "required": true,
4576
+ "description": "Render slot for the sticky-left identity cell. Receives the row's `identity` value — typically renders a name, avatar+name, or any identity compound."
4577
+ },
4578
+ {
4579
+ "name": "aria-label",
4580
+ "type": "string",
4581
+ "description": "Accessible label for the table element."
4582
+ }
4583
+ ],
4584
+ "dependencies": [
4585
+ "@phosphor-icons/react",
4586
+ "@loworbitstudio/visor-core"
4587
+ ],
4588
+ "tokens_used": [
4589
+ "--border-default",
4590
+ "--font-size-sm",
4591
+ "--font-weight-medium",
4592
+ "--font-weight-normal",
4593
+ "--line-height-tight",
4594
+ "--motion-duration-fast",
4595
+ "--motion-easing-standard",
4596
+ "--radius-full",
4597
+ "--radius-lg",
4598
+ "--shadow-sm",
4599
+ "--spacing-1",
4600
+ "--spacing-2",
4601
+ "--spacing-3",
4602
+ "--stroke-width-thin",
4603
+ "--surface-card",
4604
+ "--surface-muted",
4605
+ "--surface-success-default",
4606
+ "--text-inverse",
4607
+ "--text-primary",
4608
+ "--text-tertiary"
4609
+ ],
4610
+ "example": "const columns: MatrixColumn[] = [\n { id: 'admin', label: 'Admin', count: 3 },\n { id: 'editor', label: 'Editor', count: 5 },\n { id: 'viewer', label: 'Viewer', count: 12 },\n]\n\nconst rows: MatrixRow<{ name: string; email: string }>[] = [\n { id: '1', identity: { name: 'Ada Lovelace', email: 'ada@example.com' }, activeColumns: new Set(['admin', 'editor']) },\n { id: '2', identity: { name: 'Grace Hopper', email: 'grace@example.com' }, activeColumns: ['viewer'] },\n // Mixed string + boolean cells via `cells` (string renders as plain text):\n { id: '3', identity: { name: 'Storage', email: '' }, activeColumns: [], cells: { admin: '50GB', editor: true, viewer: false } },\n]\n\n<MatrixTable\n columns={columns}\n rows={rows}\n renderIdentity={(identity) => <span>{identity.name}</span>}\n aria-label=\"Member role assignments\"\n/>\n"
4611
+ },
4428
4612
  "menubar": {
4429
4613
  "category": "overlay",
4430
4614
  "description": "Horizontal menu bar with dropdown menus, keyboard navigation, and full a11y support.",
@@ -5001,6 +5185,11 @@
5001
5185
  "name": "titleFamily",
5002
5186
  "type": "'heading' | 'display' | string",
5003
5187
  "description": "Title font-family override. `\"heading\"` and `\"display\"` are tokens that map to `data-title-family` attributes; `\"display\"` resolves to `var(--font-display, var(--font-family-heading, inherit))` so themes without a display font degrade to the heading family. Any other string is forwarded as a raw CSS family on an inline `--page-header-title-family` declaration.\n"
5188
+ },
5189
+ {
5190
+ "name": "leading",
5191
+ "type": "string | number",
5192
+ "description": "Title line-height override, forwarded as an inline `--page-header-title-leading` custom property (a unitless number like `1.05` or any CSS length). When omitted the title keeps its default line-height (tight for the standard title, `1` for the marquee scale), so existing call sites render unchanged.\n"
5004
5193
  }
5005
5194
  ],
5006
5195
  "dependencies": [
@@ -5021,6 +5210,7 @@
5021
5210
  "--line-height-relaxed",
5022
5211
  "--line-height-tight",
5023
5212
  "--page-header-title-family",
5213
+ "--page-header-title-leading",
5024
5214
  "--page-header-title-size",
5025
5215
  "--spacing-1",
5026
5216
  "--spacing-2",
@@ -5758,6 +5948,86 @@
5758
5948
  ],
5759
5949
  "example": "<SectionHeader title=\"Tonight's events\" meta=\"2 events\" />\n<SectionHeader title=\"Activity\" meta=\"last hour\" />\n<SectionHeader title=\"Top promoters · 30d\" />\n"
5760
5950
  },
5951
+ "section-nav": {
5952
+ "category": "navigation",
5953
+ "description": "A link/anchor-based section sub-navigation strip — a leading Phosphor icon + label + optional trailing count pill per item, with a static 2px primary underline on the active item. Items navigate via href (use `asChild` with `next/link` for client-side routing). Distinct from Tabs — no button triggers, no content panels, no animated indicator.",
5954
+ "when_to_use": [
5955
+ "A sub-navigation strip across the top of a detail view whose tabs are real routes (e.g. Organization → Detail / Roles / Invites)",
5956
+ "When each section is its own URL and you want client-side navigation via next/link rather than in-page panel switching",
5957
+ "When sections carry a count (member count, pending invites) you want to surface in a trailing pill"
5958
+ ],
5959
+ "when_not_to_use": [
5960
+ "In-page panel switching where the content lives on the same route (use Tabs)",
5961
+ "Top-level site navigation with brand + actions (use Navbar)",
5962
+ "Paginated record lists (use Pagination)"
5963
+ ],
5964
+ "variants": {},
5965
+ "props": [
5966
+ {
5967
+ "name": "label",
5968
+ "type": "React.ReactNode",
5969
+ "required": true,
5970
+ "description": "The item's visible label text. (SectionNavItem)"
5971
+ },
5972
+ {
5973
+ "name": "href",
5974
+ "type": "string",
5975
+ "description": "Destination URL. Applied directly when not using `asChild`. (SectionNavItem)"
5976
+ },
5977
+ {
5978
+ "name": "icon",
5979
+ "type": "Icon",
5980
+ "description": "Leading Phosphor icon component (e.g. `UsersIcon`). (SectionNavItem)"
5981
+ },
5982
+ {
5983
+ "name": "count",
5984
+ "type": "number",
5985
+ "description": "Optional trailing count pill value. `0` is rendered; `undefined`/`null` hides the pill. (SectionNavItem)"
5986
+ },
5987
+ {
5988
+ "name": "isActive",
5989
+ "type": "boolean",
5990
+ "default": "false",
5991
+ "description": "Marks the item as the current section — text-primary, 2px primary underline, primary-tinted count pill, and `aria-current=\"page\"`. (SectionNavItem)"
5992
+ },
5993
+ {
5994
+ "name": "asChild",
5995
+ "type": "boolean",
5996
+ "default": "false",
5997
+ "description": "Merge the item's chrome onto the immediate child element instead of rendering an `<a>`. Use with `next/link` for client-side navigation. (SectionNavItem)"
5998
+ }
5999
+ ],
6000
+ "dependencies": [
6001
+ "@radix-ui/react-slot",
6002
+ "@phosphor-icons/react",
6003
+ "@loworbitstudio/visor-core"
6004
+ ],
6005
+ "tokens_used": [
6006
+ "--border-default",
6007
+ "--border-focus",
6008
+ "--focus-ring-offset",
6009
+ "--focus-ring-width",
6010
+ "--font-size-sm",
6011
+ "--font-size-xs",
6012
+ "--font-weight-medium",
6013
+ "--line-height-tight",
6014
+ "--motion-duration-fast",
6015
+ "--motion-easing-standard",
6016
+ "--primary",
6017
+ "--radius-full",
6018
+ "--radius-sm",
6019
+ "--spacing-1",
6020
+ "--spacing-2",
6021
+ "--spacing-3",
6022
+ "--stroke-width-thin",
6023
+ "--surface-accent-subtle",
6024
+ "--surface-muted",
6025
+ "--text-link",
6026
+ "--text-primary",
6027
+ "--text-secondary"
6028
+ ],
6029
+ "example": "import Link from 'next/link'\nimport { UsersIcon, ShieldIcon, EnvelopeIcon } from '@phosphor-icons/react'\nimport { SectionNav, SectionNavItem } from '@/components/ui/section-nav/section-nav'\n\n<SectionNav aria-label=\"Organization sections\">\n <SectionNavItem asChild isActive icon={UsersIcon} label=\"Detail\">\n <Link href=\"/org/detail\" />\n </SectionNavItem>\n <SectionNavItem asChild icon={ShieldIcon} label=\"Roles\" count={4}>\n <Link href=\"/org/roles\" />\n </SectionNavItem>\n <SectionNavItem asChild icon={EnvelopeIcon} label=\"Invites\" count={2}>\n <Link href=\"/org/invites\" />\n </SectionNavItem>\n</SectionNav>\n"
6030
+ },
5761
6031
  "select": {
5762
6032
  "category": "form",
5763
6033
  "description": "An accessible select component built on Radix UI Select with all sub-components.",
@@ -7055,6 +7325,57 @@
7055
7325
  ],
7056
7326
  "example": "<SurfaceRow token=\"--surface-card\" name=\"Card\" />\n<SurfaceRow token=\"--surface-overlay\" name=\"Overlay\" lightText />\n"
7057
7327
  },
7328
+ "surface-scale-stack": {
7329
+ "category": "specimen",
7330
+ "description": "Multi-tier stacked surface aggregator block. Composes ordered SurfaceRow specimens into a rounded vertical stack with an optional use-note column.",
7331
+ "when_to_use": [
7332
+ "Documenting a full surface scale (e.g. page → screen → panel → panel-2 → panel-3)",
7333
+ "Design system foundation pages showing tier hierarchy",
7334
+ "Theme validation for a complete surface token set"
7335
+ ],
7336
+ "when_not_to_use": [
7337
+ "Displaying a single surface tier (use SurfaceRow)",
7338
+ "Actual page or card surfaces (use the surface tokens directly)"
7339
+ ],
7340
+ "props": [
7341
+ {
7342
+ "name": "surfaces",
7343
+ "type": "SurfaceScaleItem[]",
7344
+ "description": "Ordered array of surface tiers — each with token, name, and optional note"
7345
+ },
7346
+ {
7347
+ "name": "surfaces[].token",
7348
+ "type": "string",
7349
+ "description": "CSS custom property for the surface background (e.g. \"--surface-page\")"
7350
+ },
7351
+ {
7352
+ "name": "surfaces[].name",
7353
+ "type": "string",
7354
+ "description": "Display name for the surface tier"
7355
+ },
7356
+ {
7357
+ "name": "surfaces[].note",
7358
+ "type": "string",
7359
+ "description": "Optional use-note shown in the right-aligned column"
7360
+ },
7361
+ {
7362
+ "name": "surfaces[].lightText",
7363
+ "type": "boolean",
7364
+ "default": "false",
7365
+ "description": "When true, text renders in light colors for dark surfaces"
7366
+ }
7367
+ ],
7368
+ "dependencies": [
7369
+ "surface-row"
7370
+ ],
7371
+ "tokens_used": [
7372
+ "--font-size-xs",
7373
+ "--radius-md",
7374
+ "--spacing-4",
7375
+ "--text-tertiary"
7376
+ ],
7377
+ "example": "<SurfaceScaleStack\n surfaces={[\n { token: \"--surface-page\", name: \"Page\", note: \"Root canvas\" },\n { token: \"--surface-screen\", name: \"Screen\", note: \"Full-bleed section\" },\n { token: \"--surface-card\", name: \"Card\", note: \"Primary content card\" },\n { token: \"--surface-raised\", name: \"Raised\", note: \"Elevated card\" },\n { token: \"--surface-overlay\", name: \"Overlay\", note: \"Modal / sheet\", lightText: true },\n ]}\n/>\n"
7378
+ },
7058
7379
  "switch": {
7059
7380
  "category": "form",
7060
7381
  "description": "An accessible toggle switch component built on Radix UI Switch.",
@@ -7893,6 +8214,37 @@
7893
8214
  ],
7894
8215
  "example": "<TooltipProvider>\n <Tooltip>\n <TooltipTrigger asChild>\n <Button variant=\"ghost\" size=\"sm\"><TrashIcon /></Button>\n </TooltipTrigger>\n <TooltipContent>Delete item</TooltipContent>\n </Tooltip>\n</TooltipProvider>\n"
7895
8216
  },
8217
+ "type-scale-stack": {
8218
+ "category": "specimen",
8219
+ "description": "Discrete N-tier type-scale aggregator that wraps an ordered list of TypeSpecimen rows in a rounded, screen-tier, borderless vertical stack.",
8220
+ "when_to_use": [
8221
+ "Documenting a discrete N-tier type scale on a foundation or design system page",
8222
+ "Displaying a full project type scale (e.g. 11-tier V7 scale) as a single visual block",
8223
+ "Theme validation for the complete set of font size tokens at once"
8224
+ ],
8225
+ "when_not_to_use": [
8226
+ "Rendering actual page content (use Heading or Text)",
8227
+ "Continuous or modular-scale rendering",
8228
+ "Single type scale rows (use TypeSpecimen directly)"
8229
+ ],
8230
+ "props": [
8231
+ {
8232
+ "name": "steps",
8233
+ "type": "TypeScaleStepProps[]",
8234
+ "description": "Ordered array of type scale steps — each with token, label, sizePx, and sample"
8235
+ }
8236
+ ],
8237
+ "dependencies": [
8238
+ "type-specimen"
8239
+ ],
8240
+ "tokens_used": [
8241
+ "--radius-lg",
8242
+ "--spacing-3",
8243
+ "--spacing-4",
8244
+ "--surface-screen"
8245
+ ],
8246
+ "example": "<TypeScaleStack steps={[\n { token: \"--font-size-xs\", label: \"xs\", sizePx: 12, sample: \"Caption / helper text\" },\n { token: \"--font-size-sm\", label: \"sm\", sizePx: 14, sample: \"Small body text\" },\n { token: \"--font-size-md\", label: \"md\", sizePx: 16, sample: \"Base body text\" },\n { token: \"--font-size-lg\", label: \"lg\", sizePx: 18, sample: \"Large body text\" },\n { token: \"--font-size-xl\", label: \"xl\", sizePx: 20, sample: \"Subsection heading\" },\n]} />\n"
8247
+ },
7896
8248
  "type-specimen": {
7897
8249
  "category": "specimen",
7898
8250
  "description": "A single typography row displaying sample text at a given font-size token with weight and size metadata.",
@@ -9062,7 +9414,7 @@
9062
9414
  },
9063
9415
  "right-rail-list": {
9064
9416
  "category": "data-display",
9065
- "description": "Compact vertical list block tuned for admin dashboard side rails. Each row pairs an optional leading slot (short label, avatar, badge, status dot), a primary label (typically a link), and an optional trailing meta value (count, value, tone-tinted status word). Trailing accepts default / mint / muted / warn tones that bind to the shared semantic text tokens. Supports compact density and ul / ol / div root element variants.",
9417
+ "description": "Compact vertical list block tuned for admin dashboard side rails. Each row pairs an optional leading slot (short label, avatar, badge, status dot), a primary label (typically a link), and an optional trailing meta value (count, value, tone-tinted status word). Trailing accepts default / mint / muted / warn tones that bind to the shared semantic text tokens. Supports compact density, xs row text size for dense rails, and ul / ol / div root element variants.",
9066
9418
  "components_used": [],
9067
9419
  "when_to_use": [
9068
9420
  "Side-rail summary panels in dashboards (this-week digests, top-N rankings, status callouts)",
@@ -9605,6 +9957,10 @@
9605
9957
  "Sign-in and sign-up pages",
9606
9958
  "Forgot password and reset password flows",
9607
9959
  "Invitation acceptance screens"
9960
+ ],
9961
+ "when_not_to_use": [
9962
+ "Collecting setup preferences after the user is already signed in — use onboarding-flow",
9963
+ "A standalone validated form that is not authentication — use form-with-validation"
9608
9964
  ]
9609
9965
  },
9610
9966
  "card-grid": {
@@ -9621,30 +9977,19 @@
9621
9977
  "Displaying a collection of items as visual tiles (projects, products, team members)",
9622
9978
  "When a table layout is too data-dense and card previews are more scannable",
9623
9979
  "Catalog or gallery pages with paginated content"
9624
- ]
9625
- },
9626
- "crud-table": {
9627
- "description": "Data table with row actions, confirmation dialog, and pagination for managing collections of records.",
9628
- "components_used": [
9629
- "table",
9630
- "button",
9631
- "dropdown-menu",
9632
- "dialog",
9633
- "alert",
9634
- "pagination",
9635
- "badge"
9636
9980
  ],
9637
- "when_to_use": [
9638
- "Admin pages listing and managing resources (users, orders, products)",
9639
- "Any collection view with create, read, update, delete operations",
9640
- "Data tables needing row-level actions and bulk operations"
9981
+ "when_not_to_use": [
9982
+ "Results driven by a search query or type-ahead — use search-results",
9983
+ "Tabular records needing sorting and filtering rather than cards — use data-table-with-filters"
9641
9984
  ]
9642
9985
  },
9643
9986
  "dashboard-layout": {
9644
- "description": "App shell with collapsible sidebar navigation, top navbar, and content area with cards and tabs.",
9987
+ "description": "Responsive app shell a persistent sidebar on desktop that collapses to a Sheet drawer on mobile — with a top navbar and a content area of cards and tabs.",
9645
9988
  "components_used": [
9646
9989
  "sidebar",
9990
+ "sheet",
9647
9991
  "navbar",
9992
+ "button",
9648
9993
  "card",
9649
9994
  "tabs",
9650
9995
  "separator",
@@ -9652,12 +9997,17 @@
9652
9997
  ],
9653
9998
  "when_to_use": [
9654
9999
  "Admin dashboards and internal tools",
9655
- "Multi-section apps with persistent navigation",
9656
- "Content-heavy layouts needing sidebar + main area structure"
10000
+ "Multi-section apps with persistent navigation that must also work on mobile",
10001
+ "Content-heavy layouts needing sidebar + main area structure",
10002
+ "Any app shell where the desktop sidebar should collapse to a drawer without duplicating nav markup"
10003
+ ],
10004
+ "when_not_to_use": [
10005
+ "A single configuration screen rather than the whole app shell — use settings-page",
10006
+ "Just the tabular data inside the shell — use data-table-with-filters or data-table-row-actions"
9657
10007
  ]
9658
10008
  },
9659
10009
  "data-table-row-actions": {
9660
- "description": "A data table with per-row action menus, bulk selection with a bulk action bar, confirmation dialogs, and toast feedback for destructive operations.",
10010
+ "description": "A data table for managing collections of records (CRUD) — per-row action menus, bulk selection with a bulk action bar, confirmation dialogs, and toast feedback for destructive operations.",
9661
10011
  "components_used": [
9662
10012
  "data-table",
9663
10013
  "dropdown-menu",
@@ -9667,9 +10017,13 @@
9667
10017
  "bulk-action-bar"
9668
10018
  ],
9669
10019
  "when_to_use": [
10020
+ "Admin pages listing and managing resources (users, orders, products)",
9670
10021
  "Admin lists where rows have contextual actions (edit, archive, delete)",
9671
10022
  "When supporting both single-row and bulk operations on the same table",
9672
- "Any CRUD interface where destructive actions require confirmation"
10023
+ "Any CRUD interface (create, read, update, delete) where destructive actions require confirmation"
10024
+ ],
10025
+ "when_not_to_use": [
10026
+ "Read-heavy lists whose main need is search, filtering, and sorting rather than row mutations — use data-table-with-filters"
9673
10027
  ]
9674
10028
  },
9675
10029
  "data-table-with-filters": {
@@ -9687,21 +10041,9 @@
9687
10041
  "Data-heavy pages where users need to find specific records",
9688
10042
  "Admin dashboards with sortable, filterable lists",
9689
10043
  "Search result pages with faceted filtering"
9690
- ]
9691
- },
9692
- "empty-state": {
9693
- "description": "Placeholder shown when a page, list, or search has no content to display.",
9694
- "components_used": [
9695
- "card",
9696
- "button",
9697
- "heading",
9698
- "text"
9699
10044
  ],
9700
- "when_to_use": [
9701
- "Empty lists or tables (no data yet)",
9702
- "Search results returning zero matches",
9703
- "First-time user onboarding (no content created yet)",
9704
- "Error states where content failed to load"
10045
+ "when_not_to_use": [
10046
+ "Per-row action menus, bulk selection, and confirm-on-delete on the table — use data-table-row-actions"
9705
10047
  ]
9706
10048
  },
9707
10049
  "form-with-validation": {
@@ -9718,6 +10060,10 @@
9718
10060
  "Any form collecting user input (settings, profile, onboarding)",
9719
10061
  "Forms needing inline validation feedback",
9720
10062
  "Multi-field forms with consistent spacing and error display"
10063
+ ],
10064
+ "when_not_to_use": [
10065
+ "A form presented inside a modal or dialog overlay — use modal-form",
10066
+ "A multi-step guided flow rather than a single form — use onboarding-flow"
9721
10067
  ]
9722
10068
  },
9723
10069
  "modal-form": {
@@ -9735,6 +10081,10 @@
9735
10081
  "Creating or editing a record without leaving the current page",
9736
10082
  "Collecting a small set of inputs (fewer than 8 fields)",
9737
10083
  "When the action is contextual to the parent list or table"
10084
+ ],
10085
+ "when_not_to_use": [
10086
+ "A full-page or inline form that is not in an overlay — use form-with-validation",
10087
+ "A multi-step guided flow — use onboarding-flow"
9738
10088
  ]
9739
10089
  },
9740
10090
  "notification-center": {
@@ -9750,10 +10100,14 @@
9750
10100
  "Apps with persistent in-app notifications or activity alerts",
9751
10101
  "When users need to review, dismiss, or act on multiple notifications at once",
9752
10102
  "Combining real-time toast feedback with a browsable notification history"
10103
+ ],
10104
+ "when_not_to_use": [
10105
+ "A single transient confirmation after one action — use a bare Toast, not the full center",
10106
+ "A command palette for navigation or search — use search-results"
9753
10107
  ]
9754
10108
  },
9755
10109
  "onboarding-flow": {
9756
- "description": "A step-by-step welcome flow that collects user preferences and setup choices using progress tracking, cards, and inline forms with checkbox selections.",
10110
+ "description": "A multi-step guided flow — first-run onboarding, setup wizards, or checkout — that breaks a long or gated process into validated steps with progress tracking, cards, and inline forms.",
9757
10111
  "components_used": [
9758
10112
  "stepper",
9759
10113
  "progress",
@@ -9767,23 +10121,14 @@
9767
10121
  "when_to_use": [
9768
10122
  "First-run experiences after account creation",
9769
10123
  "Feature setup flows where configuration choices shape the initial workspace",
9770
- "Product tours that collect preferences before showing the main dashboard"
9771
- ]
9772
- },
9773
- "responsive-sidebar-layout": {
9774
- "description": "A full-app shell that renders a persistent sidebar on desktop and a Sheet-based drawer on mobile, sharing the same navigation content.",
9775
- "components_used": [
9776
- "sidebar",
9777
- "sheet",
9778
- "navbar",
9779
- "button",
9780
- "separator",
9781
- "scroll-area"
10124
+ "Product tours that collect preferences before showing the main dashboard",
10125
+ "Checkout or other multi-step sequences that stage a long process",
10126
+ "When a single long form would overwhelm the user — break into logical steps",
10127
+ "Flows where earlier steps gate or inform later steps"
9782
10128
  ],
9783
- "when_to_use": [
9784
- "Any multi-section app needing sidebar navigation that must work on mobile",
9785
- "When the desktop sidebar should collapse to a drawer without duplicating nav markup",
9786
- "Admin tools, dashboards, or SaaS apps requiring a responsive shell"
10129
+ "when_not_to_use": [
10130
+ "Login or signup itself use auth-flow",
10131
+ "A single validated form rather than a multi-step flow use form-with-validation"
9787
10132
  ]
9788
10133
  },
9789
10134
  "search-results": {
@@ -9800,6 +10145,9 @@
9800
10145
  "Search pages where users need to filter and browse a large dataset",
9801
10146
  "When combining free-text search with faceted category filters",
9802
10147
  "Directory, catalog, or discovery interfaces with card-based result display"
10148
+ ],
10149
+ "when_not_to_use": [
10150
+ "A static grid of cards not driven by a query — use card-grid"
9803
10151
  ]
9804
10152
  },
9805
10153
  "settings-page": {
@@ -9821,23 +10169,10 @@
9821
10169
  "User profile and account settings",
9822
10170
  "Application preferences and configuration",
9823
10171
  "Team or organization settings"
9824
- ]
9825
- },
9826
- "wizard-flow": {
9827
- "description": "A multi-step guided flow with per-step validation, progress tracking, and a linear navigation structure for complex data collection.",
9828
- "components_used": [
9829
- "stepper",
9830
- "field",
9831
- "input",
9832
- "button",
9833
- "alert",
9834
- "progress",
9835
- "separator"
9836
10172
  ],
9837
- "when_to_use": [
9838
- "Onboarding flows, setup wizards, or checkout sequences",
9839
- "When a single long form would overwhelm the userbreak into logical steps",
9840
- "Flows where earlier steps gate or inform later steps"
10173
+ "when_not_to_use": [
10174
+ "The whole app shell and navigation chrome — use dashboard-layout",
10175
+ "A single focused form rather than grouped settings sections use form-with-validation"
9841
10176
  ]
9842
10177
  }
9843
10178
  },
@@ -9854,6 +10189,8 @@
9854
10189
  "radius-scale",
9855
10190
  "spacing-scale",
9856
10191
  "surface-row",
10192
+ "surface-scale-stack",
10193
+ "type-scale-stack",
9857
10194
  "type-specimen"
9858
10195
  ],
9859
10196
  "data-display": [
@@ -9879,7 +10216,9 @@
9879
10216
  "data-table",
9880
10217
  "empty-state",
9881
10218
  "filter-bar",
10219
+ "infographic-bar",
9882
10220
  "kbd",
10221
+ "matrix-table",
9883
10222
  "score-indicator",
9884
10223
  "stat-card",
9885
10224
  "stat-hero",
@@ -9913,6 +10252,7 @@
9913
10252
  "pagination",
9914
10253
  "quick-actions",
9915
10254
  "section-header",
10255
+ "section-nav",
9916
10256
  "stepper",
9917
10257
  "tabs"
9918
10258
  ],
@@ -9988,6 +10328,163 @@
9988
10328
  "slide-theme-context"
9989
10329
  ]
9990
10330
  },
10331
+ "brand_strategy": {
10332
+ "positioning": {
10333
+ "onliness": "The only design system that compiles a complete brand — visual and verbal — from one portable file, for humans and agents alike.",
10334
+ "category": "design system",
10335
+ "differentiation": "brand strategy, visual and verbal, as derivable machine-readable data"
10336
+ },
10337
+ "essence": [
10338
+ "coherent",
10339
+ "open",
10340
+ "yours"
10341
+ ],
10342
+ "personality": [
10343
+ {
10344
+ "trait": "precise",
10345
+ "not": "fussy"
10346
+ },
10347
+ {
10348
+ "trait": "candid",
10349
+ "not": "cold"
10350
+ },
10351
+ {
10352
+ "trait": "generous",
10353
+ "not": "indulgent"
10354
+ },
10355
+ {
10356
+ "trait": "warm",
10357
+ "not": "saccharine"
10358
+ }
10359
+ ],
10360
+ "archetype": {
10361
+ "primary": "sage",
10362
+ "secondary": "creator",
10363
+ "tertiary": "everyman"
10364
+ },
10365
+ "pillars": [
10366
+ {
10367
+ "id": "coherence",
10368
+ "statement": "Every layer derives from the one above it.",
10369
+ "governs": {
10370
+ "tokens": [
10371
+ "--primary",
10372
+ "--surface-card",
10373
+ "--text-primary"
10374
+ ],
10375
+ "components": [
10376
+ "*"
10377
+ ]
10378
+ }
10379
+ },
10380
+ {
10381
+ "id": "openness",
10382
+ "statement": "The whole system is open — readable by humans and agents, and free to take.",
10383
+ "governs": {
10384
+ "surfaces": [
10385
+ "manifest",
10386
+ "cli",
10387
+ "component-metadata"
10388
+ ]
10389
+ }
10390
+ },
10391
+ {
10392
+ "id": "ownership",
10393
+ "statement": "Copy-and-own. You hold the source; there's no lock-in, ever.",
10394
+ "governs": {
10395
+ "components": [
10396
+ "*"
10397
+ ]
10398
+ }
10399
+ }
10400
+ ],
10401
+ "voice": {
10402
+ "traits": [
10403
+ {
10404
+ "name": "plainspoken",
10405
+ "do": "Say it in one clause. Lead with the answer.",
10406
+ "dont": "Bury the point under qualifiers and throat-clearing.",
10407
+ "example": "Copy-and-own is just that — the source is yours. Edit anything; there's no wrapper to fight."
10408
+ },
10409
+ {
10410
+ "name": "candid",
10411
+ "do": "Name the tradeoff and the cost before the reader hits it.",
10412
+ "dont": "Oversell, hide the sharp edges, or hedge to sound safe.",
10413
+ "example": "Heads up — this theme fails WCAG AA on small text. Bump the contrast a notch, or keep the warning if that's intentional."
10414
+ },
10415
+ {
10416
+ "name": "generous",
10417
+ "do": "Give the why. Show the worked example. Assume the reader will go further than you did.",
10418
+ "dont": "Gatekeep, wave at best practices, or make them read the source to understand.",
10419
+ "example": "Fallbacks use Gray, not Slate — so an un-themed component lands on a neutral that fits your palette instead of clashing. Small thing, but it's what keeps a theme feeling whole."
10420
+ },
10421
+ {
10422
+ "name": "warm",
10423
+ "do": "Greet the reader like a peer you're glad to help. A little delight is welcome.",
10424
+ "dont": "Go cold and transactional — or paper over it with forced cheer.",
10425
+ "example": "Welcome — let's get your first theme on the screen. It takes about a minute."
10426
+ }
10427
+ ]
10428
+ },
10429
+ "tone": {
10430
+ "error": {
10431
+ "feeling": "warm, accountable, already holding the fix",
10432
+ "example": "That didn't save — looks like the theme name's taken. Pick another and we'll keep everything else just as you left it."
10433
+ },
10434
+ "success": {
10435
+ "feeling": "a real, small celebration — a little confetti is fine",
10436
+ "example": "Saved! Your theme's live across every component — go take a look."
10437
+ },
10438
+ "empty": {
10439
+ "feeling": "inviting, a friendly nudge to start",
10440
+ "example": "Nothing here yet — let's change that. Start from a blank file, or clone one and make it yours."
10441
+ },
10442
+ "loading": {
10443
+ "feeling": "unhurried and friendly, honest about the wait",
10444
+ "example": "Compiling your tokens — just a moment…"
10445
+ },
10446
+ "validation-warning": {
10447
+ "feeling": "a friend flagging a smell, never a scold",
10448
+ "example": "Quick one — your primary and accent are nearly twins. Themes can read a little flat this close, so nudge one if it's not on purpose."
10449
+ }
10450
+ },
10451
+ "lexicon": [
10452
+ {
10453
+ "use": "theme",
10454
+ "avoid": "skin"
10455
+ },
10456
+ {
10457
+ "use": "copy-and-own",
10458
+ "avoid": "fork"
10459
+ },
10460
+ {
10461
+ "use": "compose",
10462
+ "avoid": "drag-and-drop"
10463
+ },
10464
+ {
10465
+ "use": "token",
10466
+ "avoid": "variable"
10467
+ },
10468
+ {
10469
+ "use": "adapter",
10470
+ "avoid": "plugin"
10471
+ },
10472
+ {
10473
+ "use": "transform",
10474
+ "avoid": "restyle"
10475
+ },
10476
+ {
10477
+ "use": "portable",
10478
+ "avoid": "exportable"
10479
+ }
10480
+ ],
10481
+ "core": [
10482
+ "positioning",
10483
+ "essence",
10484
+ "pillars"
10485
+ ],
10486
+ "visibility": "public"
10487
+ },
9991
10488
  "tokens": {
9992
10489
  "primitives": [
9993
10490
  {
@@ -11357,6 +11854,20 @@
11357
11854
  "defaultLight": "var(--spacing-24)",
11358
11855
  "defaultDark": "var(--spacing-24)"
11359
11856
  },
11857
+ {
11858
+ "name": "--layout-section-padding",
11859
+ "tier": "semantic",
11860
+ "description": "Semantic spacing: layout-section-padding",
11861
+ "defaultLight": "var(--spacing-24)",
11862
+ "defaultDark": "var(--spacing-24)"
11863
+ },
11864
+ {
11865
+ "name": "--layout-section-padding-mobile",
11866
+ "tier": "semantic",
11867
+ "description": "Semantic spacing: layout-section-padding-mobile",
11868
+ "defaultLight": "var(--spacing-16)",
11869
+ "defaultDark": "var(--spacing-16)"
11870
+ },
11360
11871
  {
11361
11872
  "name": "--motion-duration-fast",
11362
11873
  "tier": "semantic",
@@ -12180,7 +12691,7 @@
12180
12691
  }
12181
12692
  ],
12182
12693
  "summary": {
12183
- "total": 312
12694
+ "total": 314
12184
12695
  }
12185
12696
  }
12186
12697
  }