@sableui/react 0.0.0-stage → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/AGENTS.md +157 -0
  2. package/CHANGELOG.md +55 -0
  3. package/CONTRIBUTING.md +221 -0
  4. package/DESIGN.md +548 -0
  5. package/LICENSE +21 -0
  6. package/README.md +194 -2
  7. package/THIRD_PARTY_NOTICES.md +44 -0
  8. package/bin/sable-lint.mjs +0 -0
  9. package/bin/sable.mjs +1223 -0
  10. package/dist/_contract-CYScOdf5.d.ts +150 -0
  11. package/dist/chunk-3IWZYBGH.js +398 -0
  12. package/dist/chunk-5Z5KLOAU.js +167 -0
  13. package/dist/chunk-7MG4SHYX.js +15 -0
  14. package/dist/chunk-ADLLDWLW.js +15 -0
  15. package/dist/chunk-EP55KSYA.js +14 -0
  16. package/dist/chunk-J23ELQQZ.js +9396 -0
  17. package/dist/chunk-JI7WJP2L.js +286 -0
  18. package/dist/chunk-K7RUHUGC.js +14 -0
  19. package/dist/chunk-KO3NAEBF.js +15 -0
  20. package/dist/chunk-L4IEIQQA.js +14 -0
  21. package/dist/chunk-L6Y46C62.js +270 -0
  22. package/dist/chunk-NEQNXI2G.js +25 -0
  23. package/dist/chunk-PAOZBZME.js +40 -0
  24. package/dist/chunk-RWP4XBSK.js +139 -0
  25. package/dist/chunk-SRQWQUTW.js +63 -0
  26. package/dist/chunk-YXBOYWBN.js +15 -0
  27. package/dist/foundations/index.d.ts +88 -0
  28. package/dist/foundations/index.js +792 -0
  29. package/dist/icon/index.d.ts +60 -0
  30. package/dist/icon/index.js +2 -0
  31. package/dist/icon-sets/brands.d.ts +44 -0
  32. package/dist/icon-sets/brands.js +147 -0
  33. package/dist/icon-sets/reicon.d.ts +8 -0
  34. package/dist/icon-sets/reicon.js +1 -0
  35. package/dist/index.d.ts +7013 -0
  36. package/dist/index.js +15462 -0
  37. package/dist/ios/chrome.css +83 -0
  38. package/dist/ios/frame.css +5 -0
  39. package/dist/ios/index.d.ts +70 -0
  40. package/dist/ios/index.js +313 -0
  41. package/dist/ios/preview.d.ts +64 -0
  42. package/dist/ios/preview.js +133 -0
  43. package/dist/ios/styles.css +77 -0
  44. package/dist/layout/index.d.ts +280 -0
  45. package/dist/layout/index.js +2 -0
  46. package/dist/meta-6dUzgC6M.d.ts +205 -0
  47. package/dist/patterns/index.d.ts +36 -0
  48. package/dist/patterns/index.js +934 -0
  49. package/dist/presets/index.d.ts +37 -0
  50. package/dist/presets/index.js +117 -0
  51. package/dist/registry-CyL28OzJ.d.ts +28 -0
  52. package/dist/styles.css +1893 -0
  53. package/dist/theme-provider-BWcizhAt.d.ts +105 -0
  54. package/dist/themes/atelier/atelier.css +213 -0
  55. package/dist/themes/atelier/index.d.ts +9 -0
  56. package/dist/themes/atelier/index.js +1 -0
  57. package/dist/themes/base/base.css +443 -0
  58. package/dist/themes/base/index.d.ts +9 -0
  59. package/dist/themes/base/index.js +1 -0
  60. package/dist/themes/ember/ember.css +270 -0
  61. package/dist/themes/ember/index.d.ts +9 -0
  62. package/dist/themes/ember/index.js +1 -0
  63. package/dist/themes/index.d.ts +10 -0
  64. package/dist/themes/index.js +8 -0
  65. package/dist/themes/meridian/index.d.ts +9 -0
  66. package/dist/themes/meridian/index.js +1 -0
  67. package/dist/themes/meridian/meridian.css +255 -0
  68. package/dist/themes/poppy/index.d.ts +6 -0
  69. package/dist/themes/poppy/index.js +1 -0
  70. package/dist/themes/poppy/poppy.css +174 -0
  71. package/dist/themes/prism/index.d.ts +6 -0
  72. package/dist/themes/prism/index.js +1 -0
  73. package/dist/themes/prism/prism.css +183 -0
  74. package/dist/themes/verdant/index.d.ts +9 -0
  75. package/dist/themes/verdant/index.js +1 -0
  76. package/dist/themes/verdant/verdant.css +210 -0
  77. package/dist/themes.css +30 -0
  78. package/llms/components/accordion.md +93 -0
  79. package/llms/components/app-header.md +70 -0
  80. package/llms/components/app-shell.md +117 -0
  81. package/llms/components/attachment.md +105 -0
  82. package/llms/components/avatar.md +141 -0
  83. package/llms/components/badge.md +117 -0
  84. package/llms/components/banner.md +119 -0
  85. package/llms/components/bottom-nav.md +80 -0
  86. package/llms/components/breadcrumbs.md +75 -0
  87. package/llms/components/browser.md +67 -0
  88. package/llms/components/bubble.md +119 -0
  89. package/llms/components/button.md +199 -0
  90. package/llms/components/calendar.md +75 -0
  91. package/llms/components/card.md +135 -0
  92. package/llms/components/carousel.md +87 -0
  93. package/llms/components/chat-composer.md +126 -0
  94. package/llms/components/checkbox-card.md +98 -0
  95. package/llms/components/checkbox.md +90 -0
  96. package/llms/components/code-block.md +81 -0
  97. package/llms/components/code.md +62 -0
  98. package/llms/components/collapsible.md +83 -0
  99. package/llms/components/color-field.md +100 -0
  100. package/llms/components/combobox.md +119 -0
  101. package/llms/components/command-menu.md +158 -0
  102. package/llms/components/context-card.md +73 -0
  103. package/llms/components/context-menu.md +79 -0
  104. package/llms/components/data-table.md +99 -0
  105. package/llms/components/date-picker.md +97 -0
  106. package/llms/components/description.md +96 -0
  107. package/llms/components/destructive-action-modal.md +76 -0
  108. package/llms/components/dialog.md +127 -0
  109. package/llms/components/dots-menu.md +64 -0
  110. package/llms/components/empty-state.md +113 -0
  111. package/llms/components/entity.md +67 -0
  112. package/llms/components/feedback.md +63 -0
  113. package/llms/components/fieldset.md +106 -0
  114. package/llms/components/file-dropzone.md +103 -0
  115. package/llms/components/form.md +111 -0
  116. package/llms/components/gliding-highlight.md +84 -0
  117. package/llms/components/inline-status.md +62 -0
  118. package/llms/components/input.md +127 -0
  119. package/llms/components/kbd.md +57 -0
  120. package/llms/components/label.md +73 -0
  121. package/llms/components/marker.md +99 -0
  122. package/llms/components/marquee.md +66 -0
  123. package/llms/components/menu.md +122 -0
  124. package/llms/components/message-scroller.md +110 -0
  125. package/llms/components/message.md +114 -0
  126. package/llms/components/meter.md +124 -0
  127. package/llms/components/middle-truncate.md +62 -0
  128. package/llms/components/note.md +81 -0
  129. package/llms/components/notification-badge.md +67 -0
  130. package/llms/components/number-field.md +70 -0
  131. package/llms/components/otp-field.md +101 -0
  132. package/llms/components/page-header.md +76 -0
  133. package/llms/components/page-loader.md +67 -0
  134. package/llms/components/pagination.md +92 -0
  135. package/llms/components/panel-group.md +120 -0
  136. package/llms/components/panel-section.md +122 -0
  137. package/llms/components/phone.md +70 -0
  138. package/llms/components/pill.md +73 -0
  139. package/llms/components/popover.md +79 -0
  140. package/llms/components/progress.md +98 -0
  141. package/llms/components/radio-card.md +90 -0
  142. package/llms/components/radio.md +86 -0
  143. package/llms/components/relative-time.md +60 -0
  144. package/llms/components/scroller.md +88 -0
  145. package/llms/components/scrub-field.md +97 -0
  146. package/llms/components/search-input.md +84 -0
  147. package/llms/components/select.md +106 -0
  148. package/llms/components/separator.md +70 -0
  149. package/llms/components/settings-menu.md +139 -0
  150. package/llms/components/sheet.md +97 -0
  151. package/llms/components/show-more.md +59 -0
  152. package/llms/components/side-nav.md +106 -0
  153. package/llms/components/sidebar.md +87 -0
  154. package/llms/components/skeleton.md +62 -0
  155. package/llms/components/slider.md +114 -0
  156. package/llms/components/spinner.md +87 -0
  157. package/llms/components/status-bar.md +91 -0
  158. package/llms/components/status-dot.md +70 -0
  159. package/llms/components/stepper.md +125 -0
  160. package/llms/components/streaming-text.md +86 -0
  161. package/llms/components/switch.md +87 -0
  162. package/llms/components/table.md +112 -0
  163. package/llms/components/tabs.md +84 -0
  164. package/llms/components/textarea.md +88 -0
  165. package/llms/components/theme-selector.md +95 -0
  166. package/llms/components/theme-switcher.md +71 -0
  167. package/llms/components/thinking-orb.md +91 -0
  168. package/llms/components/toast.md +130 -0
  169. package/llms/components/toggle.md +95 -0
  170. package/llms/components/toolbar.md +168 -0
  171. package/llms/components/tooltip.md +93 -0
  172. package/llms/components/tree.md +227 -0
  173. package/llms/components/video.md +66 -0
  174. package/llms/components/workspace.md +138 -0
  175. package/llms/foundations/accessibility.md +60 -0
  176. package/llms/foundations/motion.md +96 -0
  177. package/llms/foundations/scrolling.md +41 -0
  178. package/llms/foundations/shape.md +73 -0
  179. package/llms/foundations/spacing.md +82 -0
  180. package/llms/foundations/surfaces.md +69 -0
  181. package/llms/foundations/typography.md +120 -0
  182. package/llms/layout/aspect-box.md +37 -0
  183. package/llms/layout/bleed.md +31 -0
  184. package/llms/layout/center.md +37 -0
  185. package/llms/layout/columns.md +51 -0
  186. package/llms/layout/grid-overlay.md +40 -0
  187. package/llms/layout/grid.md +47 -0
  188. package/llms/layout/page.md +39 -0
  189. package/llms/layout/region.md +49 -0
  190. package/llms/layout/row.md +40 -0
  191. package/llms/layout/safe-area.md +37 -0
  192. package/llms/layout/spacer.md +39 -0
  193. package/llms/layout/split-pane.md +41 -0
  194. package/llms/layout/stack.md +39 -0
  195. package/llms/patterns/auth-page.md +68 -0
  196. package/llms/patterns/brand-landing-page.md +423 -0
  197. package/llms/patterns/chat-panel.md +210 -0
  198. package/llms/patterns/dashboard-page.md +170 -0
  199. package/llms/patterns/feed-page.md +103 -0
  200. package/llms/patterns/landing-page.md +122 -0
  201. package/llms/patterns/list-detail-page.md +100 -0
  202. package/llms/patterns/settings-page.md +121 -0
  203. package/llms/reference/token-intent.md +324 -0
  204. package/llms/reference/utilities.md +129 -0
  205. package/llms/tasks/adding-a-component.md +113 -0
  206. package/llms/tasks/auditing-an-app.md +216 -0
  207. package/llms/tasks/building-a-page.md +109 -0
  208. package/llms/tasks/building-a-tool.md +141 -0
  209. package/llms/tasks/building-an-ios-prototype.md +105 -0
  210. package/llms/tasks/building-with-sable.md +73 -0
  211. package/llms/tasks/choosing-a-component.md +109 -0
  212. package/llms/tasks/converting-an-app.md +139 -0
  213. package/llms/tasks/creating-a-preset.md +43 -0
  214. package/llms/tasks/creating-design-assets.md +96 -0
  215. package/llms/tasks/designing-a-surface.md +115 -0
  216. package/llms/tasks/developing-taste.md +157 -0
  217. package/llms/tasks/getting-started.md +63 -0
  218. package/llms/tasks/learning-from-builds.md +74 -0
  219. package/llms/tasks/reviewing-a-design.md +114 -0
  220. package/llms/tasks/reviewing-a-journey.md +84 -0
  221. package/llms/tasks/reviewing-motion.md +92 -0
  222. package/llms/tasks/using-presets.md +87 -0
  223. package/llms/taste/asset-plan.template.json +53 -0
  224. package/llms/taste/composition-follows-content.md +20 -0
  225. package/llms/taste/hierarchy-is-a-relationship.md +22 -0
  226. package/llms/taste/lessons.json +57 -0
  227. package/llms/taste/motion-needs-a-reason.md +21 -0
  228. package/llms/taste/surface-states-travel-together.md +20 -0
  229. package/llms-full.txt +14906 -0
  230. package/llms.txt +405 -0
  231. package/package.json +185 -3
  232. package/registry.json +18812 -0
  233. package/scripts/agent-setup.mjs +54 -0
  234. package/scripts/design-atlas.mjs +221 -0
  235. package/scripts/design-directions.mjs +123 -0
  236. package/scripts/design-memory.mjs +166 -0
  237. package/scripts/design-preferences.mjs +227 -0
  238. package/scripts/design-presets.mjs +48 -0
  239. package/scripts/grade.mjs +509 -0
  240. package/scripts/lint-rules.mjs +1065 -0
  241. package/scripts/review-evidence.mjs +120 -0
  242. package/scripts/skeleton.mjs +248 -0
  243. package/skills/entry/SKILL.md +34 -0
  244. package/skills/sable/SKILL.md +187 -0
  245. package/skills/sable/agents/openai.yaml +6 -0
  246. package/targets/ios.json +982 -0
  247. package/third-party/reicon-LICENSE.txt +20 -0
