@awarebydefault/display-case 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (254) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +309 -0
  3. package/display-case.prompt.md +64 -0
  4. package/docs/ai-agents.md +126 -0
  5. package/docs/cli.md +99 -0
  6. package/docs/configuration.md +410 -0
  7. package/docs/documentation-panel.md +50 -0
  8. package/docs/examples/README.md +14 -0
  9. package/docs/examples/multi-variant.case.tsx +30 -0
  10. package/docs/examples/plain.case.tsx +22 -0
  11. package/docs/examples/tweak-control.placard.md +80 -0
  12. package/docs/examples/tweaks.case.tsx +39 -0
  13. package/docs/hierarchy.md +59 -0
  14. package/docs/quick-start.md +78 -0
  15. package/docs/style-engines.md +180 -0
  16. package/docs/testing.md +245 -0
  17. package/docs/theming.md +97 -0
  18. package/docs/tweaks.md +75 -0
  19. package/docs/writing-cases.md +144 -0
  20. package/docs/writing-placard-docs.md +194 -0
  21. package/package.json +113 -0
  22. package/skills/display-case-author-case/README.md +20 -0
  23. package/skills/display-case-author-case/SKILL.md +40 -0
  24. package/skills/display-case-author-placard-doc/README.md +24 -0
  25. package/skills/display-case-author-placard-doc/SKILL.md +65 -0
  26. package/skills/display-case-review/README.md +19 -0
  27. package/skills/display-case-review/SKILL.md +30 -0
  28. package/skills/display-case-snapshot/README.md +20 -0
  29. package/skills/display-case-snapshot/SKILL.md +29 -0
  30. package/src/checks/a11y-scanner.test.ts +240 -0
  31. package/src/checks/a11y-scanner.ts +410 -0
  32. package/src/checks/check-text.test.ts +53 -0
  33. package/src/checks/check-text.ts +78 -0
  34. package/src/checks/check.test.ts +194 -0
  35. package/src/checks/check.ts +473 -0
  36. package/src/checks/providers/pixelmatch-diff.test.ts +79 -0
  37. package/src/checks/providers/pixelmatch-diff.ts +30 -0
  38. package/src/checks/providers/playwright-driver.ts +104 -0
  39. package/src/checks/ssr-check.test.ts +73 -0
  40. package/src/checks/ssr-check.ts +96 -0
  41. package/src/checks/structure-check.cross-package.test.ts +165 -0
  42. package/src/checks/structure-check.test.ts +651 -0
  43. package/src/checks/structure-check.ts +988 -0
  44. package/src/checks/tokens-check.test.ts +159 -0
  45. package/src/checks/tokens-check.ts +162 -0
  46. package/src/cli.ts +218 -0
  47. package/src/commands/agents.test.ts +24 -0
  48. package/src/commands/agents.ts +28 -0
  49. package/src/commands/init-run.test.ts +123 -0
  50. package/src/commands/init.test.ts +63 -0
  51. package/src/commands/init.ts +412 -0
  52. package/src/commands/publish.test.ts +210 -0
  53. package/src/commands/publish.ts +292 -0
  54. package/src/core/affected.test.ts +99 -0
  55. package/src/core/affected.ts +144 -0
  56. package/src/core/catalog.test.ts +152 -0
  57. package/src/core/catalog.ts +92 -0
  58. package/src/core/discovery.test.ts +184 -0
  59. package/src/core/discovery.ts +250 -0
  60. package/src/core/manifest.ts +41 -0
  61. package/src/core/mdx-lite/__fixtures__/box-stub.tsx +7 -0
  62. package/src/core/mdx-lite/index.ts +393 -0
  63. package/src/core/mdx-lite/mdx-lite.test.ts +345 -0
  64. package/src/core/mdx-plugin.test.ts +60 -0
  65. package/src/core/mdx-plugin.ts +30 -0
  66. package/src/flow-step.test-d.ts +39 -0
  67. package/src/index.test.ts +100 -0
  68. package/src/index.ts +564 -0
  69. package/src/render/collect-styles.emotion.test.tsx +114 -0
  70. package/src/render/collect-styles.test.tsx +72 -0
  71. package/src/render/collect-styles.ts +33 -0
  72. package/src/render/documents.test.ts +184 -0
  73. package/src/render/documents.ts +88 -0
  74. package/src/render/render-node.test.tsx +160 -0
  75. package/src/render/render-node.tsx +133 -0
  76. package/src/render/ssr-primer.test.tsx +25 -0
  77. package/src/render/ssr-primer.tsx +54 -0
  78. package/src/render/ssr-render.test.tsx +142 -0
  79. package/src/render/ssr-render.tsx +63 -0
  80. package/src/render/ssr-shell.test.tsx +57 -0
  81. package/src/render/ssr-shell.tsx +54 -0
  82. package/src/server/prod-server.ts +237 -0
  83. package/src/server/server.test.ts +117 -0
  84. package/src/server/server.ts +1039 -0
  85. package/src/style-engine.test-d.ts +37 -0
  86. package/src/testing/test-helpers.ts +27 -0
  87. package/src/types/pixelmatch.d.ts +12 -0
  88. package/src/ui/browser-entry.tsx +51 -0
  89. package/src/ui/chrome.css +485 -0
  90. package/src/ui/design-system/README.md +88 -0
  91. package/src/ui/design-system/components/controls/Button.case.tsx +52 -0
  92. package/src/ui/design-system/components/controls/Button.css +89 -0
  93. package/src/ui/design-system/components/controls/Button.placard.md +14 -0
  94. package/src/ui/design-system/components/controls/Button.test.tsx +45 -0
  95. package/src/ui/design-system/components/controls/Button.tsx +41 -0
  96. package/src/ui/design-system/components/controls/IconButton.case.tsx +52 -0
  97. package/src/ui/design-system/components/controls/IconButton.css +67 -0
  98. package/src/ui/design-system/components/controls/IconButton.placard.md +13 -0
  99. package/src/ui/design-system/components/controls/IconButton.test.tsx +39 -0
  100. package/src/ui/design-system/components/controls/IconButton.tsx +47 -0
  101. package/src/ui/design-system/components/controls/Input.case.tsx +50 -0
  102. package/src/ui/design-system/components/controls/Input.css +52 -0
  103. package/src/ui/design-system/components/controls/Input.placard.md +12 -0
  104. package/src/ui/design-system/components/controls/Input.test.tsx +43 -0
  105. package/src/ui/design-system/components/controls/Input.tsx +45 -0
  106. package/src/ui/design-system/components/controls/Select.case.tsx +48 -0
  107. package/src/ui/design-system/components/controls/Select.css +44 -0
  108. package/src/ui/design-system/components/controls/Select.placard.md +15 -0
  109. package/src/ui/design-system/components/controls/Select.test.tsx +57 -0
  110. package/src/ui/design-system/components/controls/Select.tsx +58 -0
  111. package/src/ui/design-system/components/controls/SelectMenu.case.tsx +100 -0
  112. package/src/ui/design-system/components/controls/SelectMenu.css +72 -0
  113. package/src/ui/design-system/components/controls/SelectMenu.placard.md +18 -0
  114. package/src/ui/design-system/components/controls/SelectMenu.test.tsx +66 -0
  115. package/src/ui/design-system/components/controls/SelectMenu.tsx +377 -0
  116. package/src/ui/design-system/components/index.ts +66 -0
  117. package/src/ui/design-system/components/primer-specimen/ColorRamp.case.tsx +44 -0
  118. package/src/ui/design-system/components/primer-specimen/ColorRamp.placard.md +15 -0
  119. package/src/ui/design-system/components/primer-specimen/ColorRamp.tsx +51 -0
  120. package/src/ui/design-system/components/primer-specimen/DefinitionList.case.tsx +38 -0
  121. package/src/ui/design-system/components/primer-specimen/DefinitionList.placard.md +15 -0
  122. package/src/ui/design-system/components/primer-specimen/DefinitionList.tsx +41 -0
  123. package/src/ui/design-system/components/primer-specimen/FontFamilies.case.tsx +24 -0
  124. package/src/ui/design-system/components/primer-specimen/FontFamilies.placard.md +12 -0
  125. package/src/ui/design-system/components/primer-specimen/FontFamilies.tsx +41 -0
  126. package/src/ui/design-system/components/primer-specimen/GlyphGrid.case.tsx +27 -0
  127. package/src/ui/design-system/components/primer-specimen/GlyphGrid.placard.md +13 -0
  128. package/src/ui/design-system/components/primer-specimen/GlyphGrid.tsx +34 -0
  129. package/src/ui/design-system/components/primer-specimen/LayoutMock.case.tsx +36 -0
  130. package/src/ui/design-system/components/primer-specimen/LayoutMock.placard.md +7 -0
  131. package/src/ui/design-system/components/primer-specimen/LayoutMock.tsx +36 -0
  132. package/src/ui/design-system/components/primer-specimen/SpacingScale.case.tsx +20 -0
  133. package/src/ui/design-system/components/primer-specimen/SpacingScale.placard.md +12 -0
  134. package/src/ui/design-system/components/primer-specimen/SpacingScale.tsx +33 -0
  135. package/src/ui/design-system/components/primer-specimen/SpecimenBoxRow.case.tsx +56 -0
  136. package/src/ui/design-system/components/primer-specimen/SpecimenBoxRow.placard.md +17 -0
  137. package/src/ui/design-system/components/primer-specimen/SpecimenBoxRow.tsx +45 -0
  138. package/src/ui/design-system/components/primer-specimen/StatusList.case.tsx +17 -0
  139. package/src/ui/design-system/components/primer-specimen/StatusList.placard.md +16 -0
  140. package/src/ui/design-system/components/primer-specimen/StatusList.tsx +39 -0
  141. package/src/ui/design-system/components/primer-specimen/SwatchGrid.case.tsx +26 -0
  142. package/src/ui/design-system/components/primer-specimen/SwatchGrid.placard.md +15 -0
  143. package/src/ui/design-system/components/primer-specimen/SwatchGrid.tsx +42 -0
  144. package/src/ui/design-system/components/primer-specimen/TypeScale.case.tsx +23 -0
  145. package/src/ui/design-system/components/primer-specimen/TypeScale.placard.md +14 -0
  146. package/src/ui/design-system/components/primer-specimen/TypeScale.tsx +34 -0
  147. package/src/ui/design-system/components/primer-specimen/WeightSpecimen.case.tsx +28 -0
  148. package/src/ui/design-system/components/primer-specimen/WeightSpecimen.placard.md +15 -0
  149. package/src/ui/design-system/components/primer-specimen/WeightSpecimen.tsx +46 -0
  150. package/src/ui/design-system/components/primer-specimen/index.ts +31 -0
  151. package/src/ui/design-system/components/primer-specimen/styles.css +476 -0
  152. package/src/ui/design-system/components/shell/A11yPage.case.tsx +237 -0
  153. package/src/ui/design-system/components/shell/A11yPage.placard.md +15 -0
  154. package/src/ui/design-system/components/shell/CaseTemplate.case.tsx +32 -0
  155. package/src/ui/design-system/components/shell/CaseTemplate.placard.md +5 -0
  156. package/src/ui/design-system/components/shell/CasesPage.case.tsx +141 -0
  157. package/src/ui/design-system/components/shell/CasesPage.placard.md +12 -0
  158. package/src/ui/design-system/components/shell/PrimerPage.case.tsx +22 -0
  159. package/src/ui/design-system/components/shell/PrimerPage.placard.md +3 -0
  160. package/src/ui/design-system/components/shell/PrimerTemplate.case.tsx +22 -0
  161. package/src/ui/design-system/components/shell/PrimerTemplate.placard.md +5 -0
  162. package/src/ui/design-system/components/shell/ShellView.case.tsx +57 -0
  163. package/src/ui/design-system/components/shell/ShellView.placard.md +5 -0
  164. package/src/ui/design-system/components/shell/ShellView.tsx +678 -0
  165. package/src/ui/design-system/components/shell/shell-fixtures.tsx +727 -0
  166. package/src/ui/design-system/components/showcase/A11yBadge.case.tsx +46 -0
  167. package/src/ui/design-system/components/showcase/A11yBadge.css +27 -0
  168. package/src/ui/design-system/components/showcase/A11yBadge.placard.md +11 -0
  169. package/src/ui/design-system/components/showcase/A11yBadge.test.tsx +31 -0
  170. package/src/ui/design-system/components/showcase/A11yBadge.tsx +41 -0
  171. package/src/ui/design-system/components/showcase/A11yPanel.case.tsx +121 -0
  172. package/src/ui/design-system/components/showcase/A11yPanel.css +198 -0
  173. package/src/ui/design-system/components/showcase/A11yPanel.placard.md +19 -0
  174. package/src/ui/design-system/components/showcase/A11yPanel.test.tsx +81 -0
  175. package/src/ui/design-system/components/showcase/A11yPanel.tsx +144 -0
  176. package/src/ui/design-system/components/showcase/Chip.case.tsx +48 -0
  177. package/src/ui/design-system/components/showcase/Chip.css +51 -0
  178. package/src/ui/design-system/components/showcase/Chip.placard.md +13 -0
  179. package/src/ui/design-system/components/showcase/Chip.test.tsx +46 -0
  180. package/src/ui/design-system/components/showcase/Chip.tsx +54 -0
  181. package/src/ui/design-system/components/showcase/Eyebrow.case.tsx +30 -0
  182. package/src/ui/design-system/components/showcase/Eyebrow.css +16 -0
  183. package/src/ui/design-system/components/showcase/Eyebrow.placard.md +10 -0
  184. package/src/ui/design-system/components/showcase/Eyebrow.test.tsx +38 -0
  185. package/src/ui/design-system/components/showcase/Eyebrow.tsx +29 -0
  186. package/src/ui/design-system/components/showcase/FlowNav.case.tsx +35 -0
  187. package/src/ui/design-system/components/showcase/FlowNav.css +29 -0
  188. package/src/ui/design-system/components/showcase/FlowNav.placard.md +13 -0
  189. package/src/ui/design-system/components/showcase/FlowNav.test.tsx +48 -0
  190. package/src/ui/design-system/components/showcase/FlowNav.tsx +58 -0
  191. package/src/ui/design-system/components/showcase/ImpactTag.case.tsx +19 -0
  192. package/src/ui/design-system/components/showcase/ImpactTag.css +36 -0
  193. package/src/ui/design-system/components/showcase/ImpactTag.placard.md +14 -0
  194. package/src/ui/design-system/components/showcase/ImpactTag.test.tsx +40 -0
  195. package/src/ui/design-system/components/showcase/ImpactTag.tsx +35 -0
  196. package/src/ui/design-system/components/showcase/NavItem.case.tsx +86 -0
  197. package/src/ui/design-system/components/showcase/NavItem.css +111 -0
  198. package/src/ui/design-system/components/showcase/NavItem.placard.md +13 -0
  199. package/src/ui/design-system/components/showcase/NavItem.test.tsx +65 -0
  200. package/src/ui/design-system/components/showcase/NavItem.tsx +95 -0
  201. package/src/ui/design-system/components/showcase/RenderAddress.case.tsx +21 -0
  202. package/src/ui/design-system/components/showcase/RenderAddress.css +35 -0
  203. package/src/ui/design-system/components/showcase/RenderAddress.placard.md +7 -0
  204. package/src/ui/design-system/components/showcase/RenderAddress.test.tsx +26 -0
  205. package/src/ui/design-system/components/showcase/RenderAddress.tsx +43 -0
  206. package/src/ui/design-system/components/showcase/SegmentedToggle.case.tsx +84 -0
  207. package/src/ui/design-system/components/showcase/SegmentedToggle.css +61 -0
  208. package/src/ui/design-system/components/showcase/SegmentedToggle.placard.md +21 -0
  209. package/src/ui/design-system/components/showcase/SegmentedToggle.test.tsx +81 -0
  210. package/src/ui/design-system/components/showcase/SegmentedToggle.tsx +75 -0
  211. package/src/ui/design-system/components/showcase/Sidebar.case.tsx +67 -0
  212. package/src/ui/design-system/components/showcase/Sidebar.css +6 -0
  213. package/src/ui/design-system/components/showcase/Sidebar.placard.md +14 -0
  214. package/src/ui/design-system/components/showcase/Sidebar.test.tsx +32 -0
  215. package/src/ui/design-system/components/showcase/Sidebar.tsx +30 -0
  216. package/src/ui/design-system/components/showcase/Stage.case.tsx +51 -0
  217. package/src/ui/design-system/components/showcase/Stage.css +91 -0
  218. package/src/ui/design-system/components/showcase/Stage.placard.md +15 -0
  219. package/src/ui/design-system/components/showcase/Stage.test.tsx +84 -0
  220. package/src/ui/design-system/components/showcase/Stage.tsx +97 -0
  221. package/src/ui/design-system/components/showcase/TweaksPanel.case.tsx +81 -0
  222. package/src/ui/design-system/components/showcase/TweaksPanel.css +169 -0
  223. package/src/ui/design-system/components/showcase/TweaksPanel.placard.md +20 -0
  224. package/src/ui/design-system/components/showcase/TweaksPanel.tsx +230 -0
  225. package/src/ui/design-system/components/showcase/Wordmark.case.tsx +42 -0
  226. package/src/ui/design-system/components/showcase/Wordmark.css +31 -0
  227. package/src/ui/design-system/components/showcase/Wordmark.placard.md +10 -0
  228. package/src/ui/design-system/components/showcase/Wordmark.test.tsx +22 -0
  229. package/src/ui/design-system/components/showcase/Wordmark.tsx +22 -0
  230. package/src/ui/design-system/primer-specimens/brand.tsx +26 -0
  231. package/src/ui/design-system/primer-specimens/colors.tsx +83 -0
  232. package/src/ui/design-system/primer-specimens/components.tsx +308 -0
  233. package/src/ui/design-system/primer-specimens/foundations.tsx +71 -0
  234. package/src/ui/design-system/primer-specimens/index.ts +25 -0
  235. package/src/ui/design-system/primer-specimens/showcase.tsx +68 -0
  236. package/src/ui/design-system/primer-specimens/spacing.tsx +101 -0
  237. package/src/ui/design-system/primer-specimens/type.tsx +75 -0
  238. package/src/ui/design-system/primer.mdx +236 -0
  239. package/src/ui/design-system/styles.css +14 -0
  240. package/src/ui/design-system/tokens/colors.css +172 -0
  241. package/src/ui/design-system/tokens/fonts.css +18 -0
  242. package/src/ui/design-system/tokens/spacing.css +48 -0
  243. package/src/ui/design-system/tokens/typography.css +49 -0
  244. package/src/ui/markdown.test.tsx +54 -0
  245. package/src/ui/markdown.tsx +19 -0
  246. package/src/ui/primer-mount.tsx +76 -0
  247. package/src/ui/primer.css +175 -0
  248. package/src/ui/primer.tsx +277 -0
  249. package/src/ui/render-mount.tsx +284 -0
  250. package/src/ui/shell-core.test.ts +340 -0
  251. package/src/ui/shell-core.ts +295 -0
  252. package/src/ui/shell.tsx +60 -0
  253. package/src/ui/test-ids.ts +53 -0
  254. package/src/ui/use-shell.ts +1230 -0
