@starci/hfs 4.7.34 → 4.7.36
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 +13 -0
- package/README.md +8 -11
- package/codemod/button-intent.mjs +356 -0
- package/lint/run.mjs +70 -29
- package/package.json +3 -2
- package/runtime/knowledge/grammars/index.yaml +111 -0
- package/runtime/knowledge/grammars/offset-pop/playbook.yaml +302 -0
- package/runtime/knowledge/grammars/starci/playbook.yaml +1190 -0
- package/runtime/knowledge/hfs/canon-pins.yaml +22 -8
- package/runtime/knowledge/hfs/fe-stack.yaml +12 -4
- package/runtime/knowledge/hfs/rules.yaml +163 -83
- package/runtime/knowledge/hfs/slots.yaml +3 -3
- package/runtime/knowledge/ui/presentation/font.yaml +101 -0
- package/runtime/knowledge/ui/presentation/padding.yaml +217 -0
- package/runtime/modules/kernel/failure-codes.yaml +102 -20
- package/runtime/modules/kernel/removed-vocabulary.yaml +29 -0
- package/runtime/modules/kernel/roles.yaml +1 -1
- package/runtime/packages/cli/src/catalog.generated.mjs +119 -9
- package/runtime/scripts/gates/canon-pins.mjs +103 -0
- package/runtime/scripts/gates/gate.mjs +3 -36
- package/runtime/scripts/gates/output.mjs +40 -0
- package/runtime/scripts/gates/test-world-run.mjs +2 -4
- package/runtime/scripts/guards/release-definition.mjs +22 -3
- package/runtime/scripts/hfs/architecture/config.mjs +8 -8
- package/runtime/scripts/hfs/check.mjs +1 -1
- package/runtime/scripts/hfs/db-restamp-verb.mjs +2 -2
- package/runtime/scripts/hfs/declaration-shape.mjs +8 -2
- package/runtime/scripts/hfs/grammar-presentation.mjs +152 -0
- package/runtime/scripts/hfs/rule-catalog.mjs +2 -2
- package/runtime/scripts/hfs/rules/a15-findings.mjs +1 -0
- package/runtime/scripts/hfs/rules/fe-stack.mjs +44 -1
- package/runtime/scripts/hfs/slots.mjs +1 -0
- package/runtime/scripts/hfs/view.mjs +1 -0
- package/runtime/scripts/lib/canon-binding-text.mjs +129 -0
- package/runtime/scripts/lib/css-rules.mjs +18 -0
- package/runtime/scripts/lib/example-refs.mjs +1 -1
- package/runtime/scripts/lib/grammar-lint.mjs +48 -0
- package/runtime/scripts/lib/grammar-vendor-parity-jsx.mjs +360 -0
- package/runtime/scripts/lib/grammar-vendor-parity.mjs +110 -157
- package/runtime/scripts/lib/numeric-match.mjs +5 -0
- package/runtime/scripts/lib/release-version.mjs +119 -0
- package/runtime/scripts/lib/runtime-publication-tags.mjs +3 -46
- package/runtime/scripts/lib/source-package-imports.mjs +111 -0
- package/runtime/scripts/work/draw/draw-layer.mjs +5 -4
- package/scaffold/app.mjs +7 -5
- package/src/main.mjs +30 -15
- package/stack/config.mjs +2 -1
- package/stack/render.mjs +24 -3
- package/sync/index.mjs +8 -2
- package/templates/app/skeleton/.starcistacks/dev/infra/compose/stack.yaml +0 -1
- package/templates/app/skeleton/.starcistacks/production/infra/swarm/stack.yaml +0 -1
- package/templates/app/skeleton-lite/.starcistacks/dev/infra/swarm/stack.yaml +0 -1
- package/templates/app/skeleton-lite/.starcistacks/production/infra/swarm/stack.yaml +0 -1
- package/templates/fe/tool-config/eslint.config.mjs +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@starci/hfs",
|
|
3
|
-
"version": "4.7.
|
|
3
|
+
"version": "4.7.36",
|
|
4
4
|
"description": "The StarCi app command implementation for scaffolding, linting, checking and synchronizing one product repository.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"db/**",
|
|
40
40
|
"ci/**",
|
|
41
41
|
"coverage/**",
|
|
42
|
+
"codemod/**",
|
|
42
43
|
"lint/**",
|
|
43
44
|
"scaffold/**",
|
|
44
45
|
"report/**",
|
|
@@ -50,7 +51,7 @@
|
|
|
50
51
|
"CHANGELOG.md"
|
|
51
52
|
],
|
|
52
53
|
"engines": {
|
|
53
|
-
"node": ">=22.
|
|
54
|
+
"node": ">=22.15.0"
|
|
54
55
|
},
|
|
55
56
|
"publishConfig": {
|
|
56
57
|
"access": "public"
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
schema: starci/knowledge-source@1
|
|
2
|
+
id: grammars
|
|
3
|
+
title: Grammar families
|
|
4
|
+
purpose: |
|
|
5
|
+
Catalog of authored UI Grammar families. Inventory only — not a default-family rule.
|
|
6
|
+
The selected design specification names the applicable installed family. The app binds that choice
|
|
7
|
+
explicitly in sides.fe.grammar; the catalog resolves its lint package and component contract.
|
|
8
|
+
A missing or ambiguous family never silently resolves to a family. DNA snapshots describe the
|
|
9
|
+
observed implementation; they do not install packages or prove current rendered behavior.
|
|
10
|
+
appliesTo:
|
|
11
|
+
- grammar
|
|
12
|
+
provenance:
|
|
13
|
+
limitations: |
|
|
14
|
+
Component names, tokens and gap tables describe the reference family at observation time.
|
|
15
|
+
Verify actual package identity/version, exported types, CSS and renderer source in the selected
|
|
16
|
+
repository before using snapshot APIs or gaps. Record current source references in the selected
|
|
17
|
+
.starciwork node; an old source census is not current UAT evidence. The current public consumer
|
|
18
|
+
entry observed for FE work is @starci/grammar/common — confirm installed exports before import.
|
|
19
|
+
The `common` entry is a DNA snapshot of that semantic entry and nothing more: it declares no palette,
|
|
20
|
+
no family boundary and no composition playbook, because the entry itself ships none of them.
|
|
21
|
+
guidance:
|
|
22
|
+
- id: catalog-not-default
|
|
23
|
+
requirement: |
|
|
24
|
+
Do not treat this catalog as selecting a default Grammar family. Family choice belongs to the
|
|
25
|
+
current design specification and its explicit sides.fe.grammar declaration.
|
|
26
|
+
rationale: |
|
|
27
|
+
Silent fallback to StarCi would invent product direction and override an absent/ambiguous design.
|
|
28
|
+
- id: verify-before-use
|
|
29
|
+
requirement: |
|
|
30
|
+
Before applying snapshot APIs or recorded gaps, inspect the selected repository's package
|
|
31
|
+
identity/version, exported types, CSS and renderer source.
|
|
32
|
+
rationale: |
|
|
33
|
+
Snapshots are historical; installed exports may differ. Inventing missing APIs is forbidden.
|
|
34
|
+
- id: ui-owns-universal
|
|
35
|
+
requirement: |
|
|
36
|
+
Common semantics, renderer anatomy, state and accessibility remain owned by knowledge/ui.
|
|
37
|
+
A family owns its scoped visual realization and promoted idioms; the product owns its facts,
|
|
38
|
+
content, routes and approved composition.
|
|
39
|
+
Apply FE-RULE-OWNERSHIP in knowledge/patterns/fe/index.yaml when placing requirements and checks.
|
|
40
|
+
rationale: |
|
|
41
|
+
Keeps universal UI law separate from family-scoped DNA and product composition.
|
|
42
|
+
topics:
|
|
43
|
+
- id: common
|
|
44
|
+
path: common/DNA.yaml
|
|
45
|
+
title: Common Grammar — DNA
|
|
46
|
+
summary: |
|
|
47
|
+
Generated DNA snapshot of the `@starci/grammar/common` public entry: custom properties,
|
|
48
|
+
the 110 renderers of its registry, their classes, stamped rule ids and recorded gaps. The DNA owns the observed package
|
|
49
|
+
version and source inventory. Common supplies anatomy, not colour. The snapshot is drift-checked.
|
|
50
|
+
- id: starci
|
|
51
|
+
path: starci/index.yaml
|
|
52
|
+
title: StarCi Core Grammar
|
|
53
|
+
summary: |
|
|
54
|
+
Historical snapshot of the StarCi Core family — DNA, idioms, playbook (including composing the
|
|
55
|
+
0.5.0 forms, overlays and navigation chrome) and family boundaries.
|
|
56
|
+
- id: offset-pop
|
|
57
|
+
path: offset-pop/index.yaml
|
|
58
|
+
title: Offset Pop Grammar
|
|
59
|
+
summary: |
|
|
60
|
+
Snapshot of the product-neutral Offset Pop family — cream canvas, ink outline plus hard offset
|
|
61
|
+
shadow, one pink decision accent with a text-safe accent for text — with DNA, idioms, a
|
|
62
|
+
mobile-first playbook for playful learning or consumer apps, and family boundaries including two
|
|
63
|
+
decisions flagged for the family owner.
|
|
64
|
+
- id: heritage
|
|
65
|
+
path: heritage/DNA.yaml
|
|
66
|
+
title: Heritage Grammar
|
|
67
|
+
summary: |
|
|
68
|
+
Generated snapshot of the Heritage family's parity declaration, arrangement, scoped tokens and Common renderers.
|
|
69
|
+
families:
|
|
70
|
+
- id: heritage
|
|
71
|
+
title: heritage
|
|
72
|
+
contractRef: common
|
|
73
|
+
packageSnapshot: heritage/DNA.yaml
|
|
74
|
+
- id: common
|
|
75
|
+
title: common
|
|
76
|
+
componentContract:
|
|
77
|
+
package: '@starci/grammar'
|
|
78
|
+
entry: '@starci/grammar/common'
|
|
79
|
+
styleEntry: '@starci/grammar/common.css'
|
|
80
|
+
peers: [react, '@heroui/react', '@xyflow/react']
|
|
81
|
+
packageSnapshot: common/DNA.yaml
|
|
82
|
+
scope: |
|
|
83
|
+
DNA snapshot only. This catalog carries no Common-side family boundary, idiom set or composition
|
|
84
|
+
playbook: `@starci/grammar/common` is the semantic/props entry every visual family is defined over
|
|
85
|
+
(`defineGrammarFamily`), not a family that ships a palette, so `authority`, `reusableStyle`,
|
|
86
|
+
`productComposition` and `index` have nothing to name here. Universal semantics, renderer anatomy,
|
|
87
|
+
state and accessibility remain owned by knowledge/ui.
|
|
88
|
+
- id: starci
|
|
89
|
+
title: starci
|
|
90
|
+
contractRef: common
|
|
91
|
+
lint:
|
|
92
|
+
package: '@starci/eslint-grammar-starci'
|
|
93
|
+
factory: starciGrammarConfig
|
|
94
|
+
prefix: starci-grammar
|
|
95
|
+
authority: starci/family.yaml
|
|
96
|
+
packageSnapshot: starci/DNA.yaml
|
|
97
|
+
reusableStyle: starci/idioms.yaml
|
|
98
|
+
productComposition: starci/playbook.yaml
|
|
99
|
+
index: starci/index.yaml
|
|
100
|
+
- id: offset-pop
|
|
101
|
+
title: offset-pop
|
|
102
|
+
contractRef: common
|
|
103
|
+
lint:
|
|
104
|
+
package: '@starci/eslint-grammar-offset-pop'
|
|
105
|
+
factory: offsetPopGrammarConfig
|
|
106
|
+
prefix: starci-grammar
|
|
107
|
+
authority: offset-pop/family.yaml
|
|
108
|
+
packageSnapshot: offset-pop/DNA.yaml
|
|
109
|
+
reusableStyle: offset-pop/idioms.yaml
|
|
110
|
+
productComposition: offset-pop/playbook.yaml
|
|
111
|
+
index: offset-pop/index.yaml
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
schema: starci/knowledge-source@1
|
|
2
|
+
id: grammar.offset-pop.playbook
|
|
3
|
+
title: Offset Pop — playbook
|
|
4
|
+
purpose: |
|
|
5
|
+
How a playful, mobile-first learning or consumer app is composed from the renderers Offset Pop
|
|
6
|
+
publishes: which renderers a business shape asks for, in what order, with which props, and the rules
|
|
7
|
+
every Offset Pop app follows (one root, one pink per decision, thumb-sized targets, a bottom-sheet
|
|
8
|
+
Drawer for secondary tasks, a navigation drawer at phone widths). Product-neutral: the shapes name no product,
|
|
9
|
+
and every label below is a role, not copy. A shape not listed here may still be composed from Common
|
|
10
|
+
semantics and family anatomy for an approved product direction.
|
|
11
|
+
appliesTo:
|
|
12
|
+
- grammar
|
|
13
|
+
family: offset-pop
|
|
14
|
+
provenance:
|
|
15
|
+
package: "@starci/grammar"
|
|
16
|
+
version: "0.5.0"
|
|
17
|
+
checkout: b6a13be97a9d1e15b7d3f628709158e81c744a2a
|
|
18
|
+
captured: "2026-09-23"
|
|
19
|
+
publicEntry: "@starci/grammar/common"
|
|
20
|
+
familyEntry: "@starci/grammar/offset-pop"
|
|
21
|
+
limitations: |
|
|
22
|
+
Use this playbook only when Offset Pop is selected in the current .starciwork specification. The
|
|
23
|
+
shapes are package usage written from the family's source, not observations of a shipped product;
|
|
24
|
+
verify installed exports, props and CSS before promising a capability, and do not invent Grammar
|
|
25
|
+
APIs absent from DNA.yaml or installed source. Reading steps are reasoning within one op, not an
|
|
26
|
+
auto-running op chain.
|
|
27
|
+
shapes:
|
|
28
|
+
- id: app-shell
|
|
29
|
+
title: App shell — fixed frame, navbar, sidebar drawer, one Toaster
|
|
30
|
+
knowledge: knowledge/ui/composition/app-shell.yaml
|
|
31
|
+
composition:
|
|
32
|
+
- renderer: OffsetPopGrammarRoot
|
|
33
|
+
role: |
|
|
34
|
+
The one root around the whole app, `theme="system"` unless the product fixes a theme; imports
|
|
35
|
+
`@starci/grammar/offset-pop/styles.css`
|
|
36
|
+
- renderer: WorkspaceShell
|
|
37
|
+
role: |
|
|
38
|
+
`viewport="fixed"` owns the frame, navbar, mobile opener band and independent sidebar and
|
|
39
|
+
content scroll. Compose the regions required by FE-APP-SHELL-1 through FE-APP-SHELL-7.
|
|
40
|
+
- renderer: TopBar
|
|
41
|
+
role: |
|
|
42
|
+
Identity, search and the ordered language, theme, notifications and account controls follow
|
|
43
|
+
the app-shell contract. Every bar control uses `size="control"`; Grammar owns its geometry.
|
|
44
|
+
- renderer: Sidebar
|
|
45
|
+
role: |
|
|
46
|
+
The desktop navigation and its icon rail use `presentation="rail"`. The route owns
|
|
47
|
+
`selectedKey`; the product owns permissions, groups and collapse persistence.
|
|
48
|
+
- renderer: Drawer
|
|
49
|
+
role: |
|
|
50
|
+
The mobile opener below the navbar opens a left drawer containing Sidebar
|
|
51
|
+
`presentation="drawer"`, plus language and theme controls. Selection, backdrop and Escape
|
|
52
|
+
dismiss it; focus stays inside while it is open (FE-APP-SHELL-4).
|
|
53
|
+
- renderer: PageContainer
|
|
54
|
+
role: |
|
|
55
|
+
Route content lives in the shell's primary region. Create actions belong on their pages
|
|
56
|
+
(FE-APP-SHELL-5); app classes express layout only.
|
|
57
|
+
- renderer: Toaster
|
|
58
|
+
role: |
|
|
59
|
+
Once, inside the root, with `label` and `dismissLabel`; its placement keeps notifications
|
|
60
|
+
clear of the shell controls and the current task.
|
|
61
|
+
notes: |
|
|
62
|
+
FE-RULE-OWNERSHIP in knowledge/patterns/fe/index.yaml keeps shell semantics in universal
|
|
63
|
+
knowledge and the named API checks in the selected Grammar lint package. The app shell has no
|
|
64
|
+
bottom tab bar. Offset Pop owns the outline, palette and hard shadow in its packaged CSS.
|
|
65
|
+
|
|
66
|
+
- id: home-continue
|
|
67
|
+
title: Home — where the reader left off, one next step
|
|
68
|
+
referenceMayContribute: |
|
|
69
|
+
Keep: which sections exist and which one is the next step. Never crosses over: layout grid, card
|
|
70
|
+
chrome, or a section that would need a renderer the family does not publish.
|
|
71
|
+
composition:
|
|
72
|
+
- renderer: SectionHeader
|
|
73
|
+
role: The greeting or section title; its eyebrow reads `accentText`, never the pink
|
|
74
|
+
- renderer: SurfaceCard
|
|
75
|
+
role: |
|
|
76
|
+
One top-level sticker for the next step (`isHighlight` on that card only), holding the title
|
|
77
|
+
and one supporting line (Text size="sm" tone="muted"), a real measurement, and one
|
|
78
|
+
Button variant="primary" — the view's single pink fill
|
|
79
|
+
- renderer: "Progress / ProgressCircle / Meter"
|
|
80
|
+
role: Only a verified value with a truthful `label` (ACCENT-4); an unknown value is not drawn
|
|
81
|
+
- renderer: SurfaceListCard
|
|
82
|
+
role: Peers (recent items, suggestions) as static rows; no second primary Button
|
|
83
|
+
- renderer: "Skeleton / EmptyNotice"
|
|
84
|
+
role: Pending is the same tree at rest (Skeleton in place of content); empty or failed is EmptyNotice
|
|
85
|
+
notes: |
|
|
86
|
+
A streak, level or reward count is a Badge or a Meter, not a second pink call to action.
|
|
87
|
+
|
|
88
|
+
- id: practice-step
|
|
89
|
+
title: One question per screen — choose, check, see the outcome
|
|
90
|
+
composition:
|
|
91
|
+
- renderer: Progress
|
|
92
|
+
role: How far through the set the reader is, from a real count
|
|
93
|
+
- renderer: Heading
|
|
94
|
+
role: The prompt; `scale="display"` only for a single short prompt
|
|
95
|
+
- renderer: "RadioGroup / CheckboxGroup / SegmentedControl"
|
|
96
|
+
role: |
|
|
97
|
+
The answer choices as the control itself (each choice is a full-width, 44px-plus target with
|
|
98
|
+
its own label); `isInvalid`/`errorMessage` only for a validation problem, never for a wrong answer
|
|
99
|
+
- renderer: Button
|
|
100
|
+
role: |
|
|
101
|
+
One variant="primary" type="submit" ("check" in the product's words), full width at the bottom
|
|
102
|
+
of the content, `isDisabled` until a choice exists — the layout does not move when it enables
|
|
103
|
+
- renderer: Alert
|
|
104
|
+
role: |
|
|
105
|
+
The outcome in place, above the action: `tone="affirmative"` (mint) or `tone="negative"`
|
|
106
|
+
(critical), its single `action` for the next step; the tone is the outcome, never decoration
|
|
107
|
+
- renderer: Drawer
|
|
108
|
+
role: |
|
|
109
|
+
`placement="bottom"` for an optional explanation or hint the reader opens; the handle is
|
|
110
|
+
decorative, the close button and Escape are the ways out
|
|
111
|
+
notes: |
|
|
112
|
+
Feedback that must not interrupt (a streak kept, an item saved) is a Toast, not an Alert; feedback
|
|
113
|
+
the reader must act on stays in the page.
|
|
114
|
+
|
|
115
|
+
- id: result-celebration
|
|
116
|
+
title: Result — celebrate a finished set, offer one way on
|
|
117
|
+
composition:
|
|
118
|
+
- renderer: SurfaceCard
|
|
119
|
+
role: The result sticker, `isHighlight`
|
|
120
|
+
- renderer: Heading
|
|
121
|
+
role: "`scale=\"display\"` (weight 900, tight tracking) for the one headline"
|
|
122
|
+
- renderer: "ProgressCircle / Meter / DescriptionList"
|
|
123
|
+
role: The score and its facts, each a real value with a label
|
|
124
|
+
- renderer: Button
|
|
125
|
+
role: One variant="primary" onward; a secondary Button or TextAction to review
|
|
126
|
+
- renderer: Toast
|
|
127
|
+
role: An earned reward announced politely (`toastQueue.add` with `tone="affirmative"`)
|
|
128
|
+
notes: |
|
|
129
|
+
Celebration is the display headline, the mint outcome and the sticker's press; the family adds no
|
|
130
|
+
confetti, and motion stays press travel only (removed under reduced motion).
|
|
131
|
+
|
|
132
|
+
- id: bottom-sheet-task
|
|
133
|
+
title: Secondary task on a phone — filters, pickers, details, quick edit
|
|
134
|
+
composition:
|
|
135
|
+
- renderer: Drawer
|
|
136
|
+
role: |
|
|
137
|
+
`placement="bottom"` below 48rem (upward hard shadow, grab handle), `placement="right"` on wide
|
|
138
|
+
layouts; `title` names the task, `footer` holds one primary Button (a render function receives
|
|
139
|
+
`close`)
|
|
140
|
+
- renderer: "Select / DatePicker / TagGroup / Switch"
|
|
141
|
+
role: The controls inside; their own popovers stay inside the root and the sheet
|
|
142
|
+
notes: |
|
|
143
|
+
One secondary-task sheet opens at a time. The shell navigation follows FE-APP-SHELL-4's left
|
|
144
|
+
drawer and preserves its own navigation and dismissal behavior.
|
|
145
|
+
|
|
146
|
+
- id: sign-up-and-onboarding
|
|
147
|
+
title: Sign-up or onboarding — short groups, one submit per step
|
|
148
|
+
composition:
|
|
149
|
+
- renderer: Stepper
|
|
150
|
+
role: Where the reader is in a multi-step flow (pink current, mint complete, critical error)
|
|
151
|
+
- renderer: Form
|
|
152
|
+
role: "`label`, `onSubmit(FormData)`, `validationErrors` by field `name`, `isPending`"
|
|
153
|
+
- renderer: Fieldset
|
|
154
|
+
role: One per named group
|
|
155
|
+
- renderer: "Select / DateField / Checkbox / Switch / RadioGroup / Textarea"
|
|
156
|
+
role: Each with its own `label`, `description`, `errorMessage`, `isRequired`, `name`
|
|
157
|
+
- renderer: Field
|
|
158
|
+
role: Only for a control the package does not publish (OtpInput, a third-party widget)
|
|
159
|
+
- renderer: Button
|
|
160
|
+
role: One variant="primary" type="submit" per step
|
|
161
|
+
notes: |
|
|
162
|
+
Field focus is the hard offset shadow (critical while invalid); do not add an app focus ring.
|
|
163
|
+
|
|
164
|
+
- id: settings
|
|
165
|
+
title: Settings — immediate toggles, grouped, destructive actions confirmed
|
|
166
|
+
composition:
|
|
167
|
+
- renderer: Fieldset
|
|
168
|
+
role: One per group of settings
|
|
169
|
+
- renderer: "Switch / Select / SegmentedControl"
|
|
170
|
+
role: A Switch applies immediately; confirm the change with a polite Toast, not a dialog
|
|
171
|
+
- renderer: AlertDialog
|
|
172
|
+
role: |
|
|
173
|
+
For an irreversible action only: `tone="negative"` (the confirm fills critical, not pink),
|
|
174
|
+
`confirmLabel`/`cancelLabel` in the product's words; initial focus lands on cancel
|
|
175
|
+
- renderer: Toast
|
|
176
|
+
role: Undo for a reversible action (`action` keeps the toast until dismissed)
|
|
177
|
+
|
|
178
|
+
- id: browse-and-pick
|
|
179
|
+
title: Browse a catalogue — search, filter, pick
|
|
180
|
+
composition:
|
|
181
|
+
- renderer: SearchField
|
|
182
|
+
role: The query, labelled
|
|
183
|
+
- renderer: TagGroup
|
|
184
|
+
role: Filters as outlined chips; selected chips turn pink and lift
|
|
185
|
+
- renderer: "ListBox / SurfaceListCard"
|
|
186
|
+
role: |
|
|
187
|
+
ListBox when picking is the task (yellow hover wash, pink focus ring, soft-pink selected row
|
|
188
|
+
with a pink leading edge); SurfaceListCard when rows only report facts
|
|
189
|
+
- renderer: Pagination
|
|
190
|
+
role: Current page is the raised pink pill
|
|
191
|
+
- renderer: "Skeleton / EmptyNotice"
|
|
192
|
+
role: Pending keeps the list shape; empty and failed are EmptyNotice
|
|
193
|
+
|
|
194
|
+
readingSteps:
|
|
195
|
+
- id: business-shape-first
|
|
196
|
+
order: 1
|
|
197
|
+
title: Business shape first
|
|
198
|
+
instruction: |
|
|
199
|
+
Name the shape and the one outcome the screen exists to produce. That outcome is the view's single
|
|
200
|
+
pink fill; everything else is ink on cream.
|
|
201
|
+
- id: then-reference
|
|
202
|
+
order: 2
|
|
203
|
+
title: Then the reference, if the request supplied one
|
|
204
|
+
instruction: |
|
|
205
|
+
A reference contributes region order, which decision dominates, and what folds into a bottom
|
|
206
|
+
sheet. It never contributes palette, outline, shadow or component anatomy — those are this
|
|
207
|
+
family's and knowledge/ui's.
|
|
208
|
+
- id: then-compose
|
|
209
|
+
order: 3
|
|
210
|
+
title: Then the shape's composition, mobile first
|
|
211
|
+
instruction: |
|
|
212
|
+
Compose the shape's renderers at phone width first: the shell's left navigation drawer,
|
|
213
|
+
bottom-sheet secondary tasks and a full-width primary action. The published responsive shell
|
|
214
|
+
switches to its sidebar and the task drawer to its wide presentation.
|
|
215
|
+
- id: compare-dna
|
|
216
|
+
order: 4
|
|
217
|
+
title: Compare DNA with actually installed source
|
|
218
|
+
instruction: |
|
|
219
|
+
Confirm named renderers, props and closed values against DNA.yaml and installed exports, and read
|
|
220
|
+
family.yaml's gaps and owner decisions before promising a capability.
|
|
221
|
+
- id: resolve-product-composition
|
|
222
|
+
order: 5
|
|
223
|
+
title: Then resolve the remaining product composition
|
|
224
|
+
instruction: |
|
|
225
|
+
Reuse a shape where it fits; otherwise compose existing Common semantics and family anatomy. A
|
|
226
|
+
shape absent from this table is an evidence limit on house style, not a reason to stop work
|
|
227
|
+
already inside the approved product scope.
|
|
228
|
+
|
|
229
|
+
authoritySplit:
|
|
230
|
+
directionChoiceRequired: |
|
|
231
|
+
DIRECTION_CHOICE_REQUIRED is reserved for a material product choice whose acceptable options lead to
|
|
232
|
+
different outcomes and whose answer is absent from the request. Product facts, copy, mascot and
|
|
233
|
+
assets come from the product; Common semantics from knowledge/ui; outline, shadow, palette and
|
|
234
|
+
reusable treatments from this family. The two decisions flagged for the family owner in family.yaml
|
|
235
|
+
(BOUNDARY-6 departure, single pink) are not the product's to change.
|
|
236
|
+
|
|
237
|
+
guidance:
|
|
238
|
+
- id: one-root-overlays-inside
|
|
239
|
+
requirement: |
|
|
240
|
+
Render everything — chrome, content, every overlay trigger (Dialog, AlertDialog, Drawer, Popover,
|
|
241
|
+
DropdownMenu, the Select/ComboBox/DatePicker fields) and the Toaster — inside one
|
|
242
|
+
`OffsetPopGrammarRoot`. Overlays portal into the nearest Grammar root; a trigger outside it opens a
|
|
243
|
+
plain, unstyled overlay in `<body>` with no outline, no offset, no dark palette.
|
|
244
|
+
rationale: |
|
|
245
|
+
The family is a scope on the root; only its DOM descendants are Offset Pop.
|
|
246
|
+
- id: one-pink-per-view
|
|
247
|
+
requirement: |
|
|
248
|
+
Give each view at most one pink-filled action (Button variant="primary", or the single confirm /
|
|
249
|
+
toast / alert action the family fills). Text that must carry the accent uses Text tone="accent"
|
|
250
|
+
(which reads `accentText`); never set the pink as a text colour.
|
|
251
|
+
rationale: |
|
|
252
|
+
Pink as body text is 3.22:1 on the canvas; one fill per view is what makes the decision obvious in
|
|
253
|
+
a family where selection, current and focus share the same pink.
|
|
254
|
+
- id: big-touch-targets
|
|
255
|
+
requirement: |
|
|
256
|
+
Keep the published sizes: Common's 44px floor for controls, the Subnav toggle and the TopBar
|
|
257
|
+
trigger, and `size="control"` throughout the navbar. Do not shrink them with app classes,
|
|
258
|
+
and put answer choices in RadioGroup/CheckboxGroup/SegmentedControl rather than small
|
|
259
|
+
custom chips.
|
|
260
|
+
rationale: |
|
|
261
|
+
A playful, thumb-driven app is used one-handed; the family's targets are part of its idiom.
|
|
262
|
+
- id: bottom-sheet-for-secondary
|
|
263
|
+
requirement: |
|
|
264
|
+
On a phone, secondary tasks open in `Drawer placement="bottom"`; reserve `Dialog` for a short task
|
|
265
|
+
that must block the page and `AlertDialog` for an irreversible decision.
|
|
266
|
+
rationale: |
|
|
267
|
+
The bottom sheet keeps the task within thumb reach and throws its shadow upward into the page.
|
|
268
|
+
- id: toaster-clear-of-content
|
|
269
|
+
requirement: |
|
|
270
|
+
One Toaster stays inside the Grammar root. Its placement keeps feedback clear of the shell
|
|
271
|
+
controls and the task's primary action, including while the navigation drawer is open.
|
|
272
|
+
rationale: |
|
|
273
|
+
Feedback remains visible without covering the control needed to complete the current task.
|
|
274
|
+
- id: no-extra-chrome
|
|
275
|
+
requirement: |
|
|
276
|
+
Do not add app-level borders, blur shadows, gradients or a second accent colour to family
|
|
277
|
+
renderers; do not restyle the palette per screen. Adapt the family only through the
|
|
278
|
+
`OFFSET_POP_TOKEN_NAMES` custom properties on the root.
|
|
279
|
+
rationale: |
|
|
280
|
+
The outline, the hard offset and the one pink are the family; an extra layer turns stickers into
|
|
281
|
+
a different, noisier family and breaks the dark and forced-colours mappings.
|
|
282
|
+
- id: product-neutral
|
|
283
|
+
requirement: |
|
|
284
|
+
Keep product names, copy, mascots and illustration inside the product. The family and this
|
|
285
|
+
playbook name roles only.
|
|
286
|
+
rationale: |
|
|
287
|
+
Offset Pop is a shared family; its first consumer does not own it.
|
|
288
|
+
|
|
289
|
+
presentation:
|
|
290
|
+
font:
|
|
291
|
+
ownership: FE-RULE-OWNERSHIP
|
|
292
|
+
inherits: starci
|
|
293
|
+
contract: |
|
|
294
|
+
Offset Pop keeps Common typography renderers and props. Its font proof reads the shared Common
|
|
295
|
+
rank-to-renderer recipes in the StarCi playbook; the Offset Pop stylesheet owns its family palette
|
|
296
|
+
and display treatment.
|
|
297
|
+
padding:
|
|
298
|
+
ownership: FE-RULE-OWNERSHIP
|
|
299
|
+
inherits: starci
|
|
300
|
+
contract: |
|
|
301
|
+
Offset Pop keeps the same Common spacing and component geometry. Its padding proof reads the
|
|
302
|
+
shared Common recipes declared in the StarCi playbook; it supplies no replacement inset scale.
|