@@ -0,0 +1,92 @@
1
+ # Task: review motion as playable behavior
2
+
3
+ Use this workflow when a meaningful transition, direct manipulation, media, or
4
+ story depends on time. Sable already supplies motion tokens and behavior
5
+ primitives. This guide reviews their composition and any external driver. A
6
+ deliberately static arrival is valid; every surface does not need animation.
7
+
8
+ ## State what the movement should explain
9
+
10
+ For each behavior under review, record the trigger, the elements or state that
11
+ change, the intended relationship, the driver, and the expected final state.
12
+ Include duration or scroll range when known, easing, interruption/reversal,
13
+ keyboard/touch equivalence, and the reduced-motion result. For a reference, keep
14
+ observed behavior separate from a proposed recreation.
15
+
16
+ Example: expanding a selected workshop exposes its details while retaining the
17
+ date choice. Repeated toggles should end in the user's latest requested state,
18
+ without an invisible focus target or an extra queued transition. Reduced motion
19
+ can reveal the same content immediately while preserving focus and feedback.
20
+
21
+ ## Capture the kind of evidence the claim needs
22
+
23
+ | Evidence | What it establishes | What it does not establish |
24
+ |---|---|---|
25
+ | Still screenshot | A visible state at capture time | Duration, smoothness, trigger, or reversal |
26
+ | Timestamped frame sequence | Sampled states and their recorded capture times | Continuous motion between samples or a measured frame rate |
27
+ | Playable recording | The recorded sequence, including visible response to actions | Other devices, refresh rates, or unrecorded inputs |
28
+ | Runtime event/animation report | Logged events, computed values, or declared timing | Perceived quality or that every declared animation ran |
29
+
30
+ Use a recording when available. Otherwise retain real sampled frames and a
31
+ small manifest listing their order, timestamps, actions, and observed outcomes.
32
+ Do not synthesize intermediate frames or assign evenly spaced timestamps to
33
+ captures that were not taken that way. If recording is unavailable, say so;
34
+ observed behavior can still be reported with its limits.
35
+
36
+ Record viewport, route/state, color mode, full/reduced motion, input actions, and
37
+ capture conditions. Preserve the real playback speed. A slowed study copy may
38
+ help inspection, but label its retiming and retain the original. Mask or avoid
39
+ private data before capture. Include the source hash and hashes of final artifacts.
40
+
41
+ ## Make the evidence inspectable
42
+
43
+ Provide a local review page with playback controls, or an ordered frame viewer
44
+ with previous/next controls and visible timestamps. Do not autoplay a review
45
+ recording. For a video, native controls are sufficient:
46
+
47
+ ```html
48
+ <figure>
49
+ <video controls preload="metadata" poster="open-menu.webp"
50
+ aria-describedby="motion-note" src="menu-toggle.webm"></video>
51
+ <figcaption id="motion-note">
52
+ Desktop, full motion. Open, close during entry, then reopen.
53
+ This recording shows the observed run, not a performance benchmark.
54
+ </figcaption>
55
+ </figure>
56
+ ```
57
+
58
+ Use actual files from the run, provide text describing the actions and outcomes,
59
+ and captions or an equivalent transcript when meaningful audio is present. Open
60
+ the saved review artifact and confirm it plays or advances correctly; a file's
61
+ existence alone is insufficient.
62
+
63
+ ## Test the behavior, including interruption
64
+
65
+ Operate the trigger, reverse it before completion, repeat it, and navigate or
66
+ resize during it when those are plausible product actions. Check that the final
67
+ state matches intent, input does not queue unexpectedly, focus remains usable,
68
+ and canceled work does not report success. Inspect the behavior at normal speed:
69
+ is the response immediate enough for its frequency, and does the movement explain
70
+ the change without delaying access to content?
71
+
72
+ Repeat relevant behavior with reduced motion enabled. This should preserve state,
73
+ focus, status, and controls; hiding the animated content is not an equivalent
74
+ result. Test a custom driver directly—Sable's policy cannot disable an unrelated
75
+ animation by itself. Pause or otherwise control meaningful persistent media as
76
+ appropriate to the surface, and verify its static/loading fallback.
77
+
78
+ ## Record conclusions at the right confidence
79
+
80
+ Separate source-declared timing, runtime measurements, and visual observations.
81
+ A CSS duration is not elapsed end-to-end latency. State where a value was measured
82
+ and what the measurement covers; avoid precise timing claims from visual guesses.
83
+ Use specific findings such as "closing during entry left focus in the hidden
84
+ panel," then retain the repaired run beside the original.
85
+
86
+ The existing `sable grade` review schema accepts `recording` and `report`
87
+ artifacts as well as screenshots; see [reviewing-a-design.md](./reviewing-a-design.md)
88
+ for their hashes and required context. A frame manifest can be a report, with its
89
+ linked frame files preserved. The validator checks the referenced artifact bytes,
90
+ not every link inside a report or the quality of playback. Keep full and reduced
91
+ evidence distinct, mark unexercised behaviors untested, and promote a motion
92
+ lesson only within the contexts the observation supports.
@@ -0,0 +1,87 @@
1
+ # Task: use a portable preset
2
+
3
+ Bundled presets are maintained with Sable. Personal presets are app-owned JSON
4
+ files that use the same component and token contract. Canvas and the skill read
5
+ the same portable format; no separate review app is required.
6
+
7
+ The schema contains `schemaVersion: 1`, a lowercase slug `id`, `label`, positive
8
+ `revision`, authoring `sableVersion`, `defaultMode`, `fonts.sans`/`fonts.mono`
9
+ (optional `display`), design `direction`, optional `references`, and
10
+ `tokens.shared`, `tokens.light`, and `tokens.dark` objects. Token keys omit `--`.
11
+ Both mode objects declare the full semantic color set, including `background`,
12
+ `foreground`, `primary`, and their paired roles.
13
+ Other supported values include typography, radii, control density, motion,
14
+ shadows, spacing, workspace surfaces, and layering. `sable preset --template`
15
+ prints a complete starting record; the public `PRESET_TOKEN_NAMES` is authoritative.
16
+
17
+ Font stacks are requirements, not downloaded fonts. Declare matching stacks in
18
+ the font metadata and tokens. Resolve internal palette variables before saving;
19
+ portable presets may reference public Sable tokens, not private palette names.
20
+ The validator rejects unknown tokens and CSS that can escape its declaration.
21
+ It does not certify contrast or that a CSS value makes visual sense.
22
+
23
+ Motion durations are nominal times at scale 1. `presetCss()` and the CLI connect
24
+ them to the live `--motion-scale` policy, so reduced motion still stops recipes.
25
+ Keep existing duration or motion-scale references when authoring CSS expressions;
26
+ do not freeze the current operating system preference into duration values.
27
+
28
+ ## Import and customize
29
+
30
+ Open Canvas, choose Export, and import the JSON file. An imported preset is
31
+ registered as a custom theme, while the inspector uses the default theme.
32
+ Review the Sable component scenes in both modes. Customize, add direction notes,
33
+ and download a JSON record. Preserve the original record when developing variants.
34
+
35
+ ## Build a product
36
+
37
+ Place the file in the target project's `.sable/presets/` directory. Read its exact
38
+ ID, revision, tokens, fonts, guidance, and evidence before starting. The product
39
+ brief determines content, layout, and behavior; guidance informs those decisions.
40
+
41
+ ```bash
42
+ pnpm exec sable preset --check .sable/presets/clay.json --json
43
+ pnpm exec sable preset --css .sable/presets/clay.json > src/clay.css
44
+ ```
45
+
46
+ Import the generated CSS after Sable's stylesheet. Load the declared fonts.
47
+ Register the manifest without editing the library:
48
+
49
+ ```tsx
50
+ import { SableThemeProvider } from "@sableui/react"
51
+ import { parsePreset, presetManifest } from "@sableui/react/presets"
52
+ import record from "../.sable/presets/clay.json"
53
+ import "./clay.css"
54
+
55
+ const preset = parsePreset(record)
56
+ const customThemes = [presetManifest(preset)]
57
+
58
+ export function App() {
59
+ return (
60
+ <SableThemeProvider customThemes={customThemes}
61
+ defaultThemeId={preset.id} defaultPreference={preset.defaultMode}>
62
+ {/* Compose the user's product from Sable components. */}
63
+ </SableThemeProvider>
64
+ )
65
+ }
66
+ ```
67
+
68
+ `presetCss(preset)` also compiles CSS in browser/build tooling. Generated selectors
69
+ are scoped by `data-sable-theme`; importing a stylesheet alone does not activate it.
70
+ Use a unique preset ID so it cannot override a bundled theme or another record.
71
+ Record any intentional adaptation and run the validation and rendered review in
72
+ [building-with-sable.md](./building-with-sable.md).
73
+
74
+ ## Upgrade the package and skill
75
+
76
+ ```bash
77
+ pnpm update @sableui/react --latest
78
+ pnpm exec sable setup --agent --update
79
+ pnpm exec sable preset --check .sable/presets/clay.json --json
80
+ pnpm exec sable doctor
81
+ ```
82
+
83
+ The skill loads instructions from the installed package on every task. Setup
84
+ refreshes unchanged managed entry files and preserves local edits. Local presets
85
+ and project preferences survive upgrades. `sableVersion` records provenance;
86
+ validation uses the current installed token vocabulary. Review the changelog
87
+ and recheck the product when upgrading.
@@ -0,0 +1,53 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "recordType": "asset-plan",
4
+ "status": "planned",
5
+ "surface": "Describe the target surface and audience",
6
+ "direction": {
7
+ "message": "What the assets should make understandable",
8
+ "sharedTreatment": "Composition, material, light or line, and color relationships",
9
+ "intentionalDifferences": "How subjects remain distinguishable within the set"
10
+ },
11
+ "initialPayloadBudgetBytes": null,
12
+ "assets": [
13
+ {
14
+ "id": "primary-visual",
15
+ "kind": "illustration",
16
+ "role": "Explain this asset's job in the surface",
17
+ "subject": "Specify the actual subject and important details",
18
+ "source": {
19
+ "origin": "unresolved",
20
+ "location": null,
21
+ "creator": null,
22
+ "usageStatus": "unresolved",
23
+ "permissionOrLicense": null,
24
+ "attribution": null
25
+ },
26
+ "treatment": "Specify framing, material, light or geometry, and color",
27
+ "variants": [
28
+ {
29
+ "id": "wide",
30
+ "placement": "Describe where and at which viewport this is used",
31
+ "focalSubject": "What must survive the crop",
32
+ "crop": "Describe framing and any reserved text area",
33
+ "path": null,
34
+ "width": null,
35
+ "height": null,
36
+ "format": null,
37
+ "budgetBytes": null,
38
+ "actualBytes": null
39
+ }
40
+ ],
41
+ "accessibility": {
42
+ "decorative": false,
43
+ "textAlternative": null
44
+ },
45
+ "fallback": "Describe the usable missing/loading-media state",
46
+ "readiness": "planned",
47
+ "verification": []
48
+ }
49
+ ],
50
+ "fonts": [],
51
+ "reviewedCaptures": [],
52
+ "openQuestions": []
53
+ }
@@ -0,0 +1,20 @@
1
+ # Composition follows content
2
+
3
+ Mixed-width feature audits gave primary ideas more space. The reusable decision
4
+ is that emphasis follows the importance and shape of the content. A particular
5
+ 7/5 grid is only one implementation.
6
+
7
+ Write the section's job before choosing its container. A comparison needs shared
8
+ baselines; a sequence needs order; a single artifact benefits from uninterrupted
9
+ space; subordinate facts can live in a ruled list. A card earns its edge when it
10
+ groups a distinct object or interactive destination. Space can group text without
11
+ a container.
12
+
13
+ Inspect the whole page at reduced scale. If every section has the same silhouette,
14
+ check whether the content actually has the same job. Vary width or density when
15
+ the story changes, while keeping alignment anchors and a small spacing vocabulary.
16
+ Preserve predictable repetition for equivalent records, forms, and frequent tasks.
17
+
18
+ Provenance: distilled from the bundled mixed-width feature pattern and editorial
19
+ reference audits. This is conditional precedent, not evidence that asymmetry is
20
+ always better. Retrieve `sable learn --show composition-follows-content --json`.
@@ -0,0 +1,22 @@
1
+ # Hierarchy is a relationship
2
+
3
+ Prior builds picked real `text-title-*` utilities for feature titles
4
+ whose role in the composition was closer to a display heading. Every token was
5
+ valid; the hierarchy still flattened. Another build reproduced a measured 128px
6
+ display size inside a narrower container, turning roughly three lines into six.
7
+
8
+ Choose the semantic HTML heading level separately from its visual tier. Set the
9
+ text, available measure, tier, weight, and adjacent spacing together, then inspect
10
+ the rendered line count on desktop and mobile. If the phrase is factual or
11
+ approved, change the layout before rewriting it. Load the actual font before
12
+ judging the result; fallback metrics are different.
13
+
14
+ Transfer this to display-led reading and persuasion surfaces. In an operating
15
+ tool, task hierarchy and scan speed may call for smaller type and consistent rows.
16
+ Large type and light weight are possible choices, never a universal recipe for
17
+ quality.
18
+
19
+ Provenance: distilled from the Sable build pipeline's recorded
20
+ typography and line-wrap defects. This is a curated precedent, not a fresh visual
21
+ test of the current package. Retrieve the structured record with
22
+ `sable learn --show hierarchy-is-a-relationship --json`.
@@ -0,0 +1,57 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lessons": [
4
+ {
5
+ "schemaVersion": 1,
6
+ "id": "hierarchy-is-a-relationship",
7
+ "title": "Choose type together with measure and content",
8
+ "tags": ["typography", "hierarchy", "editorial", "display", "wrapping", "spacing"],
9
+ "register": "page",
10
+ "mode": "either",
11
+ "principle": "A correct size token does not guarantee the intended hierarchy. Compare rendered size, weight, line count, measure, and adjacent content as one composition.",
12
+ "appliesWhen": "A display-led page feels timid or a headline wraps into many more lines than the brief intended.",
13
+ "avoidWhen": "Do not inflate headings in task-dense workspace chrome or replace factual copy merely to force a preferred wrap.",
14
+ "provenance": { "kind": "curated-precedent", "source": "Distilled recurring typography defects in maintained build reviews", "date": "2026-09-06" },
15
+ "evidence": [{ "kind": "source", "path": "llms/taste/hierarchy-is-a-relationship.md", "observation": "Prior builds used valid title tokens but flattened display-led feature headings; narrow containers also turned a three-line headline into six lines." }]
16
+ },
17
+ {
18
+ "schemaVersion": 1,
19
+ "id": "composition-follows-content",
20
+ "title": "Give unequal content unequal emphasis",
21
+ "tags": ["composition", "story", "layout", "rhythm", "asymmetry", "cards"],
22
+ "register": "page",
23
+ "mode": "either",
24
+ "principle": "Choose a section's structure from what it must communicate: a sequence, comparison, decision, object, or reading passage. Repetition is useful when the content is equivalent.",
25
+ "appliesWhen": "Distinct sections all collapse into centered headings above identical icon-and-card grids.",
26
+ "avoidWhen": "Do not make equally important records different sizes or rearrange a familiar operating flow to manufacture novelty.",
27
+ "provenance": { "kind": "curated-precedent", "source": "Distilled mixed-width feature and editorial reference audit patterns", "date": "2026-09-06" },
28
+ "evidence": [{ "kind": "source", "path": "llms/taste/composition-follows-content.md", "observation": "Reference audits preserved larger feature areas for primary ideas while secondary facts used compact rows, captions, or rules." }]
29
+ },
30
+ {
31
+ "schemaVersion": 1,
32
+ "id": "motion-needs-a-reason",
33
+ "title": "Use motion to explain a change",
34
+ "tags": ["motion", "animation", "interaction", "reduced", "timing", "restraint"],
35
+ "register": "either",
36
+ "mode": "either",
37
+ "principle": "Declare a trigger, purpose, duration, interruption behavior, and reduced-motion result. A static initial state can be intentional; every user action still needs understandable feedback.",
38
+ "appliesWhen": "A build has indiscriminate scroll reveals, generic spring entrances, or no feedback between meaningful states.",
39
+ "avoidWhen": "Do not transfer slow editorial choreography into frequent workspace operations, hide initial content while waiting for animation, or simulate scroll-driven behavior with an entrance fade.",
40
+ "provenance": { "kind": "curated-precedent", "source": "Contrasting editorial motion and dense technical tool reference audits", "date": "2026-09-06" },
41
+ "evidence": [{ "kind": "source", "path": "llms/taste/motion-needs-a-reason.md", "observation": "Editorial audits recorded deliberate cascades; technical audits recorded short ease-out feedback without overshoot. Their motion grammars were different." }]
42
+ },
43
+ {
44
+ "schemaVersion": 1,
45
+ "id": "surface-states-travel-together",
46
+ "title": "Retheme the complete interaction state",
47
+ "tags": ["color", "contrast", "hover", "interaction", "surface", "theme"],
48
+ "register": "either",
49
+ "mode": "either",
50
+ "principle": "Foreground, fill, border, hover, focus, selected, and disabled states form one surface contract. Inspect the actual rendered states after an override.",
51
+ "appliesWhen": "An existing control is moved onto an inverted, tinted, or media-backed section.",
52
+ "avoidWhen": "Do not add per-call-site color overrides when the theme already expresses the intended semantic surface.",
53
+ "provenance": { "kind": "curated-precedent", "source": "Recorded dark-band button hover regression in build guidance", "date": "2026-09-06" },
54
+ "evidence": [{ "kind": "source", "path": "llms/taste/surface-states-travel-together.md", "observation": "An outline button had readable resting text on a dark band, but its inherited hover foreground was tuned for a light surface and disappeared." }]
55
+ }
56
+ ]
57
+ }
@@ -0,0 +1,21 @@
1
+ # Motion needs a reason
2
+
3
+ Editorial reference audits found shared entrance timelines, small travel, and
4
+ slower media transitions. Technical tool audits found short ease-out feedback and
5
+ no overshoot. Copying one grammar into the other loses the purpose that made it
6
+ work.
7
+
8
+ For each meaningful change, record trigger, user benefit, driver, duration/ease,
9
+ interruption behavior, and reduced-motion result. Feedback confirms an action;
10
+ spatial motion can explain where content went; activity distinguishes waiting
11
+ from failure. Initial reading content can paint immediately. A deliberate static
12
+ choice is valid when no information is gained by animation.
13
+
14
+ Use Sable's motion tokens and primitives where they express that decision. Custom
15
+ CSS and external animation drivers must also honor the motion policy. Inspect a
16
+ real state change and reduced-motion mode; a resting screenshot cannot establish
17
+ timing, interruption behavior, or that content remains available.
18
+
19
+ Provenance: distilled from the contrasting calm editorial and dense technical
20
+ reference audit grammars. Timing numbers in an old audit are observations, not
21
+ mandatory new defaults. Retrieve `sable learn --show motion-needs-a-reason --json`.
@@ -0,0 +1,20 @@
1
+ # Surface states travel together
2
+
3
+ A recorded build defect placed an outline button on a dark band and
4
+ overrode its resting foreground. The inherited hover foreground still belonged to
5
+ a light surface. The button was legible in screenshots and lost its label on hover.
6
+
7
+ Prefer a coherent semantic surface scope. If an override is required, inspect
8
+ the component's full variant contract and verify fill, text, border, hover,
9
+ focus-visible, disabled, and selected states as appropriate. Use a matching
10
+ foreground token with each surface token. Do not assume one resting override
11
+ replaces every state-specific class.
12
+
13
+ Check the rendered control with pointer and keyboard, in each supported color
14
+ mode. Moving a control onto media also requires checking the least legible part
15
+ of the image, including after crop changes. A local state test is stronger evidence
16
+ than a claim that the palette has passed a token contrast test elsewhere.
17
+
18
+ Provenance: a dark-band button hover failure documented in the Sable reference
19
+ build workflow. This packaged distillation preserves the failure mechanism without
20
+ requiring access to private reference artifacts.