@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.
- package/AGENTS.md +157 -0
- package/CHANGELOG.md +55 -0
- package/CONTRIBUTING.md +221 -0
- package/DESIGN.md +548 -0
- package/LICENSE +21 -0
- package/README.md +194 -2
- package/THIRD_PARTY_NOTICES.md +44 -0
- package/bin/sable-lint.mjs +0 -0
- package/bin/sable.mjs +1223 -0
- package/dist/_contract-CYScOdf5.d.ts +150 -0
- package/dist/chunk-3IWZYBGH.js +398 -0
- package/dist/chunk-5Z5KLOAU.js +167 -0
- package/dist/chunk-7MG4SHYX.js +15 -0
- package/dist/chunk-ADLLDWLW.js +15 -0
- package/dist/chunk-EP55KSYA.js +14 -0
- package/dist/chunk-J23ELQQZ.js +9396 -0
- package/dist/chunk-JI7WJP2L.js +286 -0
- package/dist/chunk-K7RUHUGC.js +14 -0
- package/dist/chunk-KO3NAEBF.js +15 -0
- package/dist/chunk-L4IEIQQA.js +14 -0
- package/dist/chunk-L6Y46C62.js +270 -0
- package/dist/chunk-NEQNXI2G.js +25 -0
- package/dist/chunk-PAOZBZME.js +40 -0
- package/dist/chunk-RWP4XBSK.js +139 -0
- package/dist/chunk-SRQWQUTW.js +63 -0
- package/dist/chunk-YXBOYWBN.js +15 -0
- package/dist/foundations/index.d.ts +88 -0
- package/dist/foundations/index.js +792 -0
- package/dist/icon/index.d.ts +60 -0
- package/dist/icon/index.js +2 -0
- package/dist/icon-sets/brands.d.ts +44 -0
- package/dist/icon-sets/brands.js +147 -0
- package/dist/icon-sets/reicon.d.ts +8 -0
- package/dist/icon-sets/reicon.js +1 -0
- package/dist/index.d.ts +7013 -0
- package/dist/index.js +15462 -0
- package/dist/ios/chrome.css +83 -0
- package/dist/ios/frame.css +5 -0
- package/dist/ios/index.d.ts +70 -0
- package/dist/ios/index.js +313 -0
- package/dist/ios/preview.d.ts +64 -0
- package/dist/ios/preview.js +133 -0
- package/dist/ios/styles.css +77 -0
- package/dist/layout/index.d.ts +280 -0
- package/dist/layout/index.js +2 -0
- package/dist/meta-6dUzgC6M.d.ts +205 -0
- package/dist/patterns/index.d.ts +36 -0
- package/dist/patterns/index.js +934 -0
- package/dist/presets/index.d.ts +37 -0
- package/dist/presets/index.js +117 -0
- package/dist/registry-CyL28OzJ.d.ts +28 -0
- package/dist/styles.css +1893 -0
- package/dist/theme-provider-BWcizhAt.d.ts +105 -0
- package/dist/themes/atelier/atelier.css +213 -0
- package/dist/themes/atelier/index.d.ts +9 -0
- package/dist/themes/atelier/index.js +1 -0
- package/dist/themes/base/base.css +443 -0
- package/dist/themes/base/index.d.ts +9 -0
- package/dist/themes/base/index.js +1 -0
- package/dist/themes/ember/ember.css +270 -0
- package/dist/themes/ember/index.d.ts +9 -0
- package/dist/themes/ember/index.js +1 -0
- package/dist/themes/index.d.ts +10 -0
- package/dist/themes/index.js +8 -0
- package/dist/themes/meridian/index.d.ts +9 -0
- package/dist/themes/meridian/index.js +1 -0
- package/dist/themes/meridian/meridian.css +255 -0
- package/dist/themes/poppy/index.d.ts +6 -0
- package/dist/themes/poppy/index.js +1 -0
- package/dist/themes/poppy/poppy.css +174 -0
- package/dist/themes/prism/index.d.ts +6 -0
- package/dist/themes/prism/index.js +1 -0
- package/dist/themes/prism/prism.css +183 -0
- package/dist/themes/verdant/index.d.ts +9 -0
- package/dist/themes/verdant/index.js +1 -0
- package/dist/themes/verdant/verdant.css +210 -0
- package/dist/themes.css +30 -0
- package/llms/components/accordion.md +93 -0
- package/llms/components/app-header.md +70 -0
- package/llms/components/app-shell.md +117 -0
- package/llms/components/attachment.md +105 -0
- package/llms/components/avatar.md +141 -0
- package/llms/components/badge.md +117 -0
- package/llms/components/banner.md +119 -0
- package/llms/components/bottom-nav.md +80 -0
- package/llms/components/breadcrumbs.md +75 -0
- package/llms/components/browser.md +67 -0
- package/llms/components/bubble.md +119 -0
- package/llms/components/button.md +199 -0
- package/llms/components/calendar.md +75 -0
- package/llms/components/card.md +135 -0
- package/llms/components/carousel.md +87 -0
- package/llms/components/chat-composer.md +126 -0
- package/llms/components/checkbox-card.md +98 -0
- package/llms/components/checkbox.md +90 -0
- package/llms/components/code-block.md +81 -0
- package/llms/components/code.md +62 -0
- package/llms/components/collapsible.md +83 -0
- package/llms/components/color-field.md +100 -0
- package/llms/components/combobox.md +119 -0
- package/llms/components/command-menu.md +158 -0
- package/llms/components/context-card.md +73 -0
- package/llms/components/context-menu.md +79 -0
- package/llms/components/data-table.md +99 -0
- package/llms/components/date-picker.md +97 -0
- package/llms/components/description.md +96 -0
- package/llms/components/destructive-action-modal.md +76 -0
- package/llms/components/dialog.md +127 -0
- package/llms/components/dots-menu.md +64 -0
- package/llms/components/empty-state.md +113 -0
- package/llms/components/entity.md +67 -0
- package/llms/components/feedback.md +63 -0
- package/llms/components/fieldset.md +106 -0
- package/llms/components/file-dropzone.md +103 -0
- package/llms/components/form.md +111 -0
- package/llms/components/gliding-highlight.md +84 -0
- package/llms/components/inline-status.md +62 -0
- package/llms/components/input.md +127 -0
- package/llms/components/kbd.md +57 -0
- package/llms/components/label.md +73 -0
- package/llms/components/marker.md +99 -0
- package/llms/components/marquee.md +66 -0
- package/llms/components/menu.md +122 -0
- package/llms/components/message-scroller.md +110 -0
- package/llms/components/message.md +114 -0
- package/llms/components/meter.md +124 -0
- package/llms/components/middle-truncate.md +62 -0
- package/llms/components/note.md +81 -0
- package/llms/components/notification-badge.md +67 -0
- package/llms/components/number-field.md +70 -0
- package/llms/components/otp-field.md +101 -0
- package/llms/components/page-header.md +76 -0
- package/llms/components/page-loader.md +67 -0
- package/llms/components/pagination.md +92 -0
- package/llms/components/panel-group.md +120 -0
- package/llms/components/panel-section.md +122 -0
- package/llms/components/phone.md +70 -0
- package/llms/components/pill.md +73 -0
- package/llms/components/popover.md +79 -0
- package/llms/components/progress.md +98 -0
- package/llms/components/radio-card.md +90 -0
- package/llms/components/radio.md +86 -0
- package/llms/components/relative-time.md +60 -0
- package/llms/components/scroller.md +88 -0
- package/llms/components/scrub-field.md +97 -0
- package/llms/components/search-input.md +84 -0
- package/llms/components/select.md +106 -0
- package/llms/components/separator.md +70 -0
- package/llms/components/settings-menu.md +139 -0
- package/llms/components/sheet.md +97 -0
- package/llms/components/show-more.md +59 -0
- package/llms/components/side-nav.md +106 -0
- package/llms/components/sidebar.md +87 -0
- package/llms/components/skeleton.md +62 -0
- package/llms/components/slider.md +114 -0
- package/llms/components/spinner.md +87 -0
- package/llms/components/status-bar.md +91 -0
- package/llms/components/status-dot.md +70 -0
- package/llms/components/stepper.md +125 -0
- package/llms/components/streaming-text.md +86 -0
- package/llms/components/switch.md +87 -0
- package/llms/components/table.md +112 -0
- package/llms/components/tabs.md +84 -0
- package/llms/components/textarea.md +88 -0
- package/llms/components/theme-selector.md +95 -0
- package/llms/components/theme-switcher.md +71 -0
- package/llms/components/thinking-orb.md +91 -0
- package/llms/components/toast.md +130 -0
- package/llms/components/toggle.md +95 -0
- package/llms/components/toolbar.md +168 -0
- package/llms/components/tooltip.md +93 -0
- package/llms/components/tree.md +227 -0
- package/llms/components/video.md +66 -0
- package/llms/components/workspace.md +138 -0
- package/llms/foundations/accessibility.md +60 -0
- package/llms/foundations/motion.md +96 -0
- package/llms/foundations/scrolling.md +41 -0
- package/llms/foundations/shape.md +73 -0
- package/llms/foundations/spacing.md +82 -0
- package/llms/foundations/surfaces.md +69 -0
- package/llms/foundations/typography.md +120 -0
- package/llms/layout/aspect-box.md +37 -0
- package/llms/layout/bleed.md +31 -0
- package/llms/layout/center.md +37 -0
- package/llms/layout/columns.md +51 -0
- package/llms/layout/grid-overlay.md +40 -0
- package/llms/layout/grid.md +47 -0
- package/llms/layout/page.md +39 -0
- package/llms/layout/region.md +49 -0
- package/llms/layout/row.md +40 -0
- package/llms/layout/safe-area.md +37 -0
- package/llms/layout/spacer.md +39 -0
- package/llms/layout/split-pane.md +41 -0
- package/llms/layout/stack.md +39 -0
- package/llms/patterns/auth-page.md +68 -0
- package/llms/patterns/brand-landing-page.md +423 -0
- package/llms/patterns/chat-panel.md +210 -0
- package/llms/patterns/dashboard-page.md +170 -0
- package/llms/patterns/feed-page.md +103 -0
- package/llms/patterns/landing-page.md +122 -0
- package/llms/patterns/list-detail-page.md +100 -0
- package/llms/patterns/settings-page.md +121 -0
- package/llms/reference/token-intent.md +324 -0
- package/llms/reference/utilities.md +129 -0
- package/llms/tasks/adding-a-component.md +113 -0
- package/llms/tasks/auditing-an-app.md +216 -0
- package/llms/tasks/building-a-page.md +109 -0
- package/llms/tasks/building-a-tool.md +141 -0
- package/llms/tasks/building-an-ios-prototype.md +105 -0
- package/llms/tasks/building-with-sable.md +73 -0
- package/llms/tasks/choosing-a-component.md +109 -0
- package/llms/tasks/converting-an-app.md +139 -0
- package/llms/tasks/creating-a-preset.md +43 -0
- package/llms/tasks/creating-design-assets.md +96 -0
- package/llms/tasks/designing-a-surface.md +115 -0
- package/llms/tasks/developing-taste.md +157 -0
- package/llms/tasks/getting-started.md +63 -0
- package/llms/tasks/learning-from-builds.md +74 -0
- package/llms/tasks/reviewing-a-design.md +114 -0
- package/llms/tasks/reviewing-a-journey.md +84 -0
- package/llms/tasks/reviewing-motion.md +92 -0
- package/llms/tasks/using-presets.md +87 -0
- package/llms/taste/asset-plan.template.json +53 -0
- package/llms/taste/composition-follows-content.md +20 -0
- package/llms/taste/hierarchy-is-a-relationship.md +22 -0
- package/llms/taste/lessons.json +57 -0
- package/llms/taste/motion-needs-a-reason.md +21 -0
- package/llms/taste/surface-states-travel-together.md +20 -0
- package/llms-full.txt +14906 -0
- package/llms.txt +405 -0
- package/package.json +185 -3
- package/registry.json +18812 -0
- package/scripts/agent-setup.mjs +54 -0
- package/scripts/design-atlas.mjs +221 -0
- package/scripts/design-directions.mjs +123 -0
- package/scripts/design-memory.mjs +166 -0
- package/scripts/design-preferences.mjs +227 -0
- package/scripts/design-presets.mjs +48 -0
- package/scripts/grade.mjs +509 -0
- package/scripts/lint-rules.mjs +1065 -0
- package/scripts/review-evidence.mjs +120 -0
- package/scripts/skeleton.mjs +248 -0
- package/skills/entry/SKILL.md +34 -0
- package/skills/sable/SKILL.md +187 -0
- package/skills/sable/agents/openai.yaml +6 -0
- package/targets/ios.json +982 -0
- 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.
|