@nurix/etna 0.19.66 → 0.19.68

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 (234) hide show
  1. package/bin/etna.js +10 -1
  2. package/data/harness-index.json +1 -5
  3. package/data/harnesses/code/CLAUDE.md +2 -0
  4. package/data/harnesses/code/agents/maintenance.md +4 -1
  5. package/data/harnesses/code/harness.json +7 -2
  6. package/data/harnesses/code/hooks/awareness.mjs +69 -0
  7. package/data/harnesses/code/hooks/compliance.mjs +2 -14
  8. package/data/harnesses/code/hooks/lib/approved.mjs +30 -0
  9. package/data/harnesses/code/hooks/lib/frozen.mjs +3 -0
  10. package/data/harnesses/code/hooks/lib/ownership.mjs +3 -1
  11. package/data/harnesses/code/skills/documentation/references/frontmatter.md +1 -1
  12. package/data/harnesses/code/skills/documentation/scripts/doc-lint.mjs +1 -1
  13. package/data/harnesses/code/skills/documentation/templates/Readme.md +2 -0
  14. package/data/harnesses/code/skills/documentation/templates/structure.md +1 -0
  15. package/data/harnesses/delivery/agents/maintenance.md +4 -1
  16. package/data/harnesses/delivery/harness.json +2 -2
  17. package/data/harnesses/delivery/skills/documentation/references/frontmatter.md +1 -1
  18. package/data/harnesses/delivery/skills/documentation/scripts/doc-lint.mjs +1 -1
  19. package/data/harnesses/delivery/skills/documentation/templates/Readme.md +2 -0
  20. package/data/harnesses/delivery/skills/documentation/templates/structure.md +1 -0
  21. package/data/harnesses/etna/agents/maintenance.md +4 -1
  22. package/data/harnesses/etna/harness.json +2 -2
  23. package/data/harnesses/etna/skills/documentation/references/frontmatter.md +1 -1
  24. package/data/harnesses/etna/skills/documentation/scripts/doc-lint.mjs +1 -1
  25. package/data/harnesses/etna/skills/documentation/templates/Readme.md +2 -0
  26. package/data/harnesses/etna/skills/documentation/templates/structure.md +1 -0
  27. package/lib/install/materialize.mjs +51 -57
  28. package/package.json +2 -2
  29. package/data/harnesses/apollo/.mcp.json +0 -8
  30. package/data/harnesses/apollo/.prettierignore +0 -29
  31. package/data/harnesses/apollo/.prettierrc.json +0 -3
  32. package/data/harnesses/apollo/.vscode/settings.json +0 -19
  33. package/data/harnesses/apollo/CLAUDE.md +0 -162
  34. package/data/harnesses/apollo/agents/bookkeeper.md +0 -28
  35. package/data/harnesses/apollo/agents/brainstorm.md +0 -144
  36. package/data/harnesses/apollo/agents/change-review.md +0 -251
  37. package/data/harnesses/apollo/agents/lld-mode.md +0 -58
  38. package/data/harnesses/apollo/agents/maintenance.md +0 -234
  39. package/data/harnesses/apollo/agents/performance-review.md +0 -223
  40. package/data/harnesses/apollo/agents/retro.md +0 -46
  41. package/data/harnesses/apollo/codex/agents/bookkeeper.toml +0 -26
  42. package/data/harnesses/apollo/codex/agents/brainstorm.toml +0 -142
  43. package/data/harnesses/apollo/codex/agents/change-review.toml +0 -249
  44. package/data/harnesses/apollo/codex/agents/lld-mode.toml +0 -52
  45. package/data/harnesses/apollo/codex/agents/maintenance.toml +0 -228
  46. package/data/harnesses/apollo/codex/agents/performance-review.toml +0 -222
  47. package/data/harnesses/apollo/codex/agents/retro.toml +0 -45
  48. package/data/harnesses/apollo/harness.json +0 -19
  49. package/data/harnesses/apollo/hooks/approved-packages.md +0 -44
  50. package/data/harnesses/apollo/hooks/awareness.mjs +0 -405
  51. package/data/harnesses/apollo/hooks/check-bookkeeping-clean.mjs +0 -19
  52. package/data/harnesses/apollo/hooks/check-changelog-presence.mjs +0 -57
  53. package/data/harnesses/apollo/hooks/check-completion-integrity.mjs +0 -71
  54. package/data/harnesses/apollo/hooks/check-ownership.mjs +0 -22
  55. package/data/harnesses/apollo/hooks/compliance.mjs +0 -457
  56. package/data/harnesses/apollo/hooks/hooks.json +0 -23
  57. package/data/harnesses/apollo/hooks/lib/frozen.mjs +0 -58
  58. package/data/harnesses/apollo/hooks/lib/ownership.mjs +0 -242
  59. package/data/harnesses/apollo/hooks/lib/state.mjs +0 -170
  60. package/data/harnesses/apollo/rules/changelog.md +0 -27
  61. package/data/harnesses/apollo/rules/database.md +0 -34
  62. package/data/harnesses/apollo/rules/frontend.md +0 -30
  63. package/data/harnesses/apollo/rules/general.md +0 -40
  64. package/data/harnesses/apollo/rules/nomenclature.md +0 -30
  65. package/data/harnesses/apollo/rules/pnpm.md +0 -57
  66. package/data/harnesses/apollo/rules/testing.md +0 -64
  67. package/data/harnesses/apollo/skills/boundary/SKILL.md +0 -75
  68. package/data/harnesses/apollo/skills/boundary/references/index.md +0 -16
  69. package/data/harnesses/apollo/skills/boundary/references/mechanisms.md +0 -99
  70. package/data/harnesses/apollo/skills/boundary/references/packs/async-messaging.md +0 -81
  71. package/data/harnesses/apollo/skills/boundary/references/packs/auth.md +0 -93
  72. package/data/harnesses/apollo/skills/boundary/references/packs/build-config-runtime.md +0 -93
  73. package/data/harnesses/apollo/skills/boundary/references/packs/cloudflare.md +0 -93
  74. package/data/harnesses/apollo/skills/boundary/references/packs/frontend.md +0 -93
  75. package/data/harnesses/apollo/skills/boundary/references/packs/generic-tail.md +0 -55
  76. package/data/harnesses/apollo/skills/boundary/references/packs/persistence.md +0 -93
  77. package/data/harnesses/apollo/skills/boundary/references/packs/wire-api.md +0 -87
  78. package/data/harnesses/apollo/skills/brainstorm/README.md +0 -56
  79. package/data/harnesses/apollo/skills/brainstorm/SKILL.md +0 -173
  80. package/data/harnesses/apollo/skills/brainstorm/references/doctrine.md +0 -98
  81. package/data/harnesses/apollo/skills/brainstorm/references/harvest.md +0 -86
  82. package/data/harnesses/apollo/skills/brainstorm/references/session-schema.md +0 -186
  83. package/data/harnesses/apollo/skills/brainstorm/scripts/detector.mjs +0 -460
  84. package/data/harnesses/apollo/skills/design/SKILL.md +0 -121
  85. package/data/harnesses/apollo/skills/design/components/charts.md +0 -76
  86. package/data/harnesses/apollo/skills/design/components/collections.md +0 -132
  87. package/data/harnesses/apollo/skills/design/components/feedback.md +0 -47
  88. package/data/harnesses/apollo/skills/design/components/hooks.md +0 -35
  89. package/data/harnesses/apollo/skills/design/components/index.md +0 -143
  90. package/data/harnesses/apollo/skills/design/components/inputs.md +0 -327
  91. package/data/harnesses/apollo/skills/design/components/layout.md +0 -52
  92. package/data/harnesses/apollo/skills/design/components/media.md +0 -66
  93. package/data/harnesses/apollo/skills/design/components/motion.md +0 -82
  94. package/data/harnesses/apollo/skills/design/components/navigation.md +0 -29
  95. package/data/harnesses/apollo/skills/design/components/overlays.md +0 -72
  96. package/data/harnesses/apollo/skills/design/components/setup.md +0 -40
  97. package/data/harnesses/apollo/skills/design/components/typography.md +0 -46
  98. package/data/harnesses/apollo/skills/design/components/utils.md +0 -37
  99. package/data/harnesses/apollo/skills/design/data/blueprints/browse.md +0 -38
  100. package/data/harnesses/apollo/skills/design/data/blueprints/creation-flow.md +0 -38
  101. package/data/harnesses/apollo/skills/design/data/blueprints/dashboard.md +0 -38
  102. package/data/harnesses/apollo/skills/design/data/blueprints/grid.md +0 -38
  103. package/data/harnesses/apollo/skills/design/data/blueprints/queue.md +0 -38
  104. package/data/harnesses/apollo/skills/design/data/blueprints/record-detail.md +0 -38
  105. package/data/harnesses/apollo/skills/design/data/blueprints/settings.md +0 -38
  106. package/data/harnesses/apollo/skills/design/data/charts/census.csv +0 -58
  107. package/data/harnesses/apollo/skills/design/data/checklists/browse.md +0 -21
  108. package/data/harnesses/apollo/skills/design/data/checklists/creation-flow.md +0 -20
  109. package/data/harnesses/apollo/skills/design/data/checklists/dashboard.md +0 -21
  110. package/data/harnesses/apollo/skills/design/data/checklists/grid.md +0 -21
  111. package/data/harnesses/apollo/skills/design/data/checklists/queue.md +0 -21
  112. package/data/harnesses/apollo/skills/design/data/checklists/record-detail.md +0 -21
  113. package/data/harnesses/apollo/skills/design/data/checklists/settings.md +0 -21
  114. package/data/harnesses/apollo/skills/design/data/chrome/board-column.md +0 -68
  115. package/data/harnesses/apollo/skills/design/data/chrome/data-table.md +0 -63
  116. package/data/harnesses/apollo/skills/design/data/chrome/side-panel.md +0 -60
  117. package/data/harnesses/apollo/skills/design/data/chrome/sidebar.md +0 -78
  118. package/data/harnesses/apollo/skills/design/data/chrome/stat-cards.md +0 -62
  119. package/data/harnesses/apollo/skills/design/data/chrome/topbar.md +0 -65
  120. package/data/harnesses/apollo/skills/design/data/elevation/ant-design-directional-shadow.md +0 -19
  121. package/data/harnesses/apollo/skills/design/data/elevation/apple-liquid-glass-material.md +0 -18
  122. package/data/harnesses/apollo/skills/design/data/elevation/atlassian-surface-shadow-pairing.md +0 -20
  123. package/data/harnesses/apollo/skills/design/data/elevation/fluent-2-key-ambient-ramp.md +0 -20
  124. package/data/harnesses/apollo/skills/design/data/elevation/github-primer-sparing-shadow.md +0 -19
  125. package/data/harnesses/apollo/skills/design/data/elevation/ibm-carbon-layer-and-border.md +0 -19
  126. package/data/harnesses/apollo/skills/design/data/elevation/linear-dark-surface-ladder.md +0 -17
  127. package/data/harnesses/apollo/skills/design/data/elevation/material-2-key-ambient-dp-ramp.md +0 -19
  128. package/data/harnesses/apollo/skills/design/data/elevation/material-3-tonal-elevation.md +0 -21
  129. package/data/harnesses/apollo/skills/design/data/elevation/neobrutalist-hard-offset.md +0 -19
  130. package/data/harnesses/apollo/skills/design/data/elevation/neumorphic-soft-dual-shadow.md +0 -18
  131. package/data/harnesses/apollo/skills/design/data/elevation/notion-warm-minimal-hairline.md +0 -17
  132. package/data/harnesses/apollo/skills/design/data/elevation/polaris-elevation-inset-bevel.md +0 -21
  133. package/data/harnesses/apollo/skills/design/data/elevation/radix-themes-alpha-ring-scale.md +0 -19
  134. package/data/harnesses/apollo/skills/design/data/elevation/shadcn-neutral-derived-radius.md +0 -19
  135. package/data/harnesses/apollo/skills/design/data/elevation/stripe-brand-tinted-dual-shadow.md +0 -18
  136. package/data/harnesses/apollo/skills/design/data/elevation/tailwind-default-utility-scale.md +0 -19
  137. package/data/harnesses/apollo/skills/design/data/elevation/vercel-geist-shadow-as-border.md +0 -20
  138. package/data/harnesses/apollo/skills/design/data/iconography.md +0 -199
  139. package/data/harnesses/apollo/skills/design/data/motion/accordion-expand.md +0 -18
  140. package/data/harnesses/apollo/skills/design/data/motion/destructive-hold-confirm.md +0 -18
  141. package/data/harnesses/apollo/skills/design/data/motion/drag-dismiss-momentum.md +0 -18
  142. package/data/harnesses/apollo/skills/design/data/motion/empty-state-arrive.md +0 -18
  143. package/data/harnesses/apollo/skills/design/data/motion/hover-lift.md +0 -18
  144. package/data/harnesses/apollo/skills/design/data/motion/modal-center-arrive.md +0 -18
  145. package/data/harnesses/apollo/skills/design/data/motion/number-ticker-roll.md +0 -18
  146. package/data/harnesses/apollo/skills/design/data/motion/onboarding-bounce.md +0 -18
  147. package/data/harnesses/apollo/skills/design/data/motion/panel-slide.md +0 -18
  148. package/data/harnesses/apollo/skills/design/data/motion/press-feedback.md +0 -18
  149. package/data/harnesses/apollo/skills/design/data/motion/progress-linear-loop.md +0 -18
  150. package/data/harnesses/apollo/skills/design/data/motion/route-crossfade.md +0 -18
  151. package/data/harnesses/apollo/skills/design/data/motion/rubber-band-overscroll.md +0 -18
  152. package/data/harnesses/apollo/skills/design/data/motion/skeleton-shimmer.md +0 -18
  153. package/data/harnesses/apollo/skills/design/data/motion/stagger-arrive.md +0 -18
  154. package/data/harnesses/apollo/skills/design/data/motion/toast-enter-stack.md +0 -18
  155. package/data/harnesses/apollo/skills/design/data/motion/tooltip-chain-instant.md +0 -18
  156. package/data/harnesses/apollo/skills/design/data/motion/trigger-anchored-reveal.md +0 -18
  157. package/data/harnesses/apollo/skills/design/data/tells.csv +0 -34
  158. package/data/harnesses/apollo/skills/design/data/voices/bright-collaborator.md +0 -29
  159. package/data/harnesses/apollo/skills/design/data/voices/direct-operator.md +0 -29
  160. package/data/harnesses/apollo/skills/design/data/voices/earnest-helper.md +0 -29
  161. package/data/harnesses/apollo/skills/design/data/voices/editorial-composed.md +0 -29
  162. package/data/harnesses/apollo/skills/design/data/voices/quiet-concierge.md +0 -29
  163. package/data/harnesses/apollo/skills/design/data/voices/warm-guide.md +0 -29
  164. package/data/harnesses/apollo/skills/design/references/compose.md +0 -23
  165. package/data/harnesses/apollo/skills/design/references/content.md +0 -28
  166. package/data/harnesses/apollo/skills/design/references/emission.md +0 -21
  167. package/data/harnesses/apollo/skills/design/references/existing-apps.md +0 -27
  168. package/data/harnesses/apollo/skills/design/references/foundations.md +0 -57
  169. package/data/harnesses/apollo/skills/design/references/intake.md +0 -40
  170. package/data/harnesses/apollo/skills/design/references/object-pass.md +0 -24
  171. package/data/harnesses/apollo/skills/design/references/ship-gate.md +0 -29
  172. package/data/harnesses/apollo/skills/design/references/ux-patterns/Readme.md +0 -195
  173. package/data/harnesses/apollo/skills/design/references/ux-patterns/ai-layer.md +0 -49
  174. package/data/harnesses/apollo/skills/design/references/ux-patterns/attributes-lifecycle.md +0 -43
  175. package/data/harnesses/apollo/skills/design/references/ux-patterns/container-choice.md +0 -44
  176. package/data/harnesses/apollo/skills/design/references/ux-patterns/creation-paths.md +0 -46
  177. package/data/harnesses/apollo/skills/design/references/ux-patterns/dashboards.md +0 -42
  178. package/data/harnesses/apollo/skills/design/references/ux-patterns/modes.md +0 -42
  179. package/data/harnesses/apollo/skills/design/references/ux-patterns/object-model.md +0 -46
  180. package/data/harnesses/apollo/skills/design/references/ux-patterns/page-archetype.md +0 -48
  181. package/data/harnesses/apollo/skills/design/references/ux-patterns/promotion-demotion.md +0 -37
  182. package/data/harnesses/apollo/skills/design/references/ux-patterns/settings.md +0 -42
  183. package/data/harnesses/apollo/skills/design/references/ux-patterns/standard-pages.md +0 -46
  184. package/data/harnesses/apollo/skills/design/references/ux-patterns/state-matrix.md +0 -41
  185. package/data/harnesses/apollo/skills/design/references/ux-patterns/table-mechanics.md +0 -48
  186. package/data/harnesses/apollo/skills/design/references/ux-patterns/verbs.md +0 -45
  187. package/data/harnesses/apollo/skills/design/references/ux-patterns/viewer-context.md +0 -40
  188. package/data/harnesses/apollo/skills/design/scripts/README-validator.md +0 -27
  189. package/data/harnesses/apollo/skills/design/scripts/select-chart.mjs +0 -622
  190. package/data/harnesses/apollo/skills/design/scripts/validate-design-md.mjs +0 -1198
  191. package/data/harnesses/apollo/skills/documentation/SKILL.md +0 -135
  192. package/data/harnesses/apollo/skills/documentation/references/examples.md +0 -279
  193. package/data/harnesses/apollo/skills/documentation/references/frontmatter.md +0 -44
  194. package/data/harnesses/apollo/skills/documentation/references/instruction-style.md +0 -50
  195. package/data/harnesses/apollo/skills/documentation/references/style-guide.md +0 -384
  196. package/data/harnesses/apollo/skills/documentation/references/untemplated.md +0 -38
  197. package/data/harnesses/apollo/skills/documentation/scripts/doc-lint.mjs +0 -140
  198. package/data/harnesses/apollo/skills/documentation/templates/Readme.md +0 -35
  199. package/data/harnesses/apollo/skills/documentation/templates/api-reference.md +0 -20
  200. package/data/harnesses/apollo/skills/documentation/templates/architecture-decision.md +0 -121
  201. package/data/harnesses/apollo/skills/documentation/templates/backlog.md +0 -33
  202. package/data/harnesses/apollo/skills/documentation/templates/behavioral-checklist.md +0 -81
  203. package/data/harnesses/apollo/skills/documentation/templates/bookkeeping.md +0 -18
  204. package/data/harnesses/apollo/skills/documentation/templates/changelog-entry.md +0 -57
  205. package/data/harnesses/apollo/skills/documentation/templates/changelog-index.md +0 -41
  206. package/data/harnesses/apollo/skills/documentation/templates/docs-readme.md +0 -72
  207. package/data/harnesses/apollo/skills/documentation/templates/domain-model.md +0 -30
  208. package/data/harnesses/apollo/skills/documentation/templates/environment-registry.md +0 -15
  209. package/data/harnesses/apollo/skills/documentation/templates/feature.md +0 -150
  210. package/data/harnesses/apollo/skills/documentation/templates/glossary.md +0 -11
  211. package/data/harnesses/apollo/skills/documentation/templates/implementation-map.md +0 -42
  212. package/data/harnesses/apollo/skills/documentation/templates/journal.md +0 -13
  213. package/data/harnesses/apollo/skills/documentation/templates/memory-main.md +0 -25
  214. package/data/harnesses/apollo/skills/documentation/templates/migration-runbook.md +0 -34
  215. package/data/harnesses/apollo/skills/documentation/templates/non-goals.md +0 -11
  216. package/data/harnesses/apollo/skills/documentation/templates/operations-procedure.md +0 -36
  217. package/data/harnesses/apollo/skills/documentation/templates/plan.md +0 -88
  218. package/data/harnesses/apollo/skills/documentation/templates/protected-files.md +0 -37
  219. package/data/harnesses/apollo/skills/documentation/templates/root-readme.md +0 -104
  220. package/data/harnesses/apollo/skills/documentation/templates/security-overview.md +0 -27
  221. package/data/harnesses/apollo/skills/documentation/templates/structure.md +0 -65
  222. package/data/harnesses/apollo/skills/documentation/templates/system-overview.md +0 -32
  223. package/data/harnesses/apollo/skills/documentation/templates/testing-strategy.md +0 -29
  224. package/data/harnesses/apollo/skills/schema-design/SKILL.md +0 -141
  225. package/data/harnesses/apollo/skills/test/SKILL.md +0 -104
  226. package/data/harnesses/apollo/skills/testing/SKILL.md +0 -166
  227. package/data/harnesses/apollo/skills/workflow-mapper/SKILL.md +0 -451
  228. package/data/harnesses/apollo/skills/workflow-mapper/references/patterns.md +0 -214
  229. /package/data/harnesses/{apollo → code}/docs/README.md +0 -0
  230. /package/data/harnesses/{apollo → code}/docs/history/CHANGELOG.md +0 -0
  231. /package/data/harnesses/{apollo → code}/docs/history/backlog.md +0 -0
  232. /package/data/harnesses/{apollo → code}/docs/memory/main.md +0 -0
  233. /package/data/harnesses/{apollo → code}/docs/structure.md +0 -0
  234. /package/data/harnesses/{apollo → code}/rules/cloudflare.md +0 -0
