sheleg-design-skill 1.52.0 → 1.54.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 +99 -0
- package/README.md +6 -4
- package/bin/cli.js +9 -1
- package/cursor/rules/sheleg-design.mdc +13 -0
- package/kits/surveyor/.design-sync/config.json +14 -0
- package/kits/surveyor/.design-sync/conventions.md +35 -0
- package/kits/surveyor/README.md +33 -0
- package/kits/surveyor/package.json +29 -0
- package/kits/surveyor/src/Button.md +17 -0
- package/kits/surveyor/src/Button.tsx +33 -0
- package/kits/surveyor/src/Card.md +11 -0
- package/kits/surveyor/src/Card.tsx +24 -0
- package/kits/surveyor/src/Chip.md +11 -0
- package/kits/surveyor/src/Chip.tsx +25 -0
- package/kits/surveyor/src/Closer.md +14 -0
- package/kits/surveyor/src/Closer.tsx +21 -0
- package/kits/surveyor/src/Delta.md +12 -0
- package/kits/surveyor/src/Delta.tsx +23 -0
- package/kits/surveyor/src/Dialogue.md +11 -0
- package/kits/surveyor/src/Dialogue.tsx +24 -0
- package/kits/surveyor/src/Empty.md +13 -0
- package/kits/surveyor/src/Empty.tsx +21 -0
- package/kits/surveyor/src/Field.md +12 -0
- package/kits/surveyor/src/Field.tsx +38 -0
- package/kits/surveyor/src/Heading.md +11 -0
- package/kits/surveyor/src/Heading.tsx +19 -0
- package/kits/surveyor/src/NavBar.md +14 -0
- package/kits/surveyor/src/NavBar.tsx +20 -0
- package/kits/surveyor/src/Portrait.md +11 -0
- package/kits/surveyor/src/Portrait.tsx +12 -0
- package/kits/surveyor/src/Pulse.md +11 -0
- package/kits/surveyor/src/Pulse.tsx +15 -0
- package/kits/surveyor/src/Rule.md +10 -0
- package/kits/surveyor/src/Rule.tsx +18 -0
- package/kits/surveyor/src/Stat.md +10 -0
- package/kits/surveyor/src/Stat.tsx +17 -0
- package/kits/surveyor/src/StatSlab.md +12 -0
- package/kits/surveyor/src/StatSlab.tsx +16 -0
- package/kits/surveyor/src/TintPanel.md +12 -0
- package/kits/surveyor/src/TintPanel.tsx +17 -0
- package/kits/surveyor/src/index.ts +35 -0
- package/kits/surveyor/src/styles.css +828 -0
- package/kits/surveyor/tsconfig.json +15 -0
- 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 +2 -2
- 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 +2 -2
- package/plugins/sheleg-design/skills/sheleg-design/STYLE_PACK_INDEX.md +4 -2
- package/plugins/sheleg-design/skills/sheleg-design/SURFACE_COMPOSITION.md +5 -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/scoreboard.md +6 -1
- package/plugins/sheleg-design/skills/sheleg-design/styles/showroom.md +10 -1
- package/plugins/sheleg-design/skills/sheleg-design/styles/surveyor.md +402 -0
- package/plugins/sheleg-design/skills/sheleg-design/styles/tenor.md +1 -1
- package/plugins/sheleg-design/skills/sheleg-design/styles/test-drive.md +457 -0
- package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/surveyor.css +285 -0
- package/plugins/sheleg-design/skills/sheleg-design/styles/tokens/test-drive.css +389 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,105 @@ follow [SemVer](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [1.54.0] - 2026-08-29
|
|
10
|
+
|
|
11
|
+
### The thirty-eighth pack — the terrain is mapped
|
|
12
|
+
|
|
13
|
+
**`surveyor`**, extracted from an AI-visibility tracker's front page and named per
|
|
14
|
+
ADR-0001 for the register it encodes: a page that sells a survey of terrain the
|
|
15
|
+
buyer cannot see — contour lines for texture, counted stat slabs for readings, and
|
|
16
|
+
the product appearing only as flat portraits.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- `styles/surveyor.md` — widened, all thirteen headings; `Themes: light only`;
|
|
21
|
+
`Rank: unordered — 3 status role(s)`, and the missing warn is a stated decision
|
|
22
|
+
rather than a gap: the authored palette ships no amber, and one invented from the
|
|
23
|
+
WordPress vendor presets would be the exact rule-7 trap. Two forks written from
|
|
24
|
+
both sides: against `test-drive` (a flat portrait against a running machine on
|
|
25
|
+
the same warm paper) and against `showroom` (a field survey pinned flat against
|
|
26
|
+
one lit museum specimen).
|
|
27
|
+
- `styles/tokens/surveyor.css` — the authored layer dug out of a WordPress site:
|
|
28
|
+
SE Ranking's own `se-uikit` tokens verified against the render, with the vendor
|
|
29
|
+
preset `:root` (a full palette that paints nothing) left behind. The corrections
|
|
30
|
+
climb the reference's own ladder: its CTA label measures `#ffffff` on `#0d9488`
|
|
31
|
+
at 3.74:1, so the hover step `#0a7269` becomes the text-bearing `--action` and
|
|
32
|
+
the brand teal keeps large-only jobs; the pink that answers (`#ff91da`, 1.84:1)
|
|
33
|
+
gains a speaking step `--pink-deep` `#a83f88` at 5.32:1. The page's elevation
|
|
34
|
+
model is recorded as measured: box-shadow none everywhere except the nav after
|
|
35
|
+
it detaches on scroll.
|
|
36
|
+
- `kits/surveyor/` — the six-name spine plus `StatSlab`, `Delta`, `Portrait`,
|
|
37
|
+
`TintPanel`, `Closer`, `Dialogue`, `Pulse`, `Field`, `NavBar`, `Empty`. The
|
|
38
|
+
contour terrain ships as a CSS technique (`repeating-radial-gradient` rings)
|
|
39
|
+
over the three measured line inks, because a PNG asset cannot live in a token
|
|
40
|
+
layer.
|
|
41
|
+
- `test/scenarios.md` T36 — `surveyor` against `test-drive`, the warm-paper
|
|
42
|
+
analytics-landing fork, with its negative branch per standing instruction 4.
|
|
43
|
+
- ADR-0001 gains its fifteenth application: `surveyor`, with `contour`, `atlas`,
|
|
44
|
+
`heatmap`/`benchmark` and `field-survey` weighed and rejected.
|
|
45
|
+
|
|
46
|
+
### Changed
|
|
47
|
+
|
|
48
|
+
- `test-drive` and `showroom` each gain the reciprocal fork clause naming
|
|
49
|
+
`surveyor`.
|
|
50
|
+
- Counted claims moved with the tree: thirty-eight packs and kits across
|
|
51
|
+
`SKILL.md`, the index (six core / thirty-two widened), `SURFACE_COMPOSITION.md`
|
|
52
|
+
(the accent is `--accent` in 35 of the 38; twenty-five layers carry a
|
|
53
|
+
non-text role), `FIGMA_BRIDGE.md` (twelve of the thirty-eight ship a twin),
|
|
54
|
+
the template's theme split (12/17/9), README, DOCMAP, both installers and all
|
|
55
|
+
three manifests.
|
|
56
|
+
|
|
57
|
+
## [1.53.0] - 2026-08-27
|
|
58
|
+
|
|
59
|
+
### The thirty-seventh pack — the visitor is handed the keys
|
|
60
|
+
|
|
61
|
+
**`test-drive`**, extracted from a revenue-analytics product's front page and named per
|
|
62
|
+
ADR-0001 for the register it encodes: a page that sells by handing over the running
|
|
63
|
+
product — the set piece is the live app inside drawn browser chrome, and a founder's
|
|
64
|
+
hand (a script face, a yellow marker, a drawn arrow) annotates the tour.
|
|
65
|
+
|
|
66
|
+
### Added
|
|
67
|
+
|
|
68
|
+
- `styles/test-drive.md` — widened, all thirteen headings; `Themes: light + dark — a
|
|
69
|
+
full theme twin`; three forks written from both sides: against `datasheet` (whose
|
|
70
|
+
live instrument reads *the visitor*, where this one hands over *the product's own
|
|
71
|
+
workspace*), against `showroom` (a still exhibit against a running machine), and
|
|
72
|
+
against `scoreboard` (one public total against a dashboard's vital signs on the
|
|
73
|
+
same warm paper and orange-red family).
|
|
74
|
+
- `styles/tokens/test-drive.css` — measured off the render, not the stylesheet, and
|
|
75
|
+
the reference is the trap the skeleton's rule 7 describes: its DaisyUI theme
|
|
76
|
+
declares a teal accent that paints **nothing** (the area-weighted census found it
|
|
77
|
+
on zero elements), so the acting coral is the brand and the teal ships nowhere.
|
|
78
|
+
The coral splits into two tokens because the reference's own CTA fails AA —
|
|
79
|
+
`#ffffff` on `#e16540` is 3.42:1 — so `--accent` lights, fills and blinks while
|
|
80
|
+
`--action` `#c04a28` carries every body-size word at 4.94:1 under white. The lit
|
|
81
|
+
control recipe (contact shadow, hue ring, glow, inner bevel) is read byte-for-byte
|
|
82
|
+
out of the reference's authored `.btn-primary`/`.btn-simple` classes, in both
|
|
83
|
+
themes. The machine ladder (`--machine-*`, `#101010`–`#202020`) is quarantined and
|
|
84
|
+
ignores the theme.
|
|
85
|
+
- `kits/test-drive/` — the six-name spine plus `DemoFrame`, `Annotation`, `Marker`,
|
|
86
|
+
`Delta`, `Machine`+`Caret`, `ThinkingDots`, `Field`, `NavBar`, `Empty`. Rendered at
|
|
87
|
+
1440, 768 and an emulated 390 before shipping (CONTRIBUTING step 8): the render
|
|
88
|
+
caught the nav computing 66px against a stated 65 (a content-box border), the link
|
|
89
|
+
row overflowing a 390px page at 428px, and the touch floor missing — all three
|
|
90
|
+
fixed pre-tag. The stat row is a container (`container-type: inline-size`),
|
|
91
|
+
stepping 2 → 4 → 7 columns by its own width.
|
|
92
|
+
- `test/scenarios.md` T35 — `test-drive` against `datasheet`, the live-instrument
|
|
93
|
+
fork, with its negative branch per standing instruction 4.
|
|
94
|
+
- ADR-0001 gains its fourteenth application: `test-drive`, with `showfloor`,
|
|
95
|
+
`sandbox`, `marginalia` and `demo-day` weighed and rejected on the ADR's own
|
|
96
|
+
criteria.
|
|
97
|
+
|
|
98
|
+
### Changed
|
|
99
|
+
|
|
100
|
+
- `datasheet`, `showroom`, `scoreboard` — each gains the reciprocal fork clause
|
|
101
|
+
naming `test-drive`.
|
|
102
|
+
- Counted claims moved with the tree: thirty-seven packs and kits across `SKILL.md`,
|
|
103
|
+
the index, `SURFACE_COMPOSITION.md` (the accent is `--accent` in 34 of the 37),
|
|
104
|
+
`FIGMA_BRIDGE.md` (twelve of the thirty-seven ship a twin), `MOBILE_SURFACES.md`,
|
|
105
|
+
`DESIGN_SYNC_BRIDGE.md`, the template's theme split (12/16/9), README, DOCMAP,
|
|
106
|
+
both installers and all three manifests.
|
|
107
|
+
|
|
9
108
|
## [1.52.0] - 2026-08-27
|
|
10
109
|
|
|
11
110
|
### The front door is the designs
|
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-eight 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,8 @@ 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) |
|
|
80
|
+
| `surveyor` | peach paper where **an unseen terrain is mapped** — fine contour lines as the one texture, flat white and tinted cards with no shadow anywhere, a teal whose text-bearing steps are the reference's own hover ladder, a pink that answers but may not speak, and the product appearing only as flat portraits | **visibility, monitoring and benchmark tools** — AI-search and SEO trackers, share-of-voice and brand-listening platforms sold to marketing teams (standalone) |
|
|
79
81
|
| `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
82
|
| `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
83
|
| `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 +178,7 @@ skills.
|
|
|
176
178
|
| `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
179
|
| `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
180
|
| `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-
|
|
181
|
+
| `styles/*.md` | The thirty-eight style packs — palette, type, texture, motion tokens, motifs, bans, and the traps each one carries |
|
|
180
182
|
| `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
183
|
| `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
184
|
|
|
@@ -247,7 +249,7 @@ cd ./ds-workbench && npm install && npm run build
|
|
|
247
249
|
then `/design-sync` in that directory, from Claude Code. Three layers cross: the
|
|
248
250
|
pack's **bans** as the design system's own README, `styles.css` built from
|
|
249
251
|
`tokens/<pack>.css` verbatim, and the components — a six-name spine that is
|
|
250
|
-
identical in all thirty-
|
|
252
|
+
identical in all thirty-eight kits, so switching packs swaps identity rather than API,
|
|
251
253
|
plus each pack's signature parts. **Motion does not cross**, exactly as it does
|
|
252
254
|
not cross into Figma: a kit is the static half of a pack, and saying so is what
|
|
253
255
|
stops an agent inventing motion to fill the silence.
|
|
@@ -297,7 +299,7 @@ a pack's four widened sections used to make two gates *quieter* and still green.
|
|
|
297
299
|
One honest limit: the npx installer is checked by asserting its runtime bundle
|
|
298
300
|
walker exists, not by reading a file list — it has none by design. What proves
|
|
299
301
|
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-
|
|
302
|
+
installers and `diff -r`s the result against the source, then builds all thirty-eight
|
|
301
303
|
kits.
|
|
302
304
|
|
|
303
305
|
`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-eight 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,14 @@ ${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),
|
|
257
|
+
surveyor (peach paper mapping unseen terrain in
|
|
258
|
+
contour lines, flat shadowless cards, a teal that
|
|
259
|
+
states and a pink that answers, and the product
|
|
260
|
+
shown only as portraits),
|
|
253
261
|
babylove (white +
|
|
254
262
|
one orange, seven tokens over Tailwind defaults),
|
|
255
263
|
outrank (white +
|
|
@@ -125,6 +125,19 @@ 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;
|
|
135
|
+
surveyor — warm peach paper where an unseen terrain is mapped: fine contour lines as
|
|
136
|
+
the single texture, flat white and tinted cards with no shadow anywhere but the
|
|
137
|
+
detached nav, one teal whose text-bearing steps climb the reference's own hover
|
|
138
|
+
ladder, a pink that answers but may not speak, TT Fors at a 600 ceiling with tabular
|
|
139
|
+
numerals, and the product shown only as flat portraits, for visibility, monitoring
|
|
140
|
+
and benchmark tools sold to marketing teams;
|
|
128
141
|
otherwise follow the contract below (self-contained on purpose).
|
|
129
142
|
|
|
130
143
|
## Whether to animate at all — before how
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"pkg": "@sheleg-design/surveyor",
|
|
3
|
+
"globalName": "ShelegSurveyor",
|
|
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,35 @@
|
|
|
1
|
+
# Surveyor — conventions for a design agent
|
|
2
|
+
|
|
3
|
+
This kit is the built form of the Surveyor 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
|
+
- **The teal is a ladder and the roles are shifted one step down**: `--action`
|
|
9
|
+
(#0a7269) carries every word and text-bearing fill; `--accent` (#0d9488) is
|
|
10
|
+
large-only — stat figures, marks, the Q glyph. White body copy on #0d9488 (3.74:1)
|
|
11
|
+
is the reference's recorded failure; do not restore it.
|
|
12
|
+
- **The pink never speaks at `--pink`** (1.84:1 on the field): glyphs, series and
|
|
13
|
+
tints only. A pink word is `--pink-deep`.
|
|
14
|
+
- **Tense as tint**: mint = shipping, pink = coming. Swapping them lies.
|
|
15
|
+
- **Three statuses, no warn** — an amber here would be an invented value.
|
|
16
|
+
|
|
17
|
+
## Geometry
|
|
18
|
+
|
|
19
|
+
- Controls 10px, cards 24px, panels 32px, badges 6px, pill 99px. The corpus's 20
|
|
20
|
+
and 12 are nested instances (24−4, 20−8), never free values.
|
|
21
|
+
- Nothing is bolder than 600, and the heading tracking RELAXES at narrow widths.
|
|
22
|
+
|
|
23
|
+
## Elevation
|
|
24
|
+
|
|
25
|
+
- Flat. White/mint/pink tints on peach are the whole depth. The one shadow is the
|
|
26
|
+
detached nav's, toggled on scroll.
|
|
27
|
+
|
|
28
|
+
## Proof
|
|
29
|
+
|
|
30
|
+
- The product appears as `Portrait` — a flat still. No browser chrome, no
|
|
31
|
+
spotlight, no animation inside the image.
|
|
32
|
+
|
|
33
|
+
## Motion
|
|
34
|
+
|
|
35
|
+
- One 0.2s clock and one pulse ring. Nothing moves, lifts, scales or scrolls.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# @sheleg-design/surveyor
|
|
2
|
+
|
|
3
|
+
The React reference kit for the **Surveyor** style pack — warm peach paper where an
|
|
4
|
+
unseen terrain is mapped: contour lines for texture, flat portraits for proof, a teal
|
|
5
|
+
that states and a pink that answers.
|
|
6
|
+
|
|
7
|
+
The pack document is the source of truth for every value here:
|
|
8
|
+
`plugins/sheleg-design/skills/sheleg-design/styles/surveyor.md`. This kit is what
|
|
9
|
+
those values look like when they are built, and `src/styles.css` opens with the
|
|
10
|
+
pack's 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: `Button`,
|
|
19
|
+
`Card`, `Chip`, `Stat`, `Heading`, `Rule`.
|
|
20
|
+
|
|
21
|
+
**The signature**: `StatSlab` (the counted reading in the working hue), `Delta` (a
|
|
22
|
+
reading's movement, arrow included), `Portrait` (the flat still), `TintPanel` (tense
|
|
23
|
+
as tint), `Closer` (the one dark slab — the signature element), `Dialogue` (the
|
|
24
|
+
teal-Q/pink-A pair), `Pulse` (the one loop), `Field`, `NavBar`, `Empty`.
|
|
25
|
+
|
|
26
|
+
## The three rules a generator loses first
|
|
27
|
+
|
|
28
|
+
1. The page is flat: no shadow on anything but the detached nav, and elevation is a
|
|
29
|
+
tint. A `shadow-md` is a foreign object.
|
|
30
|
+
2. The teal ladder is shifted for AA: `--action` `#0a7269` writes and fills;
|
|
31
|
+
`--accent` `#0d9488` is large-only (`#ffffff` on it is 3.74:1).
|
|
32
|
+
3. The pink answers, it does not speak: `--pink` for glyphs and tints beside
|
|
33
|
+
readable ink, `--pink-deep` when pink must carry a word.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@sheleg-design/surveyor",
|
|
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,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Actions
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
One height (`--control-h`, 48px: 12×24 padding on 16px/500) at `--r-control`, and a
|
|
6
|
+
fill that only ever changes colour — no shadow, no scale, no travel. `primary` rests
|
|
7
|
+
on `--action` (the reference's own hover step, promoted for AA: `#ffffff` on
|
|
8
|
+
`#0a7269` is 5.79:1) and hovers to `--action-hover`. `secondary` is the measured
|
|
9
|
+
outline: transparent on the field with a 1px `--ink` border. `ghost` tints `--mint`
|
|
10
|
+
on hover. Disabled keeps the reference's own literal pair.
|
|
11
|
+
|
|
12
|
+
Focus is the pack's correction: the fill step **and** a 2px `--focus-color` outline.
|
|
13
|
+
|
|
14
|
+
```tsx
|
|
15
|
+
<Button>Start free trial</Button>
|
|
16
|
+
<Button variant="secondary">Book a demo</Button>
|
|
17
|
+
```
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface ButtonProps {
|
|
4
|
+
/** `primary` is the accent fill — at most one per view. */
|
|
5
|
+
variant?: 'primary' | 'secondary' | 'ghost';
|
|
6
|
+
size?: 'sm' | 'md' | 'lg';
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
onClick?: () => void;
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function Button({
|
|
14
|
+
variant = 'primary',
|
|
15
|
+
size = 'md',
|
|
16
|
+
disabled = false,
|
|
17
|
+
onClick,
|
|
18
|
+
children,
|
|
19
|
+
className,
|
|
20
|
+
}: ButtonProps) {
|
|
21
|
+
return (
|
|
22
|
+
<button
|
|
23
|
+
type="button"
|
|
24
|
+
className={['sv-btn', `sv-btn--${variant}`, `sv-btn--${size}`, className]
|
|
25
|
+
.filter(Boolean)
|
|
26
|
+
.join(' ')}
|
|
27
|
+
disabled={disabled}
|
|
28
|
+
onClick={onClick}
|
|
29
|
+
>
|
|
30
|
+
{children}
|
|
31
|
+
</button>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Surfaces
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
A card is `--surface` at `--r-card` (24px) with 24px padding and **nothing else** —
|
|
6
|
+
no border, no shadow, no hover. Elevation on this page is a tint, and the one drop
|
|
7
|
+
shadow belongs to the detached nav.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
<Card title="Business owners">…</Card>
|
|
11
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface CardProps {
|
|
4
|
+
title?: string;
|
|
5
|
+
/** Right-aligned metadata on the title row: a count, an id, a timestamp. */
|
|
6
|
+
meta?: string;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function Card({ title, meta, children, className }: CardProps) {
|
|
12
|
+
const head = title !== undefined || meta !== undefined;
|
|
13
|
+
return (
|
|
14
|
+
<section className={['sv-card', className].filter(Boolean).join(' ')}>
|
|
15
|
+
{head && (
|
|
16
|
+
<div className="sv-card__head">
|
|
17
|
+
{title !== undefined && <h3 className="sv-card__title">{title}</h3>}
|
|
18
|
+
{meta !== undefined && <span className="sv-card__meta">{meta}</span>}
|
|
19
|
+
</div>
|
|
20
|
+
)}
|
|
21
|
+
<div className="sv-card__body">{children}</div>
|
|
22
|
+
</section>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Data
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
A 6px-radius badge in a tense tint: default is `--mint` with `--action` text
|
|
6
|
+
("Coming soon" ships mint in the reference), `accent` is `--pink-wash` with
|
|
7
|
+
`--pink-deep`. A chip never carries a status alone — `Delta` does states.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
<Chip>Coming soon</Chip>
|
|
11
|
+
```
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface ChipProps {
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
selected?: boolean;
|
|
6
|
+
tone?: 'neutral' | 'accent';
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Chip({ children, selected = false, tone = 'neutral', className }: ChipProps) {
|
|
11
|
+
return (
|
|
12
|
+
<span
|
|
13
|
+
className={[
|
|
14
|
+
'sv-chip',
|
|
15
|
+
`sv-chip--${tone}`,
|
|
16
|
+
selected ? 'sv-chip--selected' : undefined,
|
|
17
|
+
className,
|
|
18
|
+
]
|
|
19
|
+
.filter(Boolean)
|
|
20
|
+
.join(' ')}
|
|
21
|
+
>
|
|
22
|
+
{children}
|
|
23
|
+
</span>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Signature
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
**The signature element.** The page's only dark object: an `--accent` slab at
|
|
6
|
+
`--r-panel` with two white contour origins bleeding off its edges, a white heading
|
|
7
|
+
(3.74:1 — legal at heading sizes only, which is why `support` renders at the
|
|
8
|
+
24px question size and never body), and one white outline control. One per page;
|
|
9
|
+
a second closer has spent the device twice and broken it both times.
|
|
10
|
+
|
|
11
|
+
```tsx
|
|
12
|
+
<Closer title="Need a custom plan?" support="Contact our team."
|
|
13
|
+
action={<Button variant="secondary">Book a demo</Button>} />
|
|
14
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface CloserProps {
|
|
4
|
+
/** The heading — white on the brand teal is legal at heading sizes only. */
|
|
5
|
+
title: string;
|
|
6
|
+
/** One line of support copy, kept at heading scale. */
|
|
7
|
+
support?: string;
|
|
8
|
+
/** One white outline control. */
|
|
9
|
+
action: ReactNode;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function Closer({ title, support, action, className }: CloserProps) {
|
|
14
|
+
return (
|
|
15
|
+
<section className={['sv-closer', className].filter(Boolean).join(' ')}>
|
|
16
|
+
<h2 className="sv-closer__title">{title}</h2>
|
|
17
|
+
{support !== undefined && <p className="sv-closer__support">{support}</p>}
|
|
18
|
+
<span className="sv-closer__action">{action}</span>
|
|
19
|
+
</section>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Signature
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
A reading's movement: number first, arrow second, hue third. Rising takes the
|
|
6
|
+
action family; falling takes `--pink-deep` — the *speaking* pink at 5.32:1, never
|
|
7
|
+
the glyph pink. The arrow ships inside the component because status is never
|
|
8
|
+
colour alone.
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
<Delta direction="down">1,3</Delta>
|
|
12
|
+
```
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface DeltaProps {
|
|
4
|
+
/** The arrow is the second encoding; the number beside it is the first. */
|
|
5
|
+
direction: 'up' | 'down';
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Delta({ direction, children, className }: DeltaProps) {
|
|
11
|
+
return (
|
|
12
|
+
<span
|
|
13
|
+
className={['sv-delta', `sv-delta--${direction}`, className]
|
|
14
|
+
.filter(Boolean)
|
|
15
|
+
.join(' ')}
|
|
16
|
+
>
|
|
17
|
+
{children}
|
|
18
|
+
<span aria-hidden="true" className="sv-delta__arrow">
|
|
19
|
+
{direction === 'up' ? '\u2191' : '\u2193'}
|
|
20
|
+
</span>
|
|
21
|
+
</span>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Signature
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
The two voices: a teal Q glyph beside the question, a pink A glyph beside the
|
|
6
|
+
answer. The glyphs carry the voice; the words stay in ink — `--pink` measures
|
|
7
|
+
1.84:1 on the field, which is exactly why the glyph is never the only carrier.
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
<Dialogue question="Which AI systems does it monitor?">ChatGPT, Gemini…</Dialogue>
|
|
11
|
+
```
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface DialogueProps {
|
|
4
|
+
/** The teal Q glyph and the question. */
|
|
5
|
+
question: string;
|
|
6
|
+
/** The pink A glyph and the answer body. */
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function Dialogue({ question, children, className }: DialogueProps) {
|
|
12
|
+
return (
|
|
13
|
+
<div className={['sv-dialogue', className].filter(Boolean).join(' ')}>
|
|
14
|
+
<div className="sv-dialogue__q">
|
|
15
|
+
<span className="sv-dialogue__glyph sv-dialogue__glyph--q" aria-hidden="true">Q</span>
|
|
16
|
+
<h3 className="sv-dialogue__question">{question}</h3>
|
|
17
|
+
</div>
|
|
18
|
+
<div className="sv-dialogue__a">
|
|
19
|
+
<span className="sv-dialogue__glyph sv-dialogue__glyph--a" aria-hidden="true">A</span>
|
|
20
|
+
<div className="sv-dialogue__answer">{children}</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Surfaces
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
On a page whose subject is coverage, an empty state is a **reading of zero** —
|
|
6
|
+
write it as a reading ("No mentions yet in this engine"), not an apology. A
|
|
7
|
+
`--surface` card, one 16px/500 line, one sentence in `--ink-body`, one outline
|
|
8
|
+
control.
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
<Empty title="No mentions yet in this engine"
|
|
12
|
+
hint="Add prompts to start the survey." action={<Button variant="secondary">Add prompts</Button>} />
|
|
13
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface EmptyProps {
|
|
4
|
+
/** One line in --ink, 16px/500. */
|
|
5
|
+
title: string;
|
|
6
|
+
/** One sentence in --ink-mute. */
|
|
7
|
+
hint?: string;
|
|
8
|
+
/** One quiet control that starts the demo — this pack always has one to offer. */
|
|
9
|
+
action?: ReactNode;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function Empty({ title, hint, action, className }: EmptyProps) {
|
|
14
|
+
return (
|
|
15
|
+
<div className={['sv-empty', className].filter(Boolean).join(' ')}>
|
|
16
|
+
<span className="sv-empty__title">{title}</span>
|
|
17
|
+
{hint !== undefined && <span className="sv-empty__hint">{hint}</span>}
|
|
18
|
+
{action !== undefined && <span className="sv-empty__action">{action}</span>}
|
|
19
|
+
</div>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: Actions
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
The landing ships no visible form, so the field is the pack's decision derived
|
|
6
|
+
from the control geometry: `--control-h` on `--surface`, 1px `--line` border,
|
|
7
|
+
`--r-control`, placeholder in `--ink-faint`. Invalid moves the border to
|
|
8
|
+
`--danger` **and** writes the message in it.
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
<Field label="Work email" placeholder="you@company.com" />
|
|
12
|
+
```
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface FieldProps {
|
|
2
|
+
label?: string;
|
|
3
|
+
placeholder?: string;
|
|
4
|
+
value?: string;
|
|
5
|
+
onChange?: (value: string) => void;
|
|
6
|
+
invalid?: boolean;
|
|
7
|
+
/** Shown under the field when invalid — the colour never carries the state alone. */
|
|
8
|
+
message?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function Field({
|
|
13
|
+
label,
|
|
14
|
+
placeholder,
|
|
15
|
+
value,
|
|
16
|
+
onChange,
|
|
17
|
+
invalid = false,
|
|
18
|
+
message,
|
|
19
|
+
className,
|
|
20
|
+
}: FieldProps) {
|
|
21
|
+
return (
|
|
22
|
+
<label className={['sv-field', className].filter(Boolean).join(' ')}>
|
|
23
|
+
{label !== undefined && <span className="sv-field__label">{label}</span>}
|
|
24
|
+
<input
|
|
25
|
+
className={['sv-field__input', invalid ? 'sv-field__input--invalid' : undefined]
|
|
26
|
+
.filter(Boolean)
|
|
27
|
+
.join(' ')}
|
|
28
|
+
placeholder={placeholder}
|
|
29
|
+
value={value}
|
|
30
|
+
aria-invalid={invalid || undefined}
|
|
31
|
+
onChange={(e) => onChange?.(e.target.value)}
|
|
32
|
+
/>
|
|
33
|
+
{invalid && message !== undefined && (
|
|
34
|
+
<span className="sv-field__message">{message}</span>
|
|
35
|
+
)}
|
|
36
|
+
</label>
|
|
37
|
+
);
|
|
38
|
+
}
|