sheleg-design-skill 1.51.1 → 1.53.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.
- package/CHANGELOG.md +142 -0
- package/README.md +5 -4
- package/bin/cli.js +5 -1
- package/cursor/rules/sheleg-design.mdc +7 -0
- package/kits/deskmate/src/styles.css +89 -26
- package/kits/onionskin/src/styles.css +19 -2
- package/kits/test-drive/.design-sync/config.json +14 -0
- package/kits/test-drive/.design-sync/conventions.md +40 -0
- package/kits/test-drive/README.md +34 -0
- package/kits/test-drive/package.json +29 -0
- package/kits/test-drive/src/Annotation.md +13 -0
- package/kits/test-drive/src/Annotation.tsx +20 -0
- package/kits/test-drive/src/Button.md +23 -0
- package/kits/test-drive/src/Button.tsx +33 -0
- package/kits/test-drive/src/Card.md +14 -0
- package/kits/test-drive/src/Card.tsx +24 -0
- package/kits/test-drive/src/Chip.md +13 -0
- package/kits/test-drive/src/Chip.tsx +25 -0
- package/kits/test-drive/src/Delta.md +11 -0
- package/kits/test-drive/src/Delta.tsx +23 -0
- package/kits/test-drive/src/DemoFrame.md +19 -0
- package/kits/test-drive/src/DemoFrame.tsx +25 -0
- package/kits/test-drive/src/Empty.md +13 -0
- package/kits/test-drive/src/Empty.tsx +21 -0
- package/kits/test-drive/src/Field.md +18 -0
- package/kits/test-drive/src/Field.tsx +38 -0
- package/kits/test-drive/src/Heading.md +13 -0
- package/kits/test-drive/src/Heading.tsx +19 -0
- package/kits/test-drive/src/Machine.md +18 -0
- package/kits/test-drive/src/Machine.tsx +26 -0
- package/kits/test-drive/src/Marker.md +11 -0
- package/kits/test-drive/src/Marker.tsx +12 -0
- package/kits/test-drive/src/NavBar.md +14 -0
- package/kits/test-drive/src/NavBar.tsx +20 -0
- package/kits/test-drive/src/Rule.md +11 -0
- package/kits/test-drive/src/Rule.tsx +18 -0
- package/kits/test-drive/src/Stat.md +18 -0
- package/kits/test-drive/src/Stat.tsx +17 -0
- package/kits/test-drive/src/ThinkingDots.md +15 -0
- package/kits/test-drive/src/ThinkingDots.tsx +19 -0
- package/kits/test-drive/src/index.ts +33 -0
- package/kits/test-drive/src/styles.css +833 -0
- package/kits/test-drive/tsconfig.json +15 -0
- package/package.json +3 -3
- package/plugins/sheleg-design/.claude-plugin/plugin.json +2 -2
- package/plugins/sheleg-design/commands/sheleg-design.md +2 -2
- package/plugins/sheleg-design/skills/sheleg-design/DESIGN_SYNC_BRIDGE.md +1 -1
- package/plugins/sheleg-design/skills/sheleg-design/FIGMA_BRIDGE.md +2 -2
- package/plugins/sheleg-design/skills/sheleg-design/MOBILE_SURFACES.md +1 -1
- package/plugins/sheleg-design/skills/sheleg-design/SKILL.md +3 -3
- package/plugins/sheleg-design/skills/sheleg-design/STYLE_PACK_INDEX.md +3 -2
- package/plugins/sheleg-design/skills/sheleg-design/SURFACE_COMPOSITION.md +8 -5
- package/plugins/sheleg-design/skills/sheleg-design/styles/STYLE_PACK_TEMPLATE.md +1 -1
- package/plugins/sheleg-design/skills/sheleg-design/styles/datasheet.md +5 -1
- package/plugins/sheleg-design/skills/sheleg-design/styles/deskmate.md +61 -18
- package/plugins/sheleg-design/skills/sheleg-design/styles/scoreboard.md +6 -1
- package/plugins/sheleg-design/skills/sheleg-design/styles/showroom.md +5 -1
- package/plugins/sheleg-design/skills/sheleg-design/styles/tenor.md +1 -1
- package/plugins/sheleg-design/skills/sheleg-design/styles/test-drive.md +454 -0
- package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/deskmate.css +68 -10
- package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/onionskin.css +19 -2
- package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/test-drive.css +389 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,148 @@ follow [SemVer](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.53.0] - 2026-08-27
|
|
10
|
+
|
|
11
|
+
### The thirty-seventh pack — the visitor is handed the keys
|
|
12
|
+
|
|
13
|
+
**`test-drive`**, extracted from a revenue-analytics product's front page and named per
|
|
14
|
+
ADR-0001 for the register it encodes: a page that sells by handing over the running
|
|
15
|
+
product — the set piece is the live app inside drawn browser chrome, and a founder's
|
|
16
|
+
hand (a script face, a yellow marker, a drawn arrow) annotates the tour.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- `styles/test-drive.md` — widened, all thirteen headings; `Themes: light + dark — a
|
|
21
|
+
full theme twin`; three forks written from both sides: against `datasheet` (whose
|
|
22
|
+
live instrument reads *the visitor*, where this one hands over *the product's own
|
|
23
|
+
workspace*), against `showroom` (a still exhibit against a running machine), and
|
|
24
|
+
against `scoreboard` (one public total against a dashboard's vital signs on the
|
|
25
|
+
same warm paper and orange-red family).
|
|
26
|
+
- `styles/tokens/test-drive.css` — measured off the render, not the stylesheet, and
|
|
27
|
+
the reference is the trap the skeleton's rule 7 describes: its DaisyUI theme
|
|
28
|
+
declares a teal accent that paints **nothing** (the area-weighted census found it
|
|
29
|
+
on zero elements), so the acting coral is the brand and the teal ships nowhere.
|
|
30
|
+
The coral splits into two tokens because the reference's own CTA fails AA —
|
|
31
|
+
`#ffffff` on `#e16540` is 3.42:1 — so `--accent` lights, fills and blinks while
|
|
32
|
+
`--action` `#c04a28` carries every body-size word at 4.94:1 under white. The lit
|
|
33
|
+
control recipe (contact shadow, hue ring, glow, inner bevel) is read byte-for-byte
|
|
34
|
+
out of the reference's authored `.btn-primary`/`.btn-simple` classes, in both
|
|
35
|
+
themes. The machine ladder (`--machine-*`, `#101010`–`#202020`) is quarantined and
|
|
36
|
+
ignores the theme.
|
|
37
|
+
- `kits/test-drive/` — the six-name spine plus `DemoFrame`, `Annotation`, `Marker`,
|
|
38
|
+
`Delta`, `Machine`+`Caret`, `ThinkingDots`, `Field`, `NavBar`, `Empty`. Rendered at
|
|
39
|
+
1440, 768 and an emulated 390 before shipping (CONTRIBUTING step 8): the render
|
|
40
|
+
caught the nav computing 66px against a stated 65 (a content-box border), the link
|
|
41
|
+
row overflowing a 390px page at 428px, and the touch floor missing — all three
|
|
42
|
+
fixed pre-tag. The stat row is a container (`container-type: inline-size`),
|
|
43
|
+
stepping 2 → 4 → 7 columns by its own width.
|
|
44
|
+
- `test/scenarios.md` T35 — `test-drive` against `datasheet`, the live-instrument
|
|
45
|
+
fork, with its negative branch per standing instruction 4.
|
|
46
|
+
- ADR-0001 gains its fourteenth application: `test-drive`, with `showfloor`,
|
|
47
|
+
`sandbox`, `marginalia` and `demo-day` weighed and rejected on the ADR's own
|
|
48
|
+
criteria.
|
|
49
|
+
|
|
50
|
+
### Changed
|
|
51
|
+
|
|
52
|
+
- `datasheet`, `showroom`, `scoreboard` — each gains the reciprocal fork clause
|
|
53
|
+
naming `test-drive`.
|
|
54
|
+
- Counted claims moved with the tree: thirty-seven packs and kits across `SKILL.md`,
|
|
55
|
+
the index, `SURFACE_COMPOSITION.md` (the accent is `--accent` in 34 of the 37),
|
|
56
|
+
`FIGMA_BRIDGE.md` (twelve of the thirty-seven ship a twin), `MOBILE_SURFACES.md`,
|
|
57
|
+
`DESIGN_SYNC_BRIDGE.md`, the template's theme split (12/16/9), README, DOCMAP,
|
|
58
|
+
both installers and all three manifests.
|
|
59
|
+
|
|
60
|
+
## [1.52.0] - 2026-08-27
|
|
61
|
+
|
|
62
|
+
### The front door is the designs
|
|
63
|
+
|
|
64
|
+
Opening the published catalogue used to mean reading three tiles and clicking one before
|
|
65
|
+
seeing a single pack. It now opens **on the packs**, behind a tab strip of three real
|
|
66
|
+
screens: **Designs** (the front door, and it is the gallery), **Audit** and **Method** —
|
|
67
|
+
the prose that used to occupy the index. `packs.html` stays as a canonical alias for the
|
|
68
|
+
URL the gallery lived at, because two URLs serving one gallery is duplicate content.
|
|
69
|
+
|
|
70
|
+
The tabs are links to pages rather than panels toggled in one document, and that is the
|
|
71
|
+
SEO decision, not a shortcut: one URL per screen, every screen fully in the HTML, nothing
|
|
72
|
+
behind a click a crawler has to execute. `rel="prefetch"` buys the tab feel back.
|
|
73
|
+
|
|
74
|
+
### What the SEO pass changed
|
|
75
|
+
|
|
76
|
+
- **Structured data, with one publisher everybody points at.** A `CollectionPage` whose
|
|
77
|
+
`mainEntity` is an `ItemList` of all thirty-six packs, each with its own anchor
|
|
78
|
+
(`/#pack-<name>`), so an answer engine can lift the list without running the filter JS;
|
|
79
|
+
a `SoftwareApplication` on Method; `BreadcrumbList` on both sub-pages; and an
|
|
80
|
+
`Organization` node referenced by `@id` from every page. The family site shipped the
|
|
81
|
+
opposite of that for two releases — a publisher node nothing pointed at.
|
|
82
|
+
- **A `404.html`**, a three-URL sitemap that lists only indexable screens, `llms.txt`
|
|
83
|
+
rewritten for the new shape, and `max-image-preview:large`, `color-scheme`,
|
|
84
|
+
`theme-color`, `og:site_name` and `og:locale` on every page.
|
|
85
|
+
- **Two defects the pass found in the old pages:** `method.html` was emitting its
|
|
86
|
+
canonical and description **twice** (the shared `HEAD` and `page_meta` both fired), and
|
|
87
|
+
the published dark-field count was **wrong** — `gallery.py` could not parse
|
|
88
|
+
`oklch()`, so `briefing-room`'s near-black field read as light and the site, its
|
|
89
|
+
`llms.txt` and its gallery all said five dark packs where six ship.
|
|
90
|
+
|
|
91
|
+
### `deskmate`, corrected by its own audit
|
|
92
|
+
|
|
93
|
+
A blind read of the pack (T34a, which also routed correctly and rejected `tenor` on the
|
|
94
|
+
quoted clause) found nine defects. The important one is a colour pairing no gate can see:
|
|
95
|
+
`--surface` stays white on the dusk surface while `--ink` inverts to white, so **a card
|
|
96
|
+
that painted its heading in `--ink` painted white on white** inside an inverted section.
|
|
97
|
+
The pack now ships `--on-surface` and `--on-surface-soft` — words on a card take those,
|
|
98
|
+
words on the field take `--ink` — and the kit consumes them.
|
|
99
|
+
|
|
100
|
+
Also fixed: the focus ring shipped derived-only, so a browser without `color-mix()` got
|
|
101
|
+
**no ring at all** (literal first now, derived inside `@supports`, the mechanism
|
|
102
|
+
`showroom` established); the slab's inset was 40px in the pack and 80px in the token
|
|
103
|
+
layer; the gutter ramp stated four steps and shipped two tokens; the measure stated in
|
|
104
|
+
prose (62ch/68ch) had no token; the entrance duration's two measurements (0.64s declared,
|
|
105
|
+
0.7s computed) were never reconciled; "the smallest radius that ships" and "every control
|
|
106
|
+
is 56px" were both contradicted by the pack's own body; and the provenance promise was
|
|
107
|
+
broader than the layer delivers.
|
|
108
|
+
|
|
109
|
+
One finding was rejected: `deskmate` is absent from `MOTION_DOCTRINE.md`'s ceiling
|
|
110
|
+
passage, and that passage is a named selection whose home the gate declares to be the
|
|
111
|
+
pack's own Register.
|
|
112
|
+
|
|
113
|
+
### `onionskin` gets the same focus-ring guard
|
|
114
|
+
|
|
115
|
+
The audit that read `deskmate` measured the whole library for the same shape: three
|
|
116
|
+
packs derive a focus ring, and only `showroom` guarded it. `onionskin`'s ring was
|
|
117
|
+
`color-mix()`-only, so a browser without `color-mix()` painted **no ring at all** — the
|
|
118
|
+
one degradation both packs say they may not ship. The literal now sits in `:root` and the
|
|
119
|
+
derived form in an `@supports` block; no computed value changed, and its kit's token
|
|
120
|
+
block was resynced with it.
|
|
121
|
+
|
|
122
|
+
### A count nothing could check, and now can
|
|
123
|
+
|
|
124
|
+
`SURFACE_COMPOSITION.md` claimed `--accent` in **twenty-nine** of the packs at a true
|
|
125
|
+
**thirty-three**, and named two of the three packs that call the accent something else —
|
|
126
|
+
omitting `babylove` entirely, so a reader following that sentence would look for a token
|
|
127
|
+
that pack does not have. `validate_counted_claims` cannot read a count whose noun is
|
|
128
|
+
"packs that declare a token", so `validate_token_population_counts` now derives both that
|
|
129
|
+
figure and the `@role non-text:` population from the token layers, and refuses a pack
|
|
130
|
+
that declares neither an `--accent` nor an `@role accent:` marker. The same sweep found
|
|
131
|
+
`SKILL.md` still saying "the twenty-nine".
|
|
132
|
+
|
|
133
|
+
### The scenario that produced all of this, and the half of it that did not run
|
|
134
|
+
|
|
135
|
+
`T34` is the behavioural scenario shipped with `deskmate`, and 1.52.0 is the first
|
|
136
|
+
release where one of these branches was actually run rather than filed. **`T34a`
|
|
137
|
+
passed**: it routed to the pack, quoted the deciding clause, rejected `tenor` on the
|
|
138
|
+
clause that rules it out, and stayed inside the bundle directory. It then did the half
|
|
139
|
+
these scenarios have always asked for and never exercised — read the chosen pack in full
|
|
140
|
+
and report defects with quotes — and returned nine, eight of which are fixed above.
|
|
141
|
+
|
|
142
|
+
**`T34b`, the negative branch, terminated on an account spend limit before reporting a
|
|
143
|
+
verdict, and is not counted as a result.** A positive-only pass cannot detect the failure
|
|
144
|
+
that branch exists to detect. `test/scenarios.md` records both outcomes.
|
|
145
|
+
|
|
146
|
+
### Ratchets
|
|
147
|
+
|
|
148
|
+
`validate.py` 5047 → 5060, `validate_palette.py` 3013 → 3023, `computed_at_least`
|
|
149
|
+
686 → 691. Thirteen of the first delta are the new gate.
|
|
150
|
+
|
|
9
151
|
## [1.51.1] - 2026-08-27
|
|
10
152
|
|
|
11
153
|
### `deskmate`, the thirty-sixth pack — a colleague, quoted
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ problem — invented colors, six accent hues, dark mode retrofitted later.
|
|
|
31
31
|
|
|
32
32
|
This skill is the taste layer. It gives a coding agent **one motion
|
|
33
33
|
methodology** for cinematic, scroll-driven pages, **a motion doctrine** that
|
|
34
|
-
decides whether to animate before it decides how, and **thirty-
|
|
34
|
+
decides whether to animate before it decides how, and **thirty-seven locked style
|
|
35
35
|
packs** with ready-made design tokens, so what it builds reads as one system
|
|
36
36
|
instead of a pile of effects.
|
|
37
37
|
|
|
@@ -76,6 +76,7 @@ into the cinematic layer, and says so in its own *Motion flavor* section.
|
|
|
76
76
|
| `rimlight` | a white field with a cool grey act separator and one near-black act, a grotesque for every sentence and a **monospace for every piece of chrome**, square on 84% of its elements, tracked negative at every size and with **no bold anywhere** — and an elevation made of **coloured light**: a sixteen-layer rig, six layers lit and ten held at alpha 0, thrown from below-left onto one control per viewport | **a studio's own front door and the pages that sell what it makes** — design and engineering agencies, product studios, service and case-study pages (standalone) |
|
|
77
77
|
| `onionskin` | a white technical sheet at **96.5% zero radius** — the squarest page in the library — where **two bases do all the work and everything quiet is one of them at an alpha**: text dims through the ink, structure through a navy that is never a word, so there is no grey ramp at all. A dot grid, dashed hairlines, three faces with one job each, and an **11px working size** | **developer and AI infrastructure whose front page is a working document** — memory and context engines, retrieval services, agent runtimes, evaluation and observability surfaces (standalone) |
|
|
78
78
|
| `deskmate` | a warm beige working day lit from **one source above the top edge** — every gradient origin in the reference sits at or above `y=0` — where a single four-stop ramp (peach, lilac, violet, deep navy) washes the field, fills a panel and fills one word of a heading, and everything a hand touches is a 56px pill against 32px slabs | **products sold as a colleague rather than a tool** — AI employees and chat-native agents, assistants living in Slack or Teams, delegation and approval surfaces (standalone) |
|
|
79
|
+
| `test-drive` | warm paper and white cards where **the live product runs inside drawn browser chrome** — traffic-light dots, a real address, the engine on — one coral in two tokens (the brand hue lights, fills and blinks; a darker step carries every body-size word), every control lit by a four-layer shadow in its own hue, a handwritten face and a yellow marker annotating from the margin | **self-serve SaaS sold by handing over the running product** — analytics, dashboards, developer tools with a visible console, indie SaaS (standalone) |
|
|
79
80
|
| `outrank` | white field with one violet that carries text in both directions, a 5px light ring standing in for a button shadow, and two type families split by how long a thing is read | SEO and growth SaaS, agent-run back-office — the pack for a product that ships a landing and a dashboard at once |
|
|
80
81
|
| `orchard` | warm oat field of rounded slabs, sage brand + one candy-orange action, rounded geometric display, soft-3D pills built from inset light | friendly consumer biotech, DTC wellness, testing kits & supplements |
|
|
81
82
|
| `field-notes` | warm green-cast paper ruled by hairlines, one rust accent, a hero that dissolves into the page instead of ending, numbered mono eyebrows, crop marks, colour that encodes how a claim is known | open-source & developer tools sold on auditability — code intelligence, provenance, evals, agent memory |
|
|
@@ -176,7 +177,7 @@ skills.
|
|
|
176
177
|
| `DESIGN_SYNC_BRIDGE.md` | The Claude Design contract: what a pack sends to claude.ai/design and in what shape, the rule for each of the four reference types, and the border motion does not cross |
|
|
177
178
|
| `FIGMA_BRIDGE.md` | The design↔code contract: how a pack's tokens map onto Figma variable collections and modes, how to implement a design without importing raw values, and what cannot cross the border |
|
|
178
179
|
| `AI_PRODUCT_PATTERNS.md` | The surfaces a model drives: the five states of a call, streaming instead of spinners, latency, provenance and uncertainty, agent confirmations, and the bans that keep it honest |
|
|
179
|
-
| `styles/*.md` | The thirty-
|
|
180
|
+
| `styles/*.md` | The thirty-seven style packs — palette, type, texture, motion tokens, motifs, bans, and the traps each one carries |
|
|
180
181
|
| `styles/tokens/*.css` | The ready-made token layer per pack, copied verbatim instead of transcribed (`workbench` and `field-notes` each ship a light `:root` plus a `data-theme="dark"` twin) |
|
|
181
182
|
| `styles/STYLE_PACK_TEMPLATE.md` | The pack contract as a skeleton, so a new style is authored against the same headings rather than improvised |
|
|
182
183
|
|
|
@@ -247,7 +248,7 @@ cd ./ds-workbench && npm install && npm run build
|
|
|
247
248
|
then `/design-sync` in that directory, from Claude Code. Three layers cross: the
|
|
248
249
|
pack's **bans** as the design system's own README, `styles.css` built from
|
|
249
250
|
`tokens/<pack>.css` verbatim, and the components — a six-name spine that is
|
|
250
|
-
identical in all thirty-
|
|
251
|
+
identical in all thirty-seven kits, so switching packs swaps identity rather than API,
|
|
251
252
|
plus each pack's signature parts. **Motion does not cross**, exactly as it does
|
|
252
253
|
not cross into Figma: a kit is the static half of a pack, and saying so is what
|
|
253
254
|
stops an agent inventing motion to fill the silence.
|
|
@@ -297,7 +298,7 @@ a pack's four widened sections used to make two gates *quieter* and still green.
|
|
|
297
298
|
One honest limit: the npx installer is checked by asserting its runtime bundle
|
|
298
299
|
walker exists, not by reading a file list — it has none by design. What proves
|
|
299
300
|
it ships the right files is CI, which installs the bundle through **both**
|
|
300
|
-
installers and `diff -r`s the result against the source, then builds all thirty-
|
|
301
|
+
installers and `diff -r`s the result against the source, then builds all thirty-seven
|
|
301
302
|
kits.
|
|
302
303
|
|
|
303
304
|
`test/scenarios.md` (T1–T34) is the behavioral harness: fresh subagents given a
|
package/bin/cli.js
CHANGED
|
@@ -234,7 +234,7 @@ ${c("bold", "What it installs")}
|
|
|
234
234
|
DESIGN_SYNC_BRIDGE.md the Claude Design contract (what a pack sends, and
|
|
235
235
|
what does not cross)
|
|
236
236
|
AI_PRODUCT_PATTERNS.md chat / agent / streaming surfaces (honest state)
|
|
237
|
-
styles/ thirty-
|
|
237
|
+
styles/ thirty-seven style packs — instrument-console (dark console),
|
|
238
238
|
editorial-luxury (warm editorial), workbench (light/dark
|
|
239
239
|
product UI), briefing-room (dark 16:9 presentation deck),
|
|
240
240
|
atrium (warm cream consumer health), patchbay (dark live
|
|
@@ -250,6 +250,10 @@ ${c("bold", "What it installs")}
|
|
|
250
250
|
size), deskmate (warm beige lit from above the top
|
|
251
251
|
edge, one four-stop ramp, 56px pills against 32px
|
|
252
252
|
slabs, and a framed transcript as the set piece),
|
|
253
|
+
test-drive (warm paper where the live product runs
|
|
254
|
+
inside drawn browser chrome, controls lit by a
|
|
255
|
+
four-layer shadow in their own hue, and a
|
|
256
|
+
handwritten hand annotating the tour),
|
|
253
257
|
babylove (white +
|
|
254
258
|
one orange, seven tokens over Tailwind defaults),
|
|
255
259
|
outrank (white +
|
|
@@ -125,6 +125,13 @@ slabs, elevation is a field step with two shadows on the whole page, and the set
|
|
|
125
125
|
piece is a framed transcript whose quoted chat client keeps its own face and colours
|
|
126
126
|
under a --quoted-* namespace, for products sold as a colleague rather than a tool:
|
|
127
127
|
AI employees and chat-native agents);
|
|
128
|
+
test-drive — warm paper and white cards where the set piece is the live product
|
|
129
|
+
running inside drawn browser chrome with traffic-light dots, one coral in two tokens
|
|
130
|
+
(the brand hue lights, fills and blinks; a darker step carries every body-size word),
|
|
131
|
+
every control lit by a four-layer shadow in its own hue, a handwritten face and a
|
|
132
|
+
yellow marker annotating from the margin, machine surfaces quarantined in their own
|
|
133
|
+
dark ladder that ignores the theme, for self-serve SaaS sold by handing over the
|
|
134
|
+
running product;
|
|
128
135
|
otherwise follow the contract below (self-contained on purpose).
|
|
129
136
|
|
|
130
137
|
## Whether to animate at all — before how
|
|
@@ -58,6 +58,13 @@
|
|
|
58
58
|
rules and it bars, and an icon that must be READ takes --ink-soft instead. */
|
|
59
59
|
--ink-faint: #9693a3;
|
|
60
60
|
--on-ink: #ffffff; /* 17.36:1 on --ink */
|
|
61
|
+
/* THE RULE THIS PACK CANNOT BE READ WITHOUT: --ink is for words on --bg, and
|
|
62
|
+
--on-surface is for words on --surface. On the light field the two are the same
|
|
63
|
+
value and the distinction looks decorative. On the dusk surface it is the whole
|
|
64
|
+
difference: --surface stays white there, measured, so a card that paints its text
|
|
65
|
+
in --ink paints white on white. Every component that sits on a card takes these. */
|
|
66
|
+
--on-surface: #1a182b; /* 17.36:1 on --surface */
|
|
67
|
+
--on-surface-soft: #716f7e; /* 4.91:1 on --surface */
|
|
61
68
|
|
|
62
69
|
/* ---- The accent: it writes, it fills, and it needed no correction ---- */
|
|
63
70
|
/* MEASURED. #6e47ff is the reference's purple-500 and its only functional accent:
|
|
@@ -121,9 +128,18 @@
|
|
|
121
128
|
/* MEASURED — `ring-3` is 3px, and the ring's alpha IS its specification: 50% behind
|
|
122
129
|
a control, 40% behind a field. Composited over white #ffffff the ring is
|
|
123
130
|
#b6a3ff at 2.17:1, which is why the control's own border moves colour in the
|
|
124
|
-
same state.
|
|
125
|
-
|
|
126
|
-
|
|
131
|
+
same state.
|
|
132
|
+
|
|
133
|
+
THE LITERAL IS HERE AND THE DERIVED FORM IS IN THE `@supports` BLOCK AT THE END OF
|
|
134
|
+
THIS FILE, and the order is not a style preference. A custom property accepts
|
|
135
|
+
almost any token sequence, so `--focus-ring: color-mix(…)` parses even where
|
|
136
|
+
`color-mix()` is unsupported and wins the cascade; the invalidity surfaces only
|
|
137
|
+
where it is substituted, as invalid-at-computed-value-time, and by then the literal
|
|
138
|
+
is gone and `var(--focus-ring)` resolves to `unset` — an INVISIBLE FOCUS RING, on
|
|
139
|
+
the one degradation this pack says it may not ship. `showroom` is the worked
|
|
140
|
+
example this copies. */
|
|
141
|
+
--focus-ring: 0 0 0 3px rgba(110, 71, 255, 0.5);
|
|
142
|
+
--focus-ring-field: 0 0 0 3px rgba(110, 71, 255, 0.4);
|
|
127
143
|
|
|
128
144
|
/* ---- Radii: a pill for the hand, a slab for the eye ----------------- */
|
|
129
145
|
/* MEASURED at 1440: 977 of 1,191 visible elements compute 0px, 52 take the 32px
|
|
@@ -160,14 +176,20 @@
|
|
|
160
176
|
--space-28: 112px; /* MEASURED — the section's own vertical rhythm */
|
|
161
177
|
|
|
162
178
|
--page-max: 90rem; /* 1440px — MEASURED */
|
|
163
|
-
|
|
164
|
-
|
|
179
|
+
/* MEASURED, and the ramp ships as four tokens rather than as a sentence: the page's
|
|
180
|
+
gutter steps 20 → 40 → 56 → 80 across the reference's own breakpoints, and a step a
|
|
181
|
+
consumer cannot reach through a variable is a step the pack did not ship. */
|
|
182
|
+
--gutter: 20px;
|
|
183
|
+
--gutter-2: 40px; /* from 40rem */
|
|
184
|
+
--gutter-3: 56px; /* from 48rem */
|
|
185
|
+
--gutter-wide: 80px; /* from 64rem, and the value at 1440 */
|
|
165
186
|
--control-h: 56px; /* MEASURED — the button and the field are the same height */
|
|
166
187
|
--control-h-sm: 40px; /* MEASURED — the navigation's own pair, and see --tap-min */
|
|
167
188
|
--control-px: 40px; /* MEASURED — 24px on the small size */
|
|
168
189
|
/* The navigation slab is not a control and does not take a control's height:
|
|
169
|
-
MEASURED at 65px with a 30px bottom radius at 1440
|
|
170
|
-
|
|
190
|
+
MEASURED at 65px with a 30px bottom radius at 1440 and 57px at the narrow width,
|
|
191
|
+
inset 40px from each side of the viewport and 12px below 40rem. That inset is the
|
|
192
|
+
SLAB's, and it is not the page's gutter — the gutter is 80px at the same width. */
|
|
171
193
|
--slab-h: 65px;
|
|
172
194
|
--slab-h-sm: 57px;
|
|
173
195
|
--r-slab: 30px;
|
|
@@ -204,6 +226,13 @@
|
|
|
204
226
|
--t-display-mid: 4.5rem; /* 72px from 40rem */
|
|
205
227
|
--t-display-sm: 4rem; /* 64px below 40rem */
|
|
206
228
|
|
|
229
|
+
/* The reference holds its lede in a grid column and sets `max-width: none` on both
|
|
230
|
+
the headline and the paragraph, so these two are a PACK DECISION rather than a
|
|
231
|
+
measurement: the measure the reference implies, stated in `ch` so it survives the
|
|
232
|
+
face substitution below. */
|
|
233
|
+
--measure-lede: 62ch;
|
|
234
|
+
--measure-body: 68ch;
|
|
235
|
+
|
|
207
236
|
--lh-display: 1.1; /* MEASURED — 88px on 80px */
|
|
208
237
|
--lh-body: 1.4; /* MEASURED — 22.4px on 16px */
|
|
209
238
|
--lh-ui: 1.5;
|
|
@@ -230,7 +259,12 @@
|
|
|
230
259
|
--dur-fast: 0.15s; /* a colour, a border or an opacity */
|
|
231
260
|
--dur-base: 0.2s; /* MEASURED — 23 elements */
|
|
232
261
|
--dur-slow: 0.3s; /* MEASURED — 9 elements, a disclosure opening */
|
|
233
|
-
|
|
262
|
+
/* MEASURED, and the two halves of the measurement disagree by 60ms: the reference
|
|
263
|
+
DECLARES `--enter-duration` as .6s, .64s and .68s across three sections, while the
|
|
264
|
+
transition on the 19 entering elements COMPUTES 0.7s. The pack ships the declared
|
|
265
|
+
middle value, because that is the number the reference's own author chose and the
|
|
266
|
+
0.7s is one section's instance of it. */
|
|
267
|
+
--dur-enter: 0.64s;
|
|
234
268
|
--stagger: 60ms; /* MEASURED — its enter-delay steps 0, 40, 60, 80, 120ms */
|
|
235
269
|
--enter-y: 16px; /* MEASURED — the entrance travels 8px or 16px, never further */
|
|
236
270
|
|
|
@@ -294,6 +328,10 @@
|
|
|
294
328
|
a muted icon here anyway, because its role is set by the light block. */
|
|
295
329
|
--ink-faint: #9693a3;
|
|
296
330
|
--on-ink: #150079;
|
|
331
|
+
/* A card on this surface stays WHITE — that is the measurement — so these two do NOT
|
|
332
|
+
invert with the field. They are the light block's values, and that is the point. */
|
|
333
|
+
--on-surface: #1a182b; /* 17.36:1 on --surface */
|
|
334
|
+
--on-surface-soft: #716f7e; /* 4.91:1 on --surface */
|
|
297
335
|
|
|
298
336
|
--accent: #d2c6ff; /* 10.14:1 on --bg — SELECTED, the reference's own on-dusk eyebrow */
|
|
299
337
|
--on-accent: #150079; /* 10.14:1 on --accent */
|
|
@@ -307,8 +345,12 @@
|
|
|
307
345
|
--hairline-quiet: color-mix(in srgb, #ffffff 15%, var(--bg));
|
|
308
346
|
|
|
309
347
|
--focus-color: #bcaaff; /* 7.90:1 on --bg, over the 3:1 mark floor */
|
|
310
|
-
|
|
311
|
-
|
|
348
|
+
/* MEASURED — the reference's on-dusk focus outline is its purple-400, and it is a
|
|
349
|
+
token here so the ring below derives from something rather than from a loose hex.
|
|
350
|
+
Literal first, derived in the `@supports` block, for the reason stated above. */
|
|
351
|
+
--focus-ring-base: #8b6cff;
|
|
352
|
+
--focus-ring: 0 0 0 3px rgba(139, 108, 255, 0.5);
|
|
353
|
+
--focus-ring-field: 0 0 0 3px rgba(139, 108, 255, 0.4);
|
|
312
354
|
--gradient-word-fallback: #d2c6ff; /* 10.14:1 on --bg */
|
|
313
355
|
|
|
314
356
|
/* DERIVED, and remapped rather than inherited: the light set measures 2.6-4.1:1 on
|
|
@@ -343,6 +385,22 @@
|
|
|
343
385
|
}
|
|
344
386
|
}
|
|
345
387
|
|
|
388
|
+
/* THE LITERALS ABOVE ARE THE FALLBACK, AND THEY ONLY WORK FROM IN HERE. The derived
|
|
389
|
+
form tracks the accent — change `--accent` and the ring follows — which is what a
|
|
390
|
+
literal cannot do; the literal exists so that a browser without `color-mix()` still
|
|
391
|
+
paints a ring at all. Both fields get one. */
|
|
392
|
+
@supports (color: color-mix(in srgb, red, red)) {
|
|
393
|
+
:root {
|
|
394
|
+
--focus-ring: 0 0 0 3px color-mix(in srgb, var(--accent) 50%, transparent);
|
|
395
|
+
--focus-ring-field: 0 0 0 3px color-mix(in srgb, var(--accent) 40%, transparent);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
[data-surface="dusk"] {
|
|
399
|
+
--focus-ring: 0 0 0 3px color-mix(in srgb, var(--focus-ring-base) 50%, transparent);
|
|
400
|
+
--focus-ring-field: 0 0 0 3px color-mix(in srgb, var(--focus-ring-base) 40%, transparent);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
346
404
|
/* Body copy here is weight 500 on 146 nodes, and an unset `font-weight` gives 400 —
|
|
347
405
|
one step light across the whole page. The UA's own 700 for `strong` and `b` is a
|
|
348
406
|
step the other way and lands on the display's heading weight, so emphasis is pinned
|
|
@@ -367,10 +425,15 @@ b {
|
|
|
367
425
|
/* PAGE — the page's own gutter, on the element a consumer never nests: a
|
|
368
426
|
container query here would ask a component's box how wide the page is. */
|
|
369
427
|
@media (min-width: 40rem) {
|
|
370
|
-
.dm-page { padding-inline: var(--
|
|
428
|
+
.dm-page { padding-inline: var(--gutter-2); }
|
|
371
429
|
}
|
|
372
|
-
/* PAGE —
|
|
373
|
-
@media (min-width:
|
|
430
|
+
/* PAGE — the middle step. */
|
|
431
|
+
@media (min-width: 48rem) {
|
|
432
|
+
.dm-page { padding-inline: var(--gutter-3); }
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
/* PAGE — the wide step, and the value measured at 1440. */
|
|
436
|
+
@media (min-width: 64rem) {
|
|
374
437
|
.dm-page { padding-inline: var(--gutter-wide); }
|
|
375
438
|
}
|
|
376
439
|
|
|
@@ -486,15 +549,15 @@ b {
|
|
|
486
549
|
font-size: var(--t-h3);
|
|
487
550
|
font-weight: var(--weight-strong);
|
|
488
551
|
letter-spacing: var(--track-display);
|
|
489
|
-
color: var(--
|
|
552
|
+
color: var(--on-surface);
|
|
490
553
|
}
|
|
491
554
|
|
|
492
555
|
.dm-card__meta {
|
|
493
556
|
font-size: var(--t-sm);
|
|
494
|
-
color: var(--
|
|
557
|
+
color: var(--on-surface-soft);
|
|
495
558
|
}
|
|
496
559
|
|
|
497
|
-
.dm-card__body { color: var(--
|
|
560
|
+
.dm-card__body { color: var(--on-surface-soft); font-size: var(--t-body); line-height: var(--lh-body); max-width: var(--measure-body); }
|
|
498
561
|
|
|
499
562
|
/* ---- Chip ------------------------------------------------------------ */
|
|
500
563
|
.dm-chip {
|
|
@@ -508,7 +571,7 @@ b {
|
|
|
508
571
|
background-color: var(--surface);
|
|
509
572
|
font-size: var(--t-sm);
|
|
510
573
|
font-weight: var(--weight-body);
|
|
511
|
-
color: var(--
|
|
574
|
+
color: var(--on-surface);
|
|
512
575
|
transition: border-color var(--dur-fast) var(--ease);
|
|
513
576
|
}
|
|
514
577
|
|
|
@@ -617,7 +680,7 @@ b {
|
|
|
617
680
|
margin-bottom: var(--space-2);
|
|
618
681
|
font-size: var(--t-body);
|
|
619
682
|
font-weight: var(--weight-body);
|
|
620
|
-
color: var(--
|
|
683
|
+
color: var(--on-surface);
|
|
621
684
|
}
|
|
622
685
|
|
|
623
686
|
.dm-field__input {
|
|
@@ -632,11 +695,11 @@ b {
|
|
|
632
695
|
font-family: var(--font-body);
|
|
633
696
|
font-size: var(--t-body);
|
|
634
697
|
font-weight: var(--weight-regular);
|
|
635
|
-
color: var(--
|
|
698
|
+
color: var(--on-surface);
|
|
636
699
|
transition: border-color var(--dur-fast) var(--ease);
|
|
637
700
|
}
|
|
638
701
|
|
|
639
|
-
.dm-field__input::placeholder { color: var(--
|
|
702
|
+
.dm-field__input::placeholder { color: var(--on-surface-soft); }
|
|
640
703
|
|
|
641
704
|
.dm-field__input:focus-visible {
|
|
642
705
|
outline: none;
|
|
@@ -665,7 +728,7 @@ b {
|
|
|
665
728
|
font-size: var(--t-sm);
|
|
666
729
|
}
|
|
667
730
|
|
|
668
|
-
.dm-slab__brand { color: var(--
|
|
731
|
+
.dm-slab__brand { color: var(--on-surface); font-weight: var(--weight-strong); }
|
|
669
732
|
.dm-slab__nav { display: flex; gap: var(--space-2); margin-inline-end: auto; }
|
|
670
733
|
|
|
671
734
|
.dm-slab__nav a {
|
|
@@ -674,7 +737,7 @@ b {
|
|
|
674
737
|
min-height: var(--tap-min);
|
|
675
738
|
padding: var(--space-2) var(--space-3);
|
|
676
739
|
border-radius: var(--r-pill);
|
|
677
|
-
color: var(--
|
|
740
|
+
color: var(--on-surface);
|
|
678
741
|
text-decoration: none;
|
|
679
742
|
transition: background-color var(--dur-fast) var(--ease);
|
|
680
743
|
}
|
|
@@ -791,10 +854,10 @@ b {
|
|
|
791
854
|
font-size: var(--t-h3);
|
|
792
855
|
font-weight: var(--weight-strong);
|
|
793
856
|
letter-spacing: var(--track-display);
|
|
794
|
-
color: var(--
|
|
857
|
+
color: var(--on-surface);
|
|
795
858
|
}
|
|
796
859
|
|
|
797
|
-
.dm-qcard__body { color: var(--
|
|
860
|
+
.dm-qcard__body { color: var(--on-surface-soft); font-size: var(--t-body); line-height: var(--lh-body); }
|
|
798
861
|
|
|
799
862
|
/* The card's halves answer to the CARD's box, not to the screen: at 34rem of
|
|
800
863
|
container the artefact sits beside the sentence instead of under it. */
|
|
@@ -812,8 +875,8 @@ b {
|
|
|
812
875
|
text-align: center;
|
|
813
876
|
}
|
|
814
877
|
|
|
815
|
-
.dm-empty__title { margin: 0; font-size: var(--t-body); font-weight: var(--weight-body); color: var(--
|
|
816
|
-
.dm-empty__detail { margin: var(--space-2) 0 0; font-size: var(--t-body); color: var(--
|
|
878
|
+
.dm-empty__title { margin: 0; font-size: var(--t-body); font-weight: var(--weight-body); color: var(--on-surface); }
|
|
879
|
+
.dm-empty__detail { margin: var(--space-2) 0 0; font-size: var(--t-body); color: var(--on-surface-soft); }
|
|
817
880
|
.dm-empty__action { margin-top: var(--space-6); }
|
|
818
881
|
|
|
819
882
|
/* ---- Skeleton -------------------------------------------------------- */
|
|
@@ -108,8 +108,15 @@
|
|
|
108
108
|
--shadow-hair: 0 1px 0 0 color-mix(in srgb, var(--ink) 6%, transparent); /* MEASURED */
|
|
109
109
|
--shadow-lift: 0 32px 64px -24px color-mix(in srgb, var(--ink) 28%, transparent); /* MEASURED — once */
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
|
|
111
|
+
/* MEASURED, and declared LITERAL FIRST with the derived form in the `@supports` block
|
|
112
|
+
at the end of this file. The order is the guard, not a style: a custom property
|
|
113
|
+
accepts almost any token sequence, so a `color-mix()` value parses even where
|
|
114
|
+
`color-mix()` is unsupported and wins the cascade; it fails only at substitution, by
|
|
115
|
+
which point the literal is gone and `var(--focus-ring)` resolves to `unset` — an
|
|
116
|
+
invisible focus ring. Added 1.52.0; `showroom` is the pack that established the
|
|
117
|
+
mechanism and `deskmate` carries the same guard. */
|
|
118
|
+
--focus-ring: 0 0 0 4px rgba(5, 98, 239, 0.1),
|
|
119
|
+
0 4px 10px -3px rgba(5, 98, 239, 0.45);
|
|
113
120
|
--focus-w: 2px;
|
|
114
121
|
--focus-offset: 2px;
|
|
115
122
|
--focus-color: var(--accent); /* 5.25:1 on --bg, over the 3:1 mark floor */
|
|
@@ -262,6 +269,16 @@
|
|
|
262
269
|
}
|
|
263
270
|
}
|
|
264
271
|
|
|
272
|
+
/* THE LITERALS ABOVE ARE THE FALLBACK, AND THEY ONLY WORK FROM IN HERE. The derived form
|
|
273
|
+
tracks `--accent`; the literal exists so a browser without `color-mix()` still paints a
|
|
274
|
+
ring at all. The dark band inherits this ring, and its lighter accent with it. */
|
|
275
|
+
@supports (color: color-mix(in srgb, red, red)) {
|
|
276
|
+
:root {
|
|
277
|
+
--focus-ring: 0 0 0 4px color-mix(in srgb, var(--accent) 10%, transparent),
|
|
278
|
+
0 4px 10px -3px color-mix(in srgb, var(--accent) 45%, transparent);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
265
282
|
/* The pack bans bold, and a ban the UA overrides is not a ban: `strong` and `b` are 700
|
|
266
283
|
by default in every browser. 500 is the heaviest weight this page spends at scale, so
|
|
267
284
|
emphasis here is the medium weight — or, better, the mono. */
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pkg": "@sheleg-design/test-drive",
|
|
3
|
+
"globalName": "ShelegTestDrive",
|
|
4
|
+
"shape": "package",
|
|
5
|
+
"buildCmd": "npm run build",
|
|
6
|
+
"srcDir": "src",
|
|
7
|
+
"tsconfig": "tsconfig.json",
|
|
8
|
+
"cssEntry": "src/styles.css",
|
|
9
|
+
"docsDir": "src",
|
|
10
|
+
"readmeHeader": ".design-sync/conventions.md",
|
|
11
|
+
"guidelinesGlob": [
|
|
12
|
+
"guidelines/*.md"
|
|
13
|
+
]
|
|
14
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Test-drive — conventions for a design agent
|
|
2
|
+
|
|
3
|
+
This kit is the built form of the Test-drive style pack. Read these before generating
|
|
4
|
+
anything with it; they are the pack's bans, stated where a design tool will see them.
|
|
5
|
+
|
|
6
|
+
## Colour
|
|
7
|
+
|
|
8
|
+
- **One coral, two tokens.** `--accent` (#e16540) lights controls, fills bars and
|
|
9
|
+
blinks carets; it carries text only at display sizes. Every body-size coral word is
|
|
10
|
+
`--action` (#c04a28). Swapping them ships the reference's own AA failure.
|
|
11
|
+
- **The declared teal is dead.** The reference's theme names an accent it never
|
|
12
|
+
paints; nothing here may resurrect it.
|
|
13
|
+
- **Money is coral, traffic is blue** (`--chart-money`, `--chart-traffic`), and the
|
|
14
|
+
blue never carries a word.
|
|
15
|
+
- **Status is never colour alone** — a state takes the word or the glyph beside it;
|
|
16
|
+
`Delta` ships the arrow for exactly this reason.
|
|
17
|
+
|
|
18
|
+
## Geometry
|
|
19
|
+
|
|
20
|
+
- A control is 8px (`--r-control`), a card 16px (`--r-card`), the frame 20.8px
|
|
21
|
+
(`--r-frame`), the badge a pill. The frame's window is concentric:
|
|
22
|
+
`calc(var(--r-frame) - var(--frame-inset))`.
|
|
23
|
+
- The nav is 65px, static, unfrosted, in the field's own colour.
|
|
24
|
+
|
|
25
|
+
## Elevation
|
|
26
|
+
|
|
27
|
+
- A card is ringed (`--ring-card`); a control is lit (`--lit-action` /
|
|
28
|
+
`--lit-quiet`); the frame gets the one big drop (`--shadow-frame`). There is no
|
|
29
|
+
fourth shadow.
|
|
30
|
+
|
|
31
|
+
## The machine
|
|
32
|
+
|
|
33
|
+
- Terminal, CLI and agent surfaces take `--machine-*` and ignore the theme. Their
|
|
34
|
+
tokens never reach a card, and the caret never leaves them.
|
|
35
|
+
|
|
36
|
+
## Motion
|
|
37
|
+
|
|
38
|
+
- 0.2s for anything a pointer caused; press scales to 0.95 over 0.15s; demos narrate
|
|
39
|
+
themselves on double-digit clocks. Nothing is scroll-driven. Under reduced motion a
|
|
40
|
+
demo shows its final frame, not its hidden first one.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# @sheleg-design/test-drive
|
|
2
|
+
|
|
3
|
+
The React reference kit for the **Test-drive** style pack — warm paper and white cards
|
|
4
|
+
where the set piece is the live product running inside drawn browser chrome, and a
|
|
5
|
+
founder's hand annotates the tour.
|
|
6
|
+
|
|
7
|
+
The pack document is the source of truth for every value here:
|
|
8
|
+
`plugins/sheleg-design/skills/sheleg-design/styles/test-drive.md`. This kit is what
|
|
9
|
+
those values look like when they are built, and `src/styles.css` opens with the pack's
|
|
10
|
+
token layer copied byte for byte — never transcribed.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install && npm run build # tsc only; there is no bundler in this kit
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## What ships
|
|
17
|
+
|
|
18
|
+
**The spine**, identical in name, props and types across every SHELEG kit, so switching
|
|
19
|
+
packs swaps identity rather than API: `Button`, `Card`, `Chip`, `Stat`, `Heading`,
|
|
20
|
+
`Rule`.
|
|
21
|
+
|
|
22
|
+
**The signature**, this pack's own: `DemoFrame` (the browser chrome around a running
|
|
23
|
+
interior — the signature element), `Annotation` (the hand), `Marker` (the
|
|
24
|
+
highlighter), `Delta` (a vital sign's movement), `Machine` + `Caret` (the quarantined
|
|
25
|
+
terminal), `ThinkingDots` (the machine's loader), `Field` (and the `td-join` pair),
|
|
26
|
+
`NavBar`, `Empty`.
|
|
27
|
+
|
|
28
|
+
## The three rules a generator loses first
|
|
29
|
+
|
|
30
|
+
1. The coral splits: `--accent` lights, fills and blinks; `--action` carries every
|
|
31
|
+
body-size word. `#ffffff` on `#e16540` is 3.42:1 — that is why both exist.
|
|
32
|
+
2. The lit shadow belongs to controls; a card takes `--ring-card` and nothing else.
|
|
33
|
+
3. The `DemoFrame` interior runs. A screenshot inside the chrome is `showroom`'s
|
|
34
|
+
exhibit, not this pack's proof.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sheleg-design/test-drive",
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"build": "tsc -p tsconfig.json"
|
|
21
|
+
},
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"react": ">=18"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"typescript": "^5.6.0",
|
|
27
|
+
"@types/react": "^18.3.0"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Signature
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
The founder's hand: `--font-hand` (Fuzzy Bubbles) at `--t-label`, in `--ink-mute` or
|
|
6
|
+
— for an offer — `--action`. It annotates from the margin, always beside or above the
|
|
7
|
+
thing it points at. It never announces: no headings, no controls, no body copy in the
|
|
8
|
+
hand.
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
<Annotation>Interactive demo</Annotation>
|
|
12
|
+
<Annotation tone="accent">2 months free</Annotation>
|
|
13
|
+
```
|