@@ -1,68 +0,0 @@
1
- ---
2
- id: board-column
3
- class: d2
4
- sourced: 2026-07-12
5
- source: "spec authored from scratch — @nurix/components ships no board/kanban primitive; closest building blocks: Sortable (dnd-kit compound), Card, Badge, ScrollArea, Avatar, EmptyState — ~/dev/components"
6
- license: open
7
- ---
8
-
9
- # Chrome recipe — board column
10
-
11
- > **Library gap.** `@nurix/components` has no board/kanban component (verified 2026-07-12: no kanban/board export; the docs note the name collision with Kibo UI's kanban-style "List" as a warning, not a feature). This recipe is therefore a from-scratch specification in both switch modes; under `nurix` it composes the library's `Sortable` drag-and-drop compound with `Card`/`Badge`/`ScrollArea`. Flagged as a curation candidate for library admission.
12
-
13
- One column of a kanban/work board: a workflow state rendered as a vertical lane of draggable cards with a counted header, an add affordance, and drop semantics. The board is a view-type projection of a queue — columns are states, cards are work items.
14
-
15
- ## Anatomy
16
-
17
- | Slot | Spec | nurix building block |
18
- | --- | --- | --- |
19
- | Column shell | Fixed width (280–320px), full board height, vertical flex; a quiet wash distinguishing the lane from the canvas and from its cards; rounded per the package radius scale. | `div` + tokens |
20
- | Column header | Pinned: state dot or icon (the column's identity color), title, count badge (live: cards currently in the lane), optional WIP limit rendered as `count / limit`, trailing overflow menu (rename, set limit, collapse), optional collapse toggle. | `Badge`, `DropdownMenu` |
21
- | Card list | The only scrolling region — each column scrolls independently; consistent card gap from the spacing scale. | `ScrollArea` + `SortableContent` (dnd-kit `SortableContext`, `orientation="vertical"`) |
22
- | Card | The unit of drag: title (2-line clamp), meta row (assignee `Avatar`, due date, priority pill), optional label chips and a progress/checklist hint. Whole-card drag (`SortableItem asHandle`) or an explicit grip (`SortableItemHandle`) — with an explicit handle, the card body remains a plain click target for opening the record. | `Card` + `SortableItem` |
23
- | Drop indicator | An insertion line (or ghost slot) at the projected index while a drag is over the column. | dnd-kit collision feedback |
24
- | Drag overlay | The dragged card's floating preview, portaled above the board at overlay elevation, slightly scaled/tilted per the package's motion vocabulary; the origin card stays in place at reduced opacity. | `SortableOverlay` |
25
- | Footer | "+ Add card" ghost affordance pinned under the list; activating it opens an inline title input at the column tail. | `Button variant="ghost"` |
26
- | Empty slot | An empty column keeps a dashed placeholder slot so it remains an obvious drop target. | `EmptyState` (quiet) |
27
-
28
- Board-level contract the column participates in: `Sortable` root (`DndContext`) owns `value`/`onValueChange` and `onMove({ activeIndex, overIndex })`; state changes commit through the consumer's data layer — the column never owns item data.
29
-
30
- ## The eight states
31
-
32
- | State | Spec | Token roles |
33
- | --- | --- | --- |
34
- | default | Lane on a low-alpha muted wash with a hairline edge; cards on the card surface with hairline borders; count badge quiet. | `muted` (wash), `card` + `card-foreground`, `border` |
35
- | hover | A hovered card lifts one step on the package elevation ramp; the add affordance and card grips sharpen from rest. | elevation system, `accent` |
36
- | focus | Focused card (or its handle) shows a focus-visible ring; the roving position is always visible. | `ring` |
37
- | active | Mid-drag: origin card at ~40–50% opacity in place; overlay elevated above everything; the hovered target column's wash intensifies and the drop indicator renders in the primary role at the exact insertion index. | `primary` (indicator), `accent` (target wash) |
38
- | disabled | WIP limit reached: the count reads `n / limit` in the warning role and the column rejects drops (indicator suppressed, "limit reached" hint). A locked/terminal column renders muted and non-droppable. | `warning`, reduced-alpha |
39
- | loading | Header renders immediately with title; 2–3 skeleton cards hold the lane's shape; counts appear only when true. | `muted` |
40
- | error / empty | Empty: the dashed drop slot plus a one-line hint — the lane never collapses to zero height. A failed move animates the card back to its origin and raises a toast; the board never shows a state the server rejected. | `muted-foreground`; `destructive` (failure toast) |
41
- | success | A completed drop settles with a brief interruptible settle animation; both columns' counts update in the same frame. A card entering a terminal "done" column may flash its status chip on the success role. | `success` status role (transient) |
42
-
43
- ## Keyboard behavior
44
-
45
- Grounded in the shipped `Sortable`'s keyboard sensor and screen-reader announcements (grab / move / drop / cancel are announced):
46
-
47
- - **Tab** reaches each card (or its handle) in column order, then the column's add affordance and menu. Every card is focusable — the library note that `SortableItem` dropped its `tabIndex` fallback means the spec requires `asHandle` or an explicit focusable handle on every card; a pointer-only board is a defect.
48
- - **Enter / Space** on a focused card picks it up; **arrow up/down** moves it within the column; **arrow left/right** moves it to the adjacent column (same relative index, clamped); **Enter / Space** drops; **Escape** cancels and returns the card to its origin.
49
- - Each move is announced to assistive tech ("moved to Review, position 2 of 5"); drop and cancel are announced likewise.
50
- - **Enter** on the card body (when a separate handle exists) opens the record — typically in the side-panel recipe.
51
- - The add affordance opens an inline input: **Enter** commits the new card, **Escape** dismisses.
52
- - **cmdk path**: bulk and precise moves ("Move PROJ-142 to Done") belong in the command palette; the board's own keys cover local, one-card moves.
53
-
54
- ## Token reach
55
-
56
- - `muted` — the lane wash (the column is a *region*, not a card: it stays one step quieter than its cards); `card` / `card-foreground` — the cards; `border` — lane and card hairlines.
57
- - `primary` — the drop indicator and the add affordance's hover emphasis; `ring` — focus; `accent` — hover fills and the active drop-target wash.
58
- - **Column identity colors** (the state dot, an optional header tint) resolve from `chart-1..5` or the status roles — a board with per-column hex literals re-skins wrong on package switch and renders light-in-dark; this is the token-reach report's target on this component.
59
- - Priority pills and label chips on cards consume status roles / `chart-1..5` exactly as in the data-table recipe — the same option object must render identically in both projections.
60
- - `warning` — WIP-limit breach; `destructive` — failed-move feedback; `success` — transient completion.
61
- - Overlay elevation comes from the package's shadow ramp (brand-tinted per the elevation doctrine), never an ad-hoc black shadow.
62
-
63
- ## When to use / composition notes
64
-
65
- A board is the right projection when workflow state is the primary axis the operator thinks in and moving items between states is a frequent, deliberate act — triage, pipeline stages, content review. It is a projection of the queue/browse archetype, never an archetype itself: the same items must remain reachable as a table, and the switch between projections belongs to the page, not the component. Keep visible cards per column modest (order of tens; virtualize beyond) and card content to what the move decision needs — title, owner, urgency; everything else lives one click away in the side panel. Columns are few and stable (a board with twelve columns is a table wearing a costume); WIP limits are the one piece of process the chrome itself should enforce visibly.
66
-
67
- - **`primitives: nurix`** — composed (no single import; library gap flagged above): `import { Sortable, SortableContent, SortableItem, SortableItemHandle, SortableOverlay } from "@nurix/components/sortable"; import { Card } from "@nurix/components/card"; import { Badge } from "@nurix/components/badge"; import { ScrollArea } from "@nurix/components/scroll-area";` — `Sortable` supplies `value`/`onValueChange`, `orientation`, `onMove`, mouse/touch/keyboard sensors, and screen-reader announcements out of the box.
68
- - **`primitives: native`** — this recipe is the full build spec: fixed-width independently-scrolling lanes, drag-and-drop with the complete keyboard path and live announcements above (the stack's own dnd library or an existing design-system board), optimistic moves with revert-on-failure, WIP-limit rejection, and all column/priority color resolved from the token artifact.
@@ -1,63 +0,0 @@
1
- ---
2
- id: data-table
3
- class: d2
4
- sourced: 2026-07-12
5
- source: "@nurix/components Table + defineColumn (on the UiTable primitive layer, @tanstack/react-table engine) — ~/dev/components"
6
- license: open
7
- ---
8
-
9
- # Chrome recipe — data table
10
-
11
- The operator data table: column-definition-driven, read-only by default, with opt-in selection, sorting, pagination, density, borders, resize, and editable cells that write back through a single callback. Governing invariant: a zero-config `<Table data columns />` renders DOM equivalent to a hand-written semantic table — every feature is purely additive.
12
-
13
- ## Anatomy
14
-
15
- | Slot | Library part | Spec |
16
- | --- | --- | --- |
17
- | Shells | `LoadingShell` → `FooterShell` → `AutoHeightShell` | Opt-in wrappers composed around the bare table, gated on `tableConfig` flags (`loading`, `pagination`, `autoHeight`). |
18
- | Header row | `ColumnHeader` | One cell per column; sortable columns (`display.sortable`, defaulted from type) render a sort dropdown when `tableConfig.sort` is on. `header: false` removes the row entirely. |
19
- | Selection column | id `__select__` | Prepended when `tableConfig.rowSelection`: tri-state header checkbox (page-scoped, indeterminate) + per-row checkboxes; selection accumulates across pages and emits `onSelect(selectedIds)`. |
20
- | Body rows | `UiTableRow` | Keyed by `row.id` (`TData extends { id: string }`); selected rows carry `data-state="selected"`. |
21
- | Cells | 13 renderers | Dispatched on the column `component`: `text`, `number`, `boolean`, `date`, `date-range`, `select`, `multiselect`, `slider`, `rating`, `status`, `priority`, `assignee`, `sparkline`. Each has a **display** variant (default — static, no popovers) and an **editable** variant (`editable: true`); a custom `cell(row)` function wins over everything. |
22
- | Column contract | `defineColumn({ slug, label, type, component?, editable?, hidden?, metadata?, display?, cell? })` | `type: "text" \| "number" \| "boolean" \| "date" \| "enum" \| "user"` drives the default component and sortability; enum-family options are `metadata.options: [{ value, label, color }]`; explicit `display.width` is honored independent of resize. |
23
- | Pagination footer | `TablePagination` | Controlled `{ current, size, total, onChange }`, 1-indexed; page numbers collapse with ellipses past seven pages. Sorting and pagination are always external — the table never owns that state. |
24
- | Config | `tableConfig` | `preset: "classic"` (comfortable density + pagination + full borders + muted header wash), `density: "compact" \| "comfortable" \| "spacious"`, `columnBorders`, `tableBorders`, `resize` (drag handles, 50px floor). |
25
- | Write-back | `onCellChange({ rowId, columnId, slug, value })` | Fires only from editable cells at each widget's natural commit; the table never mutates `data`. |
26
-
27
- ## The eight states
28
-
29
- | State | Spec | Token roles |
30
- | --- | --- | --- |
31
- | default | Rows on the canvas with hairline row separators; header optionally on a low-alpha muted wash (classic preset); numerals tabular. | `background`/`card`, `border`, `muted` at low alpha, `foreground` |
32
- | hover | Row takes a quiet muted wash; sort triggers and checkboxes reveal on hover where hidden at rest. | `muted` |
33
- | focus | Focus-visible ring on each interactive control — checkboxes, sort triggers, editable widgets, pagination buttons. | `ring` |
34
- | active | Selected rows fill via `data-state="selected"`; checked boxes fill with the primary role; an open editable cell shows its live widget with ring emphasis; the sorted column's header shows direction. | `muted` (row), `primary` (checkbox), `ring` |
35
- | disabled | The default **is** read-only — display cells are static, not "disabled". Truly disabled controls (a locked toggle, a non-permitted action) render at ~50% opacity with no pointer events. | reduced-alpha foreground |
36
- | loading | `loading: true` overlays a centered spinner while retaining rendered rows beneath (no layout collapse); a first load with no data renders skeleton rows at the configured density. | `muted` (skeleton), `muted-foreground` (spinner) |
37
- | error / empty | Zero rows render an empty-state block in the body — message + optional action — never a bare void. Row-level degradation is expressed through status pills (e.g. a failed sync status) on status roles, and stale data through a caption, not through reddened rows. | `muted-foreground`; `destructive`/`warning` status roles |
38
- | success | A committed edit re-renders through parent state immediately (single source of truth); positive statuses render as status-role pills. Transient save confirmation belongs to a toast, not the grid. | `success` status role |
39
-
40
- ## Keyboard behavior
41
-
42
- - **Tab** moves through interactive elements in DOM order: header checkbox → sort triggers → row checkboxes → editable widgets → pagination. Display cells are not focus stops.
43
- - **Enter/Space** toggles checkboxes and opens a sort dropdown; inside the dropdown, arrows move, Enter applies, **Escape** closes to the trigger. Up to 3 simultaneously sorted columns share one direction, FIFO-evicted.
44
- - **Editable commit semantics** (what fires `onCellChange`): text/number commit on **Enter or blur**, **Escape** reverts the uncommitted value; select/status/priority/assignee commit on selection; multiselect on popover close after a change; boolean on toggle; slider on release; rating on star activation; date on selection; date-range on full-range selection.
45
- - **Enum-family cells** open a searchable listbox (the compound Select): type to filter, arrows to move, Enter to select, Escape to close — the cmdk interaction grammar applied per-cell.
46
- - Pagination controls are plain buttons — Enter/Space activate; no custom arrow-key handling.
47
-
48
- ## Token reach
49
-
50
- - `background` / `card` — the table surface; `border` — row separators, opt-in column/table borders, resize handles.
51
- - `foreground` / `muted-foreground` — cell text vs secondary text (dates, captions, empty state).
52
- - `muted` — hover wash, selected-row fill, classic header wash, skeletons.
53
- - `primary` — checkbox fills and the focused edit widget's emphasis; `ring` — focus.
54
- - **Status/enum pills** — the `metadata.options` `color` field is specified as a token role (status roles or `chart-1..5`), never a hex literal; the pill resolves its tint from the role so package switches re-skin every pill. A table whose status column embeds literals renders wrong in the other theme while every other check stays green — this is the token-reach report's primary target.
55
- - **Sparkline cells** — `metadata.sparklineColors` defaults must resolve to `chart-1..5`; a sparkline never carries a color literal.
56
- - Destructive row actions use `destructive`. Numeric cells render with tabular numerals.
57
-
58
- ## When to use / composition notes
59
-
60
- The data table is the default projection for browse and queue archetypes — reach for it whenever rows are the unit of work and columns are attributes the operator scans, sorts, or edits in place. Real pagination and status chips are positive obligations for any believable table. Start read-only (the default) and make columns editable one at a time only where in-place editing is the actual workflow; keep sorting/pagination state in the page (the table is deliberately stateless about both) so URLs and refreshes preserve the operator's position. For bespoke markup the recipe's DOM contract is the semantic-table layer itself (`UiTable` under `nurix`), not a div grid.
61
-
62
- - **`primitives: nurix`** — `import { Table, defineColumn } from "@nurix/components/table";` (escape hatches: cell renderers like `StatusPill` are exported from the same subpath; the bare primitive layer is `@nurix/components/ui-table`).
63
- - **`primitives: native`** — this recipe is the build spec: a semantic `<table>` (never a div grid) with a sticky header, tabular numerals, externally controlled sort (max 3 columns) and 1-indexed pagination with ellipsis collapse, an opt-in checkbox selection column with a tri-state header, read-only-by-default cells with the commit/revert keyboard semantics above, and every status/spark color resolved from the token artifact.
@@ -1,60 +0,0 @@
1
- ---
2
- id: side-panel
3
- class: d2
4
- sourced: 2026-07-12
5
- source: "@nurix/components Sheet (shadcn sheet on @radix-ui/react-dialog, extended with size variants + SheetBody) — ~/dev/components"
6
- license: open
7
- ---
8
-
9
- # Chrome recipe — side panel
10
-
11
- The slide-in detail/edit panel: a modal surface anchored to a screen edge with a fixed header → scrollable body → pinned footer skeleton. Built on dialog semantics (focus trap, Escape, overlay), so it inherits correct modality for free.
12
-
13
- ## Anatomy
14
-
15
- | Slot | Library part | Spec |
16
- | --- | --- | --- |
17
- | Root | `Sheet` | Open-state owner; controlled (`open`/`onOpenChange`) or uncontrolled via trigger. |
18
- | Trigger | `SheetTrigger` | Any element (`asChild`) that opens the panel — a table row's action, a card, a button. |
19
- | Overlay | `SheetOverlay` | Full-viewport scrim behind the panel; fades with open state; click closes. |
20
- | Panel | `SheetContent { side: "right" (default) \| "left" \| "top" \| "bottom", size: "sm" 320px \| "md" 384px \| "default" 480px \| "lg" 640px \| "xl" 800px \| "full", showCloseButton?, showOverlay? }` | Fixed to the chosen edge, full-height (left/right), hairline border on the attached edge, elevated shadow, vertical flex column. Below the small breakpoint it takes ~full width regardless of size. |
21
- | Header | `SheetHeader { showDivider? }` | Shrink-to-content top region: `SheetTitle` (the accessible name — a visually hidden fallback title exists, but a real one is the spec) + `SheetDescription` in muted text. |
22
- | Body | `SheetBody { noPadding? }` | `flex-1` scroll region — the only part that scrolls; long content never pushes the footer off-screen. |
23
- | Footer | `SheetFooter { showDivider? }` | Bottom-anchored action row (`mt-auto`): primary commit right, secondary/cancel beside it. |
24
- | Close | `SheetClose` + built-in ✕ | Corner close button (top-right, 70% opacity at rest) plus any element wrapped in `SheetClose`. |
25
-
26
- ## The eight states
27
-
28
- | State | Spec | Token roles |
29
- | --- | --- | --- |
30
- | default | Open at rest: panel on the base surface over the scrim; header/body/footer stacked; hairline dividers where opted in. | `background`, `border`, `foreground`, `muted-foreground` (description) |
31
- | hover | Corner close sharpens from 70% to full opacity; interior controls follow their own recipes. | control-level roles |
32
- | focus | Focus is trapped inside the open panel; the close button and every control show a focus-visible ring. | `ring` |
33
- | active | Open/closed is expressed as `data-state` driving the slide + fade transition. The library ships 500ms in / 300ms out; the A6 panel budget (200–280ms, interruptible) governs — the package motion base overrides the stock duration, and a non-interruptible slide is a bug, not a style. | — |
34
- | disabled | The commit action disables (~50% opacity, no pointer events) while the form is invalid or a save is in flight; the panel itself never disables — Escape and close always work. | reduced-alpha on controls |
35
- | loading | Record still resolving: header renders immediately with the known title, body shows skeleton blocks, footer actions disabled. The panel never opens empty-then-jumps. | `muted` (skeleton) |
36
- | error / empty | Save failure: inline error summary at the top of the body plus per-field errors — the panel stays open, input preserved. A missing record renders an empty state in the body with a close affordance. | `destructive`, `muted-foreground` |
37
- | success | A committed save closes the panel and confirmation lands as a toast in the parent context; a multi-step flow may show transient inline success on the footer action before advancing. | `success` status role |
38
-
39
- ## Keyboard behavior
40
-
41
- - Activating the trigger opens the panel; focus moves inside (first focusable element, else the close button).
42
- - **Tab / Shift+Tab** cycle within the panel only — a full focus trap; background content is inert (`aria-modal="true"`, `role="dialog"`, labeled by the title).
43
- - **Escape** closes and returns focus to the element that opened it. Overlay click does the same. If the body holds unsaved edits, close asks before discarding — Escape never silently destroys input.
44
- - **Enter** in a single-field form commits; the footer's primary action is the default submit.
45
- - **cmdk path**: a command-palette action that opens a record panel behaves exactly like a pointer trigger — the panel takes focus on open and restores it to the palette's invoking context on close.
46
-
47
- ## Token reach
48
-
49
- - `background` — the panel surface; `border` — the attached-edge hairline and the header/footer dividers.
50
- - `foreground` / `muted-foreground` — title / description and secondary text.
51
- - `ring` — the focus trap's visible rings, including the corner close.
52
- - Scrim: the library hardcodes `black/50` — as a specification the scrim derives from a token (an overlay role, or `foreground` at low alpha) so dark themes don't double-darken; the token-reach report flags a literal scrim.
53
- - Footer actions consume the button recipe's roles (`primary`/`primary-foreground`, `secondary`, `destructive`); inline errors consume `destructive`; skeletons consume `muted`.
54
-
55
- ## When to use / composition notes
56
-
57
- The side panel is edit-in-context: opening a record's detail or a scoped form beside a table, board, or list without losing the operator's position — the list stays visible under the scrim and scroll position survives the round trip. It is the wrong container for destructive confirmation (centered dialog), for navigation (sidebar), and for content that deserves its own URL (a full page — if operators share links to it, it's a page). Pick `size` by content: `sm`/`md` for quick property edits, `default`/`lg` for record detail, `xl` for side-by-side comparison; nested panels are a smell — a second level of depth means the flow wants a page. Footer actions: one primary commit, right-aligned; cancel is quiet, never a second primary.
58
-
59
- - **`primitives: nurix`** — `import { Sheet, SheetTrigger, SheetContent, SheetHeader, SheetTitle, SheetDescription, SheetBody, SheetFooter, SheetClose } from "@nurix/components/sheet";`
60
- - **`primitives: native`** — this recipe is the build spec: a portal-rendered fixed aside on the chosen edge with the size ramp above, dialog semantics (`role="dialog"`, `aria-modal`, labeled by the title), a real focus trap with focus restore, Escape + overlay close, a fixed-header / scrollable-body / pinned-footer column, and an interruptible slide within the panel motion budget — implemented with the incumbent stack's own dialog/drawer primitive.
@@ -1,78 +0,0 @@
1
- ---
2
- id: sidebar
3
- class: d2
4
- sourced: 2026-07-12
5
- source: "@nurix/components Sidebar + opinionated layer (Brand, Switcher, ItemGroup, UserMenu, Callout, FileTree, SidebarCommandTrigger) — ~/dev/components"
6
- license: open
7
- ---
8
-
9
- # Chrome recipe — sidebar
10
-
11
- The complete app-nav sidebar: brand block, searchable sections, badged items, promo slot, user footer, icon-collapse rail. One import path (`@nurix/components/sidebar`) carries both the unstyled shell primitives and the opinionated content layer.
12
-
13
- ## Anatomy
14
-
15
- **Shell** (state + regions):
16
-
17
- | Slot | Library part | Spec |
18
- | --- | --- | --- |
19
- | Provider | `SidebarProvider` | Owns open/collapsed state; persists it in a cookie (`sidebar_state`, 7 days); registers the global toggle shortcut. |
20
- | Frame | `Sidebar` | `collapsible: "icon" \| "offcanvas" \| "none"`. Widths: 16rem expanded, 3rem icon rail, 18rem as a mobile drawer below the `md` breakpoint (mobile renders as an overlay sheet, not an inline column). |
21
- | Header | `SidebarHeader` | Pinned top region — hosts the brand block or switcher, and the search trigger. |
22
- | Content | `SidebarContent` | The scrollable middle — one or more item groups. |
23
- | Footer | `SidebarFooter` | Pinned bottom region — promo slot and/or user footer. |
24
- | Rail | `SidebarRail` | Thin edge hit-area that toggles collapse on click. |
25
- | Inset | `SidebarInset` | The main-content wrapper beside the sidebar. |
26
- | Trigger | `SidebarTrigger` | Icon button (lives in the topbar) toggling the same state. |
27
-
28
- **Content layer** (each grounded in the shipped props):
29
-
30
- - **Brand block** — `Brand { logo, name, caption?, href? }`: a 32px logo tile filled with `sidebar-primary` / `sidebar-primary-foreground`, name (medium weight) over an optional caption. Collapses to logo-only in icon mode.
31
- - **Switcher** — `Switcher { render: "simple" | "rich", drop: "bottom" | "right", options, activeId, onSelect, addAction?, menuLabel? }`: header dropdown for team/workspace/version. Options carry `{ id, label, sublabel?, icon?, shortcut? }`; an optional add-action row sits under a separator.
32
- - **Search trigger** — `SidebarCommandTrigger { placeholder, shortcut }`: a ⌘K search chip pinned to 32px height; in icon mode it swaps to a matched-height icon button with a tooltip, so the rail never shifts on collapse.
33
- - **Sections** — `ItemGroup { label?, render: "list" | "tree" | "rich", collapsible?, defaultOpen?, showMore?, items, itemsCollapsible?, compact?, collapsedLabel: "hide" | "divider" }`. `list` = flat rows with optional inline collapsible submenu; `tree` = recursive chevron tree; `rich` = two-line rows (label + sublabel + trailing hint). `collapsedLabel: "divider"` keeps a 32px hairline footprint in icon mode so groups stay separated without rail shift. `compact` halves group padding and tightens item gap.
34
- - **Item** — `{ id, label, icon?, badge?, state?, emoji?, avatar?, sublabel?, trailing?, isActive?, href?, onClick?, children? }`: one leading decoration (icon, emoji, or avatar), the label, and a trailing badge/state pill rendered outside the button (`SidebarMenuBadge`). `children` makes it a branch.
35
- - **Promo slot** — `Callout { title, description?, action?, input?: { kind: "email" | "text", placeholder?, onSubmit? } }`: a bordered card on a low-alpha `sidebar-accent` wash with title, description, optional single input + full-width action button. Hidden entirely in icon mode.
36
- - **User footer** — `UserMenu { user: { name, email, avatar? }, menuItems? }`: avatar (initials fallback) + name/email + up-down chevron; opens a dropdown (right of the rail on desktop, below on mobile) with an identity header and action items (`{ id, label, icon?, shortcut?, destructive? }`).
37
-
38
- ## The eight states
39
-
40
- | State | Spec | Token roles |
41
- | --- | --- | --- |
42
- | default | Rows at rest: transparent fill, quiet text, 16px icons. | `sidebar` (surface), `sidebar-foreground` |
43
- | hover | Row fills; text sharpens. Group labels with collapse affordance show a pointer + chevron. | `sidebar-accent`, `sidebar-accent-foreground` |
44
- | focus | Focus-visible ring on the focused row/control; same fill as hover. Never suppressed. | `sidebar-ring` |
45
- | active | The current destination: persistent fill + medium weight, exposed via `data-active` / `aria-current`. Open branch parents show a rotated chevron; an open dropdown trigger holds the accent fill (`data-state="open"`). | `sidebar-accent`, `sidebar-accent-foreground` |
46
- | disabled | ~50% opacity, no pointer events, removed from tab order; label still legible. | `sidebar-foreground` at reduced alpha |
47
- | loading | `SidebarMenuSkeleton` rows — icon square + text bar shimmer — while nav data resolves; header and footer regions render immediately so the frame never jumps. | `muted` (skeleton), `sidebar-border` |
48
- | error / empty | A group with nothing to show renders a one-line hint in muted text or is omitted; the sidebar itself carries no error surface — failures belong to content. Attention counts ride item badges. | `muted-foreground`; `destructive` on alert badges |
49
- | success | No persistent success state; confirmation is expressed as badge-count change or a status-role pill on the relevant item. | status roles via badge |
50
-
51
- ## Keyboard behavior
52
-
53
- - **Cmd/Ctrl+B** toggles collapse globally (registered by `SidebarProvider`); `SidebarTrigger` and `SidebarRail` are the pointer equivalents.
54
- - **Tab order**: header (brand/switcher → search trigger) → groups top-to-bottom, items in visual order → footer user menu. Items are real links or buttons — **Enter** activates, **Space** activates buttons.
55
- - **Branches**: Enter/Space on a collapsible parent toggles it; the chevron rotation mirrors `data-state`.
56
- - **Dropdowns** (Switcher, UserMenu): Enter/Space opens; arrow keys move through options; Enter selects; **Escape** closes and returns focus to the trigger.
57
- - **cmdk path**: the search chip opens the command palette (⌘K); deep or infrequent destinations live in the palette — the sidebar carries the trigger, not a second search UI.
58
- - **Icon mode**: focus order is unchanged; each item surfaces its label as a tooltip on focus/hover so keyboard users are never navigating unlabeled glyphs.
59
-
60
- ## Token reach
61
-
62
- The sidebar consumes the eight dedicated sidebar roles — the active package's emission must cover all eight in both themes:
63
-
64
- - `sidebar` — the rail/panel surface (distinct from content `background`).
65
- - `sidebar-foreground` — item and label text.
66
- - `sidebar-primary` / `sidebar-primary-foreground` — the brand logo tile and any primary emphasis.
67
- - `sidebar-accent` / `sidebar-accent-foreground` — hover, active, and open-menu fills.
68
- - `sidebar-border` — hairlines: the panel edge, icon-mode group dividers.
69
- - `sidebar-ring` — focus rings.
70
-
71
- Secondary reach: the Callout uses `sidebar-border` + a low-alpha `sidebar-accent` wash + `muted-foreground`; dropdown menus render on `popover` / `popover-foreground`; destructive menu items use `destructive`; skeletons use `muted`. No color literal appears anywhere in the recipe — badge and state-pill colors resolve to status roles.
72
-
73
- ## When to use / composition notes
74
-
75
- The sidebar is the primary navigation for any operator shell with more than a handful of destinations; icon-collapse earns its place on dense screens where horizontal space is the scarce resource, and the cookie-persisted state means the user's choice survives reloads. Canonical composition: `Brand` **or** `Switcher` in the header (both only when the product truly has workspace switching), the search trigger under it, one to three `ItemGroup`s in the content (label them once there are two), and the footer stacking `Callout` (optional, promotional, dismissible by omission) above `UserMenu`. Icons on every item are a positive obligation — a bare, icon-less nav is a known judge complaint. Density: `compact` on data-heavy operator tools, default elsewhere.
76
-
77
- - **`primitives: nurix`** — `import { SidebarProvider, Sidebar, SidebarHeader, SidebarContent, SidebarFooter, SidebarRail, SidebarInset, SidebarTrigger, Brand, Switcher, ItemGroup, UserMenu, Callout, SidebarCommandTrigger } from "@nurix/components/sidebar";`
78
- - **`primitives: native`** — this recipe is the build spec: a fixed aside (256px expanded / 48px icon rail) with pinned header/footer and an independently scrolling middle, collapse state persisted (cookie or localStorage), a global Cmd/Ctrl+B toggle, an overlay drawer below 768px, tooltips on rail items, and the state/keyboard/token contracts above implemented with the incumbent stack's own nav primitives.
@@ -1,62 +0,0 @@
1
- ---
2
- id: stat-cards
3
- class: d2
4
- sourced: 2026-07-12
5
- source: "@nurix/components Statistics compound family (+ AnimatedNumber, useStatHoverBridge; visuals host Gauge/Spark/ProgressBar/ChartLegend) — ~/dev/components"
6
- license: open
7
- ---
8
-
9
- # Chrome recipe — stat cards
10
-
11
- The stat-card family: one compound grammar for every KPI tile, gauge card, sparkline card, legend card, and list card. The root is a structural flex column providing shared context (`size`, `comparisonLabel`); ~two dozen dotted parts compose the regions. The card draws no chart geometry itself — the visual slot hosts a chart element. The dashboard-tile obligation applies to every instance: **number + comparison + trend + state + door**.
12
-
13
- ## Anatomy
14
-
15
- | Slot | Library part | Spec |
16
- | --- | --- | --- |
17
- | Root | `Statistics { size: "sm" \| "md" \| "lg", variant: "bare" \| "card" \| "elevated" \| "outline" \| "soft" \| "ghost", accent: "none" \| "primary" \| "success" \| "warning" \| "danger" \| "info", gap, justify, comparisonLabel }` | The surface. `bare` draws nothing (consumer owns the wrapper); the rest share `overflow-hidden rounded p-6` with their own background/border/shadow. `accent` draws a 4px left stripe. `size` scales the headline value and title through context. |
18
- | Section | `StatisticsSection` | Vertical region group for top/bottom cascades (`justify: "between"` pins one to each end). |
19
- | Header | `StatisticsHeader` → `StatisticsIcon { variant, tone: "soft" \| "solid" \| "outline" \| "plain", size (incl. "oversized"), shape }` + `StatisticsHeading` (`StatisticsTitle`, `StatisticsDescription`) + `StatisticsActions` | Icon/title block left, trailing actions (menu, info, tabs, date range) right. `oversized` icons bleed out the clipped top-right corner as a decorative watermark. |
20
- | Metric row | `StatisticsMetric` → `StatisticsValue { animated?, value, format, prefix, suffix }` + `StatisticsUnit` + `StatisticsTrend { value, direction?, invert?, pill?, format? }` + `StatisticsComparison` | Baseline-aligned: headline value (static, or digit-animated via NumberFlow with a formatted static first paint — SSR-safe), unit ("/ 5,000"), signed trend badge, comparison label (falls back to the card's `comparisonLabel`). |
21
- | Visual | `StatisticsVisual` (layout via `StatisticsGroup` horizontal/vertical) | Generic centered slot hosting `<Spark>`, `<Gauge>`, `<ProgressBar>`, `<ChartLegend>`, or any chart element. (Legacy `StatisticsGauge`/`Progress`/`SegmentedBar`/`Sparkline`/`Legend*` parts are deprecated thin wrappers over those same components.) |
22
- | Content | `StatisticsContent` | Escape hatch for list / table / paragraph cards. |
23
- | Footer | `StatisticsFooter` → `StatisticsCaption` + `StatisticsLink` | Freshness caption left ("Updated 2m ago" — the tile's *state*), link right (the tile's *door*). |
24
- | Hover bridge | `useStatHoverBridge()` | Headless hook lifting a hovered chart point into the header: hand its `onHoverChange` to the embedded graph, read `hover.value`/`hover.label` in the value/description with a resting fallback. |
25
-
26
- Every part emits `data-slot="statistics-…"` for styling and testing hooks.
27
-
28
- ## The eight states
29
-
30
- | State | Spec | Token roles |
31
- | --- | --- | --- |
32
- | default | Card variant on the card surface with a hairline border; value at display scale with tabular numerals; title strong, description muted. | `card` + `card-foreground`, `border`, `foreground`, `muted-foreground` |
33
- | hover | Elevated variants lift per the package's elevation ramp; with the hover bridge wired, hovering the embedded chart live-rewrites the value and description to the hovered point, reverting on leave. | elevation system; value stays `foreground` |
34
- | focus | The door (footer link or whole-card link) and any header action are focus stops with visible rings. | `ring` |
35
- | active | A clickable card shows a pressed treatment; the accent stripe marks category or alert affiliation. | `accent` stripe via `primary`/status roles |
36
- | disabled | No permission for the metric: value masked (—), lock caption, non-interactive, ~50% presence — the tile keeps its footprint. | reduced-alpha, `muted-foreground` |
37
- | loading | Skeleton title bar + value block + visual area at the card's fixed height — the grid never reflows when data lands. | `muted` |
38
- | error / empty | Degraded: em-dash value + status-role caption ("stale as of 09:12") — never a fabricated number. Empty series: the visual slot shows a quiet hint, never a zeroed fake chart. | `warning` / `destructive` caption, `muted-foreground` |
39
- | success | Trend intent is the success surface: up = good on the success role, down = bad on `destructive`; `invert` flips the mapping for lower-is-better metrics (error rate, latency, churn); zero/no-direction = neutral muted. `pill` wraps it in a tinted badge. Exposed as `data-direction`. | `success` / `destructive` status roles |
40
-
41
- ## Keyboard behavior
42
-
43
- - A stat card is mostly static content; its interactive elements — header actions, the footer link, a clickable card — join the tab order in reading order (header action → door), **Enter** activates.
44
- - The hover bridge is a pointer-only *enhancement*: the resting value is always the correct headline without any pointer, so keyboard and touch users lose nothing; point inspection falls to the embedded chart's own keyboard/tooltip behavior.
45
- - An actions menu follows menu semantics: Enter/Space opens, arrows move, Escape closes to the trigger.
46
- - Animated values render as real formatted text (static until the animation element registers), so the accessible name is always the current number — no aria gymnastics required.
47
- - **cmdk path**: none — tiles are destinations for the palette ("Go to revenue"), not hosts of it.
48
-
49
- ## Token reach
50
-
51
- - `card` / `card-foreground` — surface and text; `border` — hairline (outline/card variants); `muted` / `muted-foreground` — description, captions, skeletons.
52
- - Accent stripe and `StatisticsIcon` variants — `primary` plus the status roles (`success`, `warning`, `destructive`/danger, `info`) at soft/solid/outline tones.
53
- - `StatisticsTrend` — **status roles only**. Known library deviation: the shipped component pins success intent to Tailwind `emerald-500` literals and has no success token; under `nurix` the trend/icon success tints are restyled in place to the package's `success` role (the no-jails law permits this; the token-reach report flags the literal), and under `native` the implementation uses status roles from the start.
54
- - Embedded visuals — `chart-1..5` for series color, chart chrome roles (`chart-grid`, `chart-tooltip-background/foreground`) for scaffolding; a spark/gauge/progress fill is never a hex literal. The default spark stroke (`var(--primary)`) already token-reaches.
55
- - The headline value inherits the type ramp's display size via the card `size`; mono/tabular figures come from the package's type roles, never a hardcoded family.
56
-
57
- ## When to use / composition notes
58
-
59
- Stat cards are the dashboard's KPI strip (4–6 tiles full-width per the blueprint shapes) and the record header's vital signs; the same grammar scales from a bare number-plus-trend to a gauge card with a legend, so one card system covers the whole surface. Every tile carries all five obligations — a number without a comparison is decoration, a tile without a door is a dead end. Use `size` to build hierarchy (one `lg` hero metric, `md` support tiles) instead of ad-hoc font sizes; use `justify="between"` with two sections for cards whose visual anchors the bottom edge. Wire the hover bridge whenever a chart lives in the card — it is the cheapest "designed, not templated" signal in the set.
60
-
61
- - **`primitives: nurix`** — `import { Statistics, StatisticsHeader, StatisticsIcon, StatisticsHeading, StatisticsTitle, StatisticsDescription, StatisticsActions, StatisticsMetric, StatisticsValue, StatisticsUnit, StatisticsTrend, StatisticsComparison, StatisticsVisual, StatisticsFooter, StatisticsCaption, StatisticsLink, useStatHoverBridge } from "@nurix/components/statistics";` (visuals: `@nurix/components/spark`, `/gauge`, `/progress-bar`; the animated number: `@nurix/components/animated-number`).
62
- - **`primitives: native`** — this recipe is the build spec: a fixed-height card with header / baseline-aligned metric row / visual slot / footer regions, a display-scale tabular headline that is correct on first paint (animation optional and additive), a sign-driven trend badge with an invert switch on status roles, skeletons that hold the footprint, degraded states that never fabricate numbers, and all series color drawn from the token artifact's `chart-1..5`.
@@ -1,65 +0,0 @@
1
- ---
2
- id: topbar
3
- class: d2
4
- sourced: 2026-07-12
5
- source: "@nurix/components — composed pattern: SidebarTrigger + Separator + Breadcrumb family + CommandTrigger + Button (the library's site-header pattern; no single Topbar export) — ~/dev/components"
6
- license: open
7
- ---
8
-
9
- # Chrome recipe — topbar
10
-
11
- The app-shell top bar: the sticky row above the content pane carrying the sidebar toggle, the breadcrumb trail, global search, and screen-level actions. In `@nurix/components` this is a **documented composition, not a single export** — every shipped app-shell demo assembles it from `SidebarTrigger`, `Separator`, the `Breadcrumb` family, `CommandTrigger`, and `Button`. Page-level mastheads below it are separate components (`Header` at `@nurix/components/header` for config-driven record headers; `PageHeader` for list/detail mastheads with a stat ledger) and are not part of this recipe.
12
-
13
- ## Anatomy
14
-
15
- | Slot | Library part | Spec |
16
- | --- | --- | --- |
17
- | Bar | flex row | Sticky (`top-0`), 48–56px tall, full width of the content pane, hairline bottom border. Optional glass treatment: `background` at ~95% alpha + backdrop blur. |
18
- | Sidebar toggle | `SidebarTrigger` | Leading icon button toggling the sidebar; reflects open state via `data-state`. |
19
- | Divider | `Separator orientation="vertical"` | 16px vertical hairline between toggle and breadcrumbs. |
20
- | Breadcrumbs | `Breadcrumb` → `BreadcrumbList` / `BreadcrumbItem` / `BreadcrumbLink` / `BreadcrumbSeparator` / `BreadcrumbPage` | The location trail. Ancestors are links; the last segment is `BreadcrumbPage` — plain text, `aria-current="page"`, never a link. Deep trails collapse middle segments into an ellipsis dropdown. |
21
- | Spring | flex spacer | Pushes the trailing cluster right. |
22
- | Search slot | `CommandTrigger { placeholder, shortcut }` | A bordered search chip with placeholder text and a right-aligned `⌘K` kbd hint; opens the command palette. |
23
- | Actions | `Button` (ghost/icon), overflow `DropdownMenu` | At most 3 visible screen-level actions; further actions collapse into an overflow menu. Theme toggle sits here. |
24
- | Identity | `Avatar` (optional) | Only when the shell has no sidebar user footer — one identity home per shell, never two. |
25
-
26
- ## The eight states
27
-
28
- State is mostly per-control; the bar itself is stable chrome.
29
-
30
- | State | Spec | Token roles |
31
- | --- | --- | --- |
32
- | default | Bar on the content canvas with a hairline base; breadcrumb ancestors quiet, current page at full strength. | `background`, `border`, `muted-foreground` (ancestors), `foreground` (current) |
33
- | hover | Breadcrumb links sharpen to full foreground; icon buttons gain an accent fill. | `foreground`, `accent` + `accent-foreground` |
34
- | focus | Focus-visible ring on every control — toggle, links, chip, buttons. | `ring` |
35
- | active | Sidebar toggle mirrors the open sidebar (`data-state`); the current crumb is the persistent active marker; a pressed action holds its pressed fill. | `foreground`, `accent` |
36
- | disabled | Actions at ~50% opacity, no pointer events; breadcrumbs are never disabled. | reduced-alpha foreground |
37
- | loading | An in-flight screen action shows an inline spinner inside its own button. The bar never skeletons: breadcrumbs derive from the route and render immediately. | `muted-foreground` (spinner) |
38
- | error / empty | An empty trail renders the page title as the single `BreadcrumbPage`. Errors surface as toasts or content-level states — the bar itself hosts none; a degraded-environment banner may attach *beneath* the bar on a status-role tint. | `warning` / `destructive` (banner only) |
39
- | success | Transient: an action button briefly swaps to a check, or a toast confirms; nothing persistent lives in the bar. | `success` status role (transient) |
40
-
41
- ## Keyboard behavior
42
-
43
- - **Tab order**: the bar follows the skip link and precedes the content pane — toggle → breadcrumb links → search chip → actions → identity. Plain sequential tabbing; no roving focus is needed at this control count.
44
- - **Enter** activates crumbs and buttons; **Space** activates buttons.
45
- - **Cmd/Ctrl+B** toggles the sidebar from anywhere (provider-owned); the `SidebarTrigger` is its visible affordance.
46
- - **cmdk path**: **⌘K / Ctrl+K** opens the command palette from anywhere; the search chip is the visible, clickable affordance and displays the shortcut as a kbd hint. Inside the palette: type to filter, arrows to move, Enter to run, Escape to close. Global navigation and infrequent actions belong in the palette, not as more topbar buttons.
47
- - Overflow menu: Enter/Space opens, arrows move, Escape closes and returns focus to the trigger.
48
-
49
- ## Token reach
50
-
51
- - `background` — the bar surface (with optional alpha for the glass treatment). The bar sits on the content canvas: it never consumes the `sidebar-*` roles.
52
- - `border` — the bottom hairline and the vertical separator.
53
- - `foreground` / `muted-foreground` — current crumb vs ancestors; icon default strength.
54
- - `accent` / `accent-foreground` — icon-button hover/pressed fills.
55
- - `ring` — focus rings.
56
- - `popover` / `popover-foreground` — overflow and ellipsis dropdowns.
57
- - `primary` — at most one primary CTA, only when the screen genuinely has a single dominant action.
58
- - Status roles (`warning`, `destructive`, `success`) — only for the attached environment banner and transient confirmations; never as bar decoration.
59
-
60
- ## When to use / composition notes
61
-
62
- Every screen inside the shell gets the topbar; it is the constant that makes the sidebar collapsible (the toggle must survive collapse) and the command palette discoverable. Keep it thin — the topbar locates and searches; identity-weight content (record title, status, metadata, stats) belongs to the page masthead below it (`Header` / `PageHeader` under `nurix`), and datasets' own toolbars belong to their tables. The three-zone rhythm — locate left, search center-right, act right — is the invariant; what varies per product is only which trailing actions earn a permanent slot.
63
-
64
- - **`primitives: nurix`** — composed, e.g.: `import { SidebarTrigger } from "@nurix/components/sidebar"; import { Breadcrumb, BreadcrumbList, BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator } from "@nurix/components/breadcrumb"; import { CommandTrigger } from "@nurix/components/command"; import { Separator } from "@nurix/components/separator"; import { Button } from "@nurix/components/button";`
65
- - **`primitives: native`** — this recipe is the build spec: a sticky 48–56px flex row with the slot order above, a real `<nav aria-label="Breadcrumb">` trail with `aria-current="page"` on the last segment, a search affordance wired to the stack's palette (or a plain search route) showing its shortcut, and the state/keyboard/token contracts implemented with the incumbent stack's own primitives.
@@ -1,19 +0,0 @@
1
- ---
2
- id: ant-design-directional-shadow
3
- class: a3
4
- sourced: 2026-07-12
5
- source: "distilled from ant.design/docs/spec/shadow"
6
- license: open
7
- feel: "enterprise-friendly, directionally aware; drawers and fixed headers cast shadow toward the content they overlay, not just downward"
8
- ---
9
- Ant Design is unusual in defining shadow **direction** as a first-class variable: the same three-layer blur/opacity recipe is mirrored down/up/left/right depending on where the component sits (a right-side drawer casts left, a bottom-fixed table header casts up). Three layers per direction blend from a tight, high-opacity contact shadow to a huge, near-invisible ambient one.
10
-
11
- ```yaml values
12
- radius: { sm: 4, md: 6, lg: 8 }
13
- hairline: "none at rest; inputs use a separate 1px border token, not shared with the shadow system"
14
- shadow:
15
- layer1-down: "0px 1px 2px -2px rgba(0,0,0,.16), 0px 3px 6px 0px rgba(0,0,0,.12), 0px 5px 12px 4px rgba(0,0,0,.09)"
16
- layer2-down: "0px 3px 6px -4px rgba(0,0,0,.12), 0px 6px 16px 0px rgba(0,0,0,.08), 0px 9px 28px 8px rgba(0,0,0,.05)"
17
- layer3-down: "0px 6px 16px -8px rgba(0,0,0,.08), 0px 9px 28px 0px rgba(0,0,0,.05), 0px 12px 48px 16px rgba(0,0,0,.03)"
18
- dark-ladder: { step: "+~5L per level (v5 dark algorithm inverts the neutral scale)", hue: held }
19
- ```
@@ -1,18 +0,0 @@
1
- ---
2
- id: apple-liquid-glass-material
3
- class: a3
4
- sourced: 2026-07-12
5
- source: "distilled from developer.apple.com/design/human-interface-guidelines/materials"
6
- license: reference-only
7
- feel: "spatial, translucent, light-reactive; depth comes from a refractive material simulating glass thickness, not a fixed shadow token"
8
- ---
9
- Apple's newest materials model (Liquid Glass) ties elevation to simulated material *thickness* rather than a discrete shadow scale: as a glass element grows or is interacted with, it "flexes" to a thicker material with deeper shadow and more pronounced lensing/refraction. Darker, denser materials deliberately mute shadow legibility, trading depth for reduced visual noise — the opposite trade every other system here makes.
10
-
11
- ```yaml values
12
- radius: { sm: 10, md: 16, lg: 28 }
13
- hairline: "none as a drawn line — edge definition comes from the material's own refractive/specular edge"
14
- shadow:
15
- base: "shadow deepens dynamically as the glass element scales up (material 'flexes' thicker)"
16
- scroll: "shadow intensifies as content scrolls beneath it, to preserve separation"
17
- dark-ladder: { step: "n/a — darker/denser materials intentionally reduce shadow legibility rather than laddering lightness", hue: held }
18
- ```
@@ -1,20 +0,0 @@
1
- ---
2
- id: atlassian-surface-shadow-pairing
3
- class: a3
4
- sourced: 2026-07-12
5
- source: "distilled from atlassian.design/foundations/elevation and /foundations/radius; radius px approximated from usage guidance, exact figures not published in source"
6
- license: open
7
- feel: "structured enterprise calm; every raised surface ships as a matched surface+shadow pair, never a shadow in isolation"
8
- ---
9
- Atlassian defines four discrete elevations — sunken, default, raised, overlay — and enforces that `elevation.surface.*` and `elevation.shadow.*` tokens are always used together, never mixed across levels. In dark mode the rule inverts intuition: higher elevation surfaces get **lighter**, not darker, simulating front-lighting rather than cast shadow.
10
-
11
- Approximation note: radius px approximated from usage guidance — exact figures are not published in the source and should be checked before shipping.
12
-
13
- ```yaml values
14
- radius: { sm: 3, md: 6, lg: 8 }
15
- hairline: "none at rest — sunken/default read via fill color, not a border line"
16
- shadow:
17
- raised: "0px 1px 1px #091E4240, 0px 0px 1px #091E424F"
18
- overlay: "0px 8px 12px #091E4226, 0px 0px 1px #091E424F"
19
- dark-ladder: { step: "+~4L per level — \"the higher the elevation, the lighter the surface looks\"", hue: held }
20
- ```
@@ -1,20 +0,0 @@
1
- ---
2
- id: fluent-2-key-ambient-ramp
3
- class: a3
4
- sourced: 2026-07-12
5
- source: "distilled from fluent2.microsoft.design/elevation"
6
- license: open
7
- feel: "Windows-native layered light; every shadow is a paired sharp key + soft ambient cast, doubling in blur up the ramp"
8
- ---
9
- Fluent 2 generates its whole shadow ramp from one equation: each step doubles the prior step's blur (shadow2 → 4 → 8 → 16 → 28 → 64), always as a key+ambient pair. Dark mode doesn't lighten surfaces — it simply raises the shadow's own opacity (~0.14 → ~0.28) to stay visible against a dark canvas.
10
-
11
- ```yaml values
12
- radius: { sm: 2, md: 4, lg: 6 }
13
- hairline: "none by default — shadow2 (near-hairline blur) covers the lowest resting state"
14
- shadow:
15
- shadow2: "0 0.5px 1px rgba(0,0,0,.14)"
16
- shadow8: "0 4px 8px rgba(0,0,0,.14)"
17
- shadow16: "0 8px 16px rgba(0,0,0,.14)"
18
- shadow64: "0 0.5px 1px rgba(0,0,0,.24), 0 0 8px rgba(0,0,0,.20)"
19
- dark-ladder: { step: "n/a — dark mode doubles shadow alpha (~.14→.28) rather than lightening surfaces", hue: held }
20
- ```
@@ -1,19 +0,0 @@
1
- ---
2
- id: github-primer-sparing-shadow
3
- class: a3
4
- sourced: 2026-07-12
5
- source: "distilled from primer.style/product/css-utilities/box-shadow and primer.style/foundations/css-utilities/borders"
6
- license: open
7
- feel: "developer-tool restraint; flat-and-bordered by default, shadow is the deliberate exception, never the everyday chrome"
8
- ---
9
- Primer's stated philosophy is to use shadow *sparingly*: small shadows for things that need to feel slightly elevated (pricing cards), medium for editorialized clickable content, and large reserved almost entirely for marketing pages and screenshots — never for ordinary product UI, which relies on `border-default` instead.
10
-
11
- ```yaml values
12
- radius: { sm: 4, md: 6, lg: 8 }
13
- hairline: "border-default, 1px solid — the primary separation mechanic; shadow is the exception, not the rule"
14
- shadow:
15
- small: "subtle lift — pricing cards, attention-getting UI"
16
- medium: "diffused, larger — editorialized clickable content"
17
- large: "very diffused, used sparingly — marketing content and screenshots only"
18
- dark-ladder: { step: "+~3L per level (canvas-default #0d1117 → canvas-subtle/overlay)", hue: held }
19
- ```
@@ -1,19 +0,0 @@
1
- ---
2
- id: ibm-carbon-layer-and-border
3
- class: a3
4
- sourced: 2026-07-12
5
- source: "distilled from v11.carbondesignsystem.com/guidelines/color/implementation and Carbon's elevation guidance"
6
- license: open
7
- feel: "flat, rectilinear, enterprise-IBM; depth is a color-and-border swap between layers, almost never a cast shadow"
8
- ---
9
- Carbon's default posture is nearly shadow-free: each of its layer tokens (`layer-01/02/03`) is paired 1:1 with a matching border token, so nesting a panel inside a panel is a background-color-plus-border swap, not a shadow stack. Shadow is reserved almost exclusively for true overlays — dropdowns and modals. Corners stay square almost everywhere, in keeping with Carbon's rectilinear IBM heritage.
10
-
11
- ```yaml values
12
- radius: { sm: 0, md: 0, lg: 2 }
13
- hairline: "$border-strong-0X paired with $layer-0X — the layer+border pair IS the elevation cue"
14
- shadow:
15
- layer: "none — flat; separation via layer-01/02/03 background swap + paired border"
16
- overlay: "0 2px 6px 0 rgba(0,0,0,.30)"
17
- modal: "0 8px 16px 0 rgba(0,0,0,.30)"
18
- dark-ladder: { step: "n/a — discrete named themes (White/g10 light, g90/g100 dark), not a continuous ladder", hue: held }
19
- ```
@@ -1,17 +0,0 @@
1
- ---
2
- id: linear-dark-surface-ladder
3
- class: a3
4
- sourced: 2026-07-12
5
- source: "distilled from github.com/voltagent/awesome-design-md — linear.app/DESIGN.md"
6
- license: reference-only
7
- feel: "software-craft dark mode; restraint scales — one accent, hairlines, and a shallow surface ladder carry all the hierarchy, no shadows anywhere"
8
- ---
9
- Linear runs dark-only and resists drop shadows almost entirely; elevation is a **four-step surface-lightness ladder** (surface-1 through surface-4) paired with 1px hairlines of increasing strength (default → strong → tertiary) for nested content. The steps are deliberately small — a whisper of lift, never a spotlight.
10
-
11
- ```yaml values
12
- radius: { sm: 6, md: 8, lg: 12 }
13
- hairline: "1px solid {colors.hairline} #23252a at rest; {hairline-strong} #34343a on focus; {hairline-tertiary} #3e3e44 for nested surfaces"
14
- shadow:
15
- all-levels: "none — drop shadows resisted almost entirely on dark surfaces"
16
- dark-ladder: { step: "+~2L per level (surface-1 #0f1011 → surface-2 #141516 → surface-3 #18191a → surface-4 #191a1b)", hue: held }
17
- ```
@@ -1,19 +0,0 @@
1
- ---
2
- id: material-2-key-ambient-dp-ramp
3
- class: a3
4
- sourced: 2026-07-12
5
- source: "distilled from m2.material.io/design/environment/elevation.html and m1.material.io/resources/shadows.html"
6
- license: open
7
- feel: "classic Google-Material paper-stack; every raise reads as a discrete, physical dp jump"
8
- ---
9
- The original Material model: a single dp scale (0–24) drives a fixed **key shadow + ambient shadow** pair at every level — sharp directional shadow layered under a soft diffuse one, both pure black at low opacity. No brand tint, no tonal color; the whole hierarchy is shadow-only, which is what later gave way to M3's tonal approach.
10
-
11
- ```yaml values
12
- radius: { sm: 2, md: 4, lg: 8 }
13
- hairline: none
14
- shadow:
15
- 1dp: "0 1px 1px 0 rgba(0,0,0,.14), 0 2px 1px -1px rgba(0,0,0,.12), 0 1px 3px 0 rgba(0,0,0,.20)"
16
- 8dp: "0 8px 10px 1px rgba(0,0,0,.14), 0 3px 14px 2px rgba(0,0,0,.12), 0 5px 5px -3px rgba(0,0,0,.20)"
17
- 16dp: "0 16px 24px 2px rgba(0,0,0,.14), 0 6px 30px 5px rgba(0,0,0,.12), 0 8px 10px -5px rgba(0,0,0,.20)"
18
- dark-ladder: { step: "white-overlay 5%→16% across 1dp→24dp (~+1-2% per step)", hue: held }
19
- ```