@@ -0,0 +1,237 @@
1
+ import { defineCases } from '@awarebydefault/display-case'
2
+ import { useState } from 'react'
3
+ import type { A11yViolation } from '../../../../index'
4
+ import { Button, Input, RenderAddress } from '..'
5
+ import { ShellView } from './ShellView'
6
+ import {
7
+ makeModel,
8
+ mockA11y,
9
+ mockA11yClean,
10
+ mockA11yLeaf,
11
+ mockA11yPending,
12
+ mockA11yPerVariant,
13
+ mockA11yScrolling,
14
+ mockManifest,
15
+ PLACEHOLDER_DOC,
16
+ StageSlot,
17
+ selectIn,
18
+ } from './shell-fixtures'
19
+
20
+ // The resolved audit the "Re-scan" exhibit returns to after its simulated scan.
21
+ const RESCAN_RESULT = mockA11y()
22
+
23
+ /**
24
+ * Interactive "re-scan" exhibit: the panel's ⟳ control forces a fresh audit. We
25
+ * simulate the live cycle locally — clicking re-scan flips the verdict to the
26
+ * pulsing "Scanning…" state, then resolves back to the violations after a beat —
27
+ * exactly what `useShell.rescanA11y` does against the real scanner.
28
+ */
29
+ function RescanDemo() {
30
+ const [current, setCurrent] = useState<
31
+ A11yViolation[] | 'pending' | 'unavailable'
32
+ >(RESCAN_RESULT.current)
33
+ // Initial render = already-scanned → fade in at once; a re-scan resolves from
34
+ // "Scanning…" → cascade (mirrors useShell driving `reveal` off the scan).
35
+ const [reveal, setReveal] = useState<'cascade' | 'all'>('all')
36
+ const rescan = () => {
37
+ setReveal('cascade')
38
+ setCurrent('pending')
39
+ setTimeout(() => setCurrent(RESCAN_RESULT.current), 1200)
40
+ }
41
+ return (
42
+ <ShellView
43
+ {...makeModel({
44
+ ...selectIn(mockManifest, 'input', 'default'),
45
+ a11y: { byVariant: RESCAN_RESULT.byVariant, current, reveal },
46
+ rescanA11y: rescan,
47
+ boxW: 260,
48
+ boxH: 96,
49
+ })}
50
+ renderFrame={
51
+ <StageSlot>
52
+ <Input placeholder="Email address" aria-label="Email address" />
53
+ </StageSlot>
54
+ }
55
+ primerFrame={null}
56
+ />
57
+ )
58
+ }
59
+
60
+ /**
61
+ * A real page proving where accessibility violations surface in the browse
62
+ * chrome — the proposal made concrete. Two complementary surfaces:
63
+ *
64
+ * - **Discoverable** — danger markers on the nav rail. Violations belong to a
65
+ * *variant*, so a collapsed component shows the sum across its variants;
66
+ * expanded, the per-variant counts move onto the case rows and the parent
67
+ * shows a plain dot (see the "Per-variant breakdown" case).
68
+ * - **Visible** — the Accessibility panel under the stage, listing the selected
69
+ * variant's violations (rule id, help text, node count) instead of leaving
70
+ * them buried in the `display-case check` CLI log. Its header carries a
71
+ * show/hide toggle and stays pinned while the list scrolls; it sits below the
72
+ * Tweaks panel (the audit is the consequence of the tweaked state).
73
+ *
74
+ * Wiring `useShell` to feed live audit results into this same `a11y` field is the
75
+ * follow-up; the chrome that renders them is what this page proves.
76
+ */
77
+ export default defineCases(
78
+ 'A11y page',
79
+ {
80
+ Default: () => (
81
+ <ShellView
82
+ {...makeModel({
83
+ ...selectIn(mockManifest, 'input', 'default'),
84
+ a11y: mockA11y(),
85
+ boxW: 260,
86
+ boxH: 96,
87
+ })}
88
+ renderFrame={
89
+ <StageSlot>
90
+ <Input placeholder="Email address" aria-label="Email address" />
91
+ </StageSlot>
92
+ }
93
+ primerFrame={null}
94
+ />
95
+ ),
96
+ // The panel's ⟳ re-scan control — click it to force a fresh audit (flips to
97
+ // "Scanning…", then resolves). Mirrors useShell.rescanA11y in the live app.
98
+ 'Re-scan': () => <RescanDemo />,
99
+ // A11y configured, but the active variant's scan is still in flight: the
100
+ // panel shows its calm "Scanning…" state (neutral accent, no toggle) and no
101
+ // nav markers have landed yet.
102
+ Scanning: () => (
103
+ <ShellView
104
+ {...makeModel({
105
+ ...selectIn(mockManifest, 'input', 'default'),
106
+ a11y: mockA11yPending(),
107
+ boxW: 260,
108
+ boxH: 96,
109
+ })}
110
+ renderFrame={
111
+ <StageSlot>
112
+ <Input placeholder="Email address" aria-label="Email address" />
113
+ </StageSlot>
114
+ }
115
+ primerFrame={null}
116
+ />
117
+ ),
118
+ // A11y configured and everything is clean: no nav markers, and the panel
119
+ // shows its reassuring all-green pass state.
120
+ 'All clear': () => (
121
+ <ShellView
122
+ {...makeModel({
123
+ ...selectIn(mockManifest, 'input', 'default'),
124
+ a11y: mockA11yClean(),
125
+ boxW: 260,
126
+ boxH: 96,
127
+ })}
128
+ renderFrame={
129
+ <StageSlot>
130
+ <Input placeholder="Email address" aria-label="Email address" />
131
+ </StageSlot>
132
+ }
133
+ primerFrame={null}
134
+ />
135
+ ),
136
+ // A11y NOT configured (no `a11y` on the model): no nav markers and no panel
137
+ // at all — the chrome is exactly as it was before the feature.
138
+ 'Not configured': () => (
139
+ <ShellView
140
+ {...makeModel({
141
+ ...selectIn(mockManifest, 'input', 'default'),
142
+ boxW: 260,
143
+ boxH: 96,
144
+ })}
145
+ renderFrame={
146
+ <StageSlot>
147
+ <Input placeholder="Email address" aria-label="Email address" />
148
+ </StageSlot>
149
+ }
150
+ primerFrame={null}
151
+ />
152
+ ),
153
+ // A selected single-case leaf: RenderAddress has one variant, so it renders
154
+ // as a leaf (no chevron, no case rows). With no children to defer to, its
155
+ // lone variant's count sits directly on the (selected, marigold) leaf row —
156
+ // never a dot. The Accessibility panel lists that variant's violations.
157
+ 'Single-case leaf': () => (
158
+ <ShellView
159
+ {...makeModel({
160
+ ...selectIn(mockManifest, 'render-address', 'default'),
161
+ a11y: mockA11yLeaf(),
162
+ boxW: 360,
163
+ boxH: 64,
164
+ })}
165
+ renderFrame={
166
+ <StageSlot>
167
+ <RenderAddress url="https://display-case.dev/render/render-address/default?theme=light" />
168
+ </StageSlot>
169
+ }
170
+ primerFrame={null}
171
+ />
172
+ ),
173
+ // The per-variant nav breakdown: `button` is expanded, so its parent row
174
+ // shows a plain dot while its three variants carry their own counts
175
+ // (Playground 2, Variants 5, Sizes clean). The other components stay
176
+ // collapsed, showing their summed counts — the contrast the rail draws.
177
+ 'Per-variant breakdown': () => (
178
+ <ShellView
179
+ {...makeModel({
180
+ ...selectIn(mockManifest, 'button', 'variants'),
181
+ a11y: mockA11yPerVariant(),
182
+ boxW: 280,
183
+ boxH: 96,
184
+ })}
185
+ renderFrame={
186
+ <StageSlot>
187
+ <Button variant="ghost">Low-contrast label</Button>
188
+ </StageSlot>
189
+ }
190
+ primerFrame={null}
191
+ />
192
+ ),
193
+ // A case with more violations than the panel's height cap, so the list
194
+ // scrolls internally while the "ACCESSIBILITY" header stays pinned. Use the
195
+ // header's toggle to collapse the (long) list.
196
+ Scrolling: () => (
197
+ <ShellView
198
+ {...makeModel({
199
+ ...selectIn(mockManifest, 'input', 'default'),
200
+ a11y: mockA11yScrolling(),
201
+ boxW: 260,
202
+ boxH: 96,
203
+ })}
204
+ renderFrame={
205
+ <StageSlot>
206
+ <Input placeholder="Email address" aria-label="Email address" />
207
+ </StageSlot>
208
+ }
209
+ primerFrame={null}
210
+ />
211
+ ),
212
+ // Everything open at once — stage + tweaks panel + a11y panel + docs panel —
213
+ // to see how the surfaces coexist on a crowded page. The Button atom (which
214
+ // has a placard-doc and a tweakable Playground) is selected, so the chosen nav
215
+ // row genuinely carries violations. The docked tweaks panel can be collapsed
216
+ // (its header chevron) to give the content column back to the stage.
217
+ 'With tweaks and docs': () => (
218
+ <ShellView
219
+ {...makeModel({
220
+ ...selectIn(mockManifest, 'button', 'playground'),
221
+ a11y: mockA11y(),
222
+ docOpen: true,
223
+ docText: PLACEHOLDER_DOC,
224
+ boxW: 240,
225
+ boxH: 120,
226
+ })}
227
+ renderFrame={
228
+ <StageSlot>
229
+ <Button>Save changes</Button>
230
+ </StageSlot>
231
+ }
232
+ primerFrame={null}
233
+ />
234
+ ),
235
+ },
236
+ { level: 'page' },
237
+ )
@@ -0,0 +1,15 @@
1
+ **A11y page** — the Cases chrome with accessibility surfacing on: the page that proves where a11y results appear — per-variant markers in the nav rail and the Accessibility panel below the stage.
2
+
3
+ Behaviour, by case — each is the live [A11yPanel](../showcase/A11yPanel.placard.md) and [A11yBadge](../showcase/A11yBadge.placard.md) fed a static model, so it shows one state of the surface:
4
+
5
+ - **Default** — a violations verdict: the panel lists the findings impact-sorted (worst first), nav rows carry counts.
6
+ - **Scanning** — a scan in flight: the pulsing "Scanning…" bar, no markers yet.
7
+ - **All clear** — a clean pass: the green bar, no nav markers anywhere.
8
+ - **Not configured** — a11y omitted from the model: no panel and no markers at all (the chrome exactly as before the feature).
9
+ - **Single-case leaf** — a one-variant component shows its count directly on the leaf row (never a dot).
10
+ - **Per-variant breakdown** — an expanded component shows a plain dot while its case rows carry the per-variant counts; collapsed siblings show their summed count.
11
+ - **Scrolling** — a long violation list scrolls inside the height-capped panel, under the sticky header.
12
+ - **Re-scan** — the panel's ⟳ control forces a fresh audit: flips to "Scanning…", then resolves (mirrors the live `rescanA11y`).
13
+ - **With tweaks and docs** — the panel coexisting with the Tweaks and Docs panels on a crowded page.
14
+
15
+ For how the live server feeds these states (on-demand scan, cache, SSE), see the package's Configuration guide (the `a11y` option) and the `display-case-live-a11y` change.
@@ -0,0 +1,32 @@
1
+ import { defineCases } from '@awarebydefault/display-case'
2
+ import { ShellView } from './ShellView'
3
+ import {
4
+ caseTemplateSelection,
5
+ makeModel,
6
+ PlaceholderExhibit,
7
+ } from './shell-fixtures'
8
+
9
+ /**
10
+ * The Cases layout as a *template*: the chrome's header, nav rail, stage, tweaks
11
+ * panel, and docs panel arranged around placeholder content. It shows the shape
12
+ * a case page takes before any real component, tweak, or doc fills it — the
13
+ * empty template a {@link defineCases} page is poured into.
14
+ */
15
+ export default defineCases(
16
+ 'Case template',
17
+ {
18
+ Default: () => (
19
+ <ShellView
20
+ {...makeModel({
21
+ ...caseTemplateSelection(),
22
+ docText: '_Placeholder documentation lives here._',
23
+ boxW: 260,
24
+ boxH: 150,
25
+ })}
26
+ renderFrame={<PlaceholderExhibit />}
27
+ primerFrame={null}
28
+ />
29
+ ),
30
+ },
31
+ { level: 'template' },
32
+ )
@@ -0,0 +1,5 @@
1
+ **Case template** — the Cases (library) layout with no real data: the empty shape every `defineCases` page is poured into. Reach for it to see the chrome's regions before any component fills them.
2
+
3
+ Regions: **header** (wordmark · device/zoom/grid controls · theme toggle) · **nav rail** (the component tree, grouped by hierarchy level) · **stage** (the centred exhibit, with its shareable `/render` address above) · **Tweaks panel** (the case's live controls, docked under the stage) · **Docs panel** (the selected component's `.placard.md`, on the right when open).
4
+
5
+ Use this to read the library layout itself. For the reading-mode layout instead, reach for [Primer template](./PrimerTemplate.placard.md). Filled with a live component, a tweak, and prose, it's exhibited in the [Cases page](./CasesPage.placard.md) (its "With tweaks and docs" variant).
@@ -0,0 +1,141 @@
1
+ import { defineCases } from '@awarebydefault/display-case'
2
+ import { Button } from '..'
3
+ import { ShellView } from './ShellView'
4
+ import {
5
+ FlowStep,
6
+ makeModel,
7
+ mockManifest,
8
+ PageScreen,
9
+ PLACEHOLDER_DOC,
10
+ StageSlot,
11
+ selectIn,
12
+ } from './shell-fixtures'
13
+
14
+ /**
15
+ * A real page: the Cases chrome (the library view) browsing the mock manifest,
16
+ * with a live exhibit on the stage. The variants pour the same page full to
17
+ * different depths and show how the stage adapts to what it's browsing:
18
+ *
19
+ * - **Default / With tweaks / With docs / With tweaks and docs** — browsing the
20
+ * Button atom; the tweaks panel rides alongside when the case carries a
21
+ * schema, the docs panel opens when the component has a placard-doc.
22
+ * - **Page** — browsing a page-level component, where the stage drops its grid
23
+ * and padding to let the screen fill edge to edge.
24
+ * - **Flow** — browsing a flow, where the FlowNav stepper appears above the
25
+ * stage and it fills edge to edge.
26
+ *
27
+ * The Primer reading view is its own page — see Primer page.
28
+ */
29
+
30
+ // The Variants case content — the stage for the bare/docs exhibits, which select
31
+ // the schema-less "Variants" case.
32
+ const variantsExhibit = (
33
+ <StageSlot>
34
+ <div style={{ display: 'flex', gap: '0.5rem' }}>
35
+ <Button>Save changes</Button>
36
+ <Button variant="accent">Publish</Button>
37
+ <Button variant="ghost">Cancel</Button>
38
+ </div>
39
+ </StageSlot>
40
+ )
41
+
42
+ // The Playground case's stage at its default tweak values (variant 'ghost', size
43
+ // 'md', label 'Button') — the single button the tweaks panel's controls drive.
44
+ // The exhibits that select "Playground" put this on the stage, so the controls
45
+ // and the staged button agree.
46
+ const playgroundExhibit = (
47
+ <StageSlot>
48
+ <Button>Button</Button>
49
+ </StageSlot>
50
+ )
51
+
52
+ export default defineCases(
53
+ 'Cases page',
54
+ {
55
+ // The bare stage: the Variants case has no tweak schema and docs stay closed.
56
+ Default: () => (
57
+ <ShellView
58
+ {...makeModel({
59
+ ...selectIn(mockManifest, 'button', 'variants'),
60
+ boxW: 280,
61
+ boxH: 120,
62
+ })}
63
+ renderFrame={variantsExhibit}
64
+ primerFrame={null}
65
+ />
66
+ ),
67
+ // Tweaks revealed: the Playground case carries a tweak schema, so the docked
68
+ // TweaksPanel rides alongside the stage — its controls at their defaults,
69
+ // driving the Playground button on the stage.
70
+ 'With tweaks': () => (
71
+ <ShellView
72
+ {...makeModel({
73
+ ...selectIn(mockManifest, 'button', 'playground'),
74
+ boxW: 280,
75
+ boxH: 120,
76
+ })}
77
+ renderFrame={playgroundExhibit}
78
+ primerFrame={null}
79
+ />
80
+ ),
81
+ // Documentation revealed: the Button component has a placard-doc, so opening
82
+ // the docs panel pours real prose into the aside.
83
+ 'With docs': () => (
84
+ <ShellView
85
+ {...makeModel({
86
+ ...selectIn(mockManifest, 'button', 'variants'),
87
+ docOpen: true,
88
+ docText: PLACEHOLDER_DOC,
89
+ boxW: 280,
90
+ boxH: 120,
91
+ })}
92
+ renderFrame={variantsExhibit}
93
+ primerFrame={null}
94
+ />
95
+ ),
96
+ // The page at its fullest: the Playground case's tweaks panel and the open
97
+ // docs panel flank the Playground button on the stage.
98
+ 'With tweaks and docs': () => (
99
+ <ShellView
100
+ {...makeModel({
101
+ ...selectIn(mockManifest, 'button', 'playground'),
102
+ docOpen: true,
103
+ docText: PLACEHOLDER_DOC,
104
+ boxW: 280,
105
+ boxH: 120,
106
+ })}
107
+ renderFrame={playgroundExhibit}
108
+ primerFrame={null}
109
+ />
110
+ ),
111
+ // Browsing a page: a page-level component flips `stageDecor` off, so the
112
+ // stage drops its grid, corner ticks, and padding (and the header's Grid
113
+ // button), and `fillFrame` lets the screen fill the whole stage edge to edge
114
+ // rather than sitting in a centred box.
115
+ Page: () => (
116
+ <ShellView
117
+ {...makeModel({
118
+ ...selectIn(mockManifest, 'cases-page', 'default'),
119
+ stageDecor: false,
120
+ })}
121
+ fillFrame
122
+ renderFrame={<PageScreen />}
123
+ primerFrame={null}
124
+ />
125
+ ),
126
+ // Browsing a flow: a flow component shows the FlowNav stepper above the stage
127
+ // (one tab per step) and, like a page, fills the whole stage edge to edge.
128
+ Flow: () => (
129
+ <ShellView
130
+ {...makeModel({
131
+ ...selectIn(mockManifest, 'sign-in', 'request-link'),
132
+ stageDecor: false,
133
+ })}
134
+ fillFrame
135
+ renderFrame={<FlowStep />}
136
+ primerFrame={null}
137
+ />
138
+ ),
139
+ },
140
+ { level: 'page' },
141
+ )
@@ -0,0 +1,12 @@
1
+ **Cases page** — the Cases (library) chrome browsing the mock manifest: the [Case template](./CaseTemplate.placard.md) poured full, with a live exhibit on the stage. The consolidated dogfood of everything the library view does.
2
+
3
+ Behaviour, by case — each shows how the stage adapts to *what it's browsing*:
4
+
5
+ - **Default** — browsing a schema-less case (Button → Variants): bare stage, no tweaks or docs panel.
6
+ - **With tweaks** — browsing a case that carries a tweak schema (Button → Playground): the docked Tweaks panel rides alongside, its controls at their defaults driving the staged button.
7
+ - **With docs** — the component has a placard-doc, so the Docs panel opens with real prose.
8
+ - **With tweaks and docs** — the fullest case: Tweaks panel and open Docs panel flanking the stage.
9
+ - **Page** — browsing a page-level component: the stage drops its grid, corner ticks, and padding (and the header's Grid button), and fills edge-to-edge.
10
+ - **Flow** — browsing a flow: the FlowNav stepper appears above the stage (one tab per step) and, like a page, fills edge-to-edge.
11
+
12
+ A static snapshot per variant (the nav/controls don't route here). The reading view is its own page — see [Primer page](./PrimerPage.placard.md).
@@ -0,0 +1,22 @@
1
+ import { defineCases } from '@awarebydefault/display-case'
2
+ import { ShellView } from './ShellView'
3
+ import { makeModel, RealPrimer } from './shell-fixtures'
4
+
5
+ /**
6
+ * The Primer *page*: the Primer template filled with the real reading page —
7
+ * actual prose and live {@link Display} specimens rendered into the host. This
8
+ * is what the Primer template becomes once a consumer authors its `.mdx`.
9
+ */
10
+ export default defineCases(
11
+ 'Primer page',
12
+ {
13
+ Default: () => (
14
+ <ShellView
15
+ {...makeModel({ mode: 'primer', shownMode: 'primer' })}
16
+ renderFrame={null}
17
+ primerFrame={<RealPrimer />}
18
+ />
19
+ ),
20
+ },
21
+ { level: 'page' },
22
+ )
@@ -0,0 +1,3 @@
1
+ **Primer page** — the [Primer template](./PrimerTemplate.placard.md) filled with the real reading page: actual prose and live `Display` specimens in the reading host. What the template becomes once a consumer authors its `.mdx`.
2
+
3
+ Behaviour: the chrome is in Primer (reading) mode — the table-of-contents nav lists the page's sections and the host renders the wall text with specimens embedded inline. The mode switch flips to the library; walking that change is the [Primer to Cases](./ShellView.placard.md) flow.
@@ -0,0 +1,22 @@
1
+ import { defineCases } from '@awarebydefault/display-case'
2
+ import { ShellView } from './ShellView'
3
+ import { makeModel, PlaceholderPrimer } from './shell-fixtures'
4
+
5
+ /**
6
+ * The Primer layout as a *template*: the chrome in reading mode — the mode
7
+ * switch, the table-of-contents nav, and the reading host — wrapped around a
8
+ * skeleton standing in for the long-form wall text and its specimens.
9
+ */
10
+ export default defineCases(
11
+ 'Primer template',
12
+ {
13
+ Default: () => (
14
+ <ShellView
15
+ {...makeModel({ mode: 'primer', shownMode: 'primer' })}
16
+ renderFrame={null}
17
+ primerFrame={<PlaceholderPrimer />}
18
+ />
19
+ ),
20
+ },
21
+ { level: 'template' },
22
+ )
@@ -0,0 +1,5 @@
1
+ **Primer template** — the chrome in reading mode with no real data: the layout a Primer `.mdx` pours into. Reach for it to see the reading-mode regions before the wall text fills them.
2
+
3
+ Regions: the **Primer / Cases mode switch** (top of the sidebar) · the **table-of-contents nav** (the page's sections, one accordion group open at a time) · the **reading host** (long-form prose with inline live specimens). No stage, Tweaks, or Docs panel — those are Cases-mode only.
4
+
5
+ Use this to read the reading-mode layout. For the library layout instead, reach for [Case template](./CaseTemplate.placard.md). Filled with real prose and specimens it becomes the [Primer page](./PrimerPage.placard.md).
@@ -0,0 +1,57 @@
1
+ import { defineFlow } from '@awarebydefault/display-case'
2
+ import { Button } from '..'
3
+ import { ShellView } from './ShellView'
4
+ import { makeModel, RealPrimer, StageSlot } from './shell-fixtures'
5
+
6
+ /**
7
+ * The headline dogfood: Display Case's own Primer ↔ Cases view change, exhibited
8
+ * as a flow. Each step is the pure {@link ShellView} fed a static model — the
9
+ * Primer step shows the reading page, the Cases step shows the library — and the
10
+ * sidebar's mode switch is wired to the flow's `goto`, so clicking it walks the
11
+ * flow exactly as it walks the live chrome.
12
+ */
13
+ export default defineFlow('Primer to Cases', {
14
+ steps: {
15
+ 'Primer view': {
16
+ transitions: ['Cases view'],
17
+ render: ({ goto }) => (
18
+ <ShellView
19
+ {...makeModel({
20
+ mode: 'primer',
21
+ shownMode: 'primer',
22
+ setMode: (m) => {
23
+ if (m === 'library') goto('Cases view')
24
+ },
25
+ })}
26
+ renderFrame={null}
27
+ primerFrame={<RealPrimer />}
28
+ />
29
+ ),
30
+ },
31
+ 'Cases view': {
32
+ transitions: ['Primer view'],
33
+ render: ({ goto }) => (
34
+ <ShellView
35
+ {...makeModel({
36
+ mode: 'library',
37
+ shownMode: 'library',
38
+ boxW: 240,
39
+ boxH: 120,
40
+ setMode: (m) => {
41
+ if (m === 'primer') goto('Primer view')
42
+ },
43
+ })}
44
+ renderFrame={
45
+ <StageSlot>
46
+ <div style={{ display: 'flex', gap: '0.5rem' }}>
47
+ <Button>Save changes</Button>
48
+ <Button variant="accent">Publish</Button>
49
+ </div>
50
+ </StageSlot>
51
+ }
52
+ primerFrame={null}
53
+ />
54
+ ),
55
+ },
56
+ },
57
+ })
@@ -0,0 +1,5 @@
1
+ **Primer to Cases** — Display Case's own Primer ↔ Cases view change, walked as a flow. The headline dogfood: the same pure `ShellView` the live chrome renders, fed a static model per step.
2
+
3
+ Steps, in order: `primer-view` (reading mode — the Primer wall text with live specimens) ↔ `cases-view` (the library — a component on the stage).
4
+
5
+ Advances when: the sidebar's **Primer / Cases mode switch** is clicked — each step wires it to the flow's `goto`, so clicking it transitions to the other step exactly as the live chrome crossfades between the two views. A two-step loop with no terminal state: walk it in either direction, or deep-link to a single step to snapshot just that view.