@orkestrel/scaffold 0.0.64 → 0.0.65
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/README.md +11 -1
- package/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +184 -177
- package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +299 -76
- package/dist/host/agents/skills/enterprise-bootstrap/references/color-modes.md +241 -0
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +83 -36
- package/dist/host/agents/skills/enterprise-bootstrap/references/frontend-design.md +297 -98
- package/dist/host/agents/skills/enterprise-bootstrap/references/inputs.md +25 -14
- package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +216 -128
- package/dist/host/agents/skills/enterprise-bootstrap/references/responsive-layout.md +187 -0
- package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +105 -16
- package/dist/host/claude/rules/workspace.md +2 -2
- package/dist/host/claude/settings.json +1 -1
- package/dist/host/claude/skills/enterprise-bootstrap/SKILL.md +10 -9
- package/dist/host/guides/scaffold.md +63 -22
- package/dist/host/manifest.json +25 -13
- package/dist/host/scripts/codex.sh +0 -0
- package/dist/host/scripts/cursor.sh +0 -0
- package/dist/host/scripts/deps.sh +0 -0
- package/dist/host/scripts/ollama.sh +322 -13
- package/dist/src/core/index.cjs +33 -12
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +31 -9
- package/dist/src/core/index.d.ts +31 -9
- package/dist/src/core/index.js +32 -13
- package/dist/src/core/index.js.map +1 -1
- package/package.json +4 -4
|
@@ -1,20 +1,25 @@
|
|
|
1
1
|
# Instruments
|
|
2
2
|
|
|
3
|
-
Reach for an instrument
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
`.claude/rules/quality.md` owns that law where
|
|
7
|
-
|
|
8
|
-
Take each entry's property, population,
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- **
|
|
16
|
-
|
|
17
|
-
|
|
3
|
+
Reach for an instrument where a capture cannot settle the claim. Run it against the compiled
|
|
4
|
+
cascade the page loads, with its negative controls under the same conditions. Treat a missed
|
|
5
|
+
negative control as a broken instrument and refuse its reading as evidence;
|
|
6
|
+
`.claude/rules/quality.md` owns that law where present.
|
|
7
|
+
|
|
8
|
+
Keep mechanical results separate from visual judgments. Take each entry's property, population,
|
|
9
|
+
reading, negative control, and coverage as its contract. Report failures and untested coverage, not
|
|
10
|
+
a pass label alone.
|
|
11
|
+
|
|
12
|
+
- **Report the population.** Name the membership rule and count what the extractor walked. An
|
|
13
|
+
expected but empty population fails. Mark a genuinely absent feature not applicable with its
|
|
14
|
+
reason; do not count it as passing.
|
|
15
|
+
- **Keep controls independent.** Construct known-invalid fixtures in the harness, outside the
|
|
16
|
+
production population and the accepted set. Include them in the test run through the same
|
|
17
|
+
extraction path, and exclude them from production counts. Do not filter the defect out before
|
|
18
|
+
the reader can see it.
|
|
19
|
+
- **Test extraction as well as reading.** Pair a directly fed fixture with one appended to the
|
|
20
|
+
tree, stylesheet, or registry wherever extraction exists. Remove harness mutations afterward.
|
|
21
|
+
- **Bound the claim.** Name files, routes, themes, viewports, states, and exclusions actually read.
|
|
22
|
+
Unsupported input and unavailable tooling remain open, never passed by assumption.
|
|
18
23
|
|
|
19
24
|
## Contents
|
|
20
25
|
|
|
@@ -22,146 +27,229 @@ every entry to these rules.
|
|
|
22
27
|
- [Declared class combinations](#declared-class-combinations)
|
|
23
28
|
- [Style escapes](#style-escapes)
|
|
24
29
|
- [Token discipline](#token-discipline)
|
|
30
|
+
- [Declared design scales](#declared-design-scales)
|
|
25
31
|
- [Custom rule doing a utility's job](#custom-rule-doing-a-utilitys-job)
|
|
32
|
+
- [Color-mode inheritance](#color-mode-inheritance)
|
|
26
33
|
- [Composited contrast in both themes](#composited-contrast-in-both-themes)
|
|
27
34
|
- [One glyph, one meaning](#one-glyph-one-meaning)
|
|
35
|
+
- [Responsive task and reflow](#responsive-task-and-reflow)
|
|
36
|
+
- [Responsive interaction continuity](#responsive-interaction-continuity)
|
|
37
|
+
- [Rendered design review](#rendered-design-review)
|
|
28
38
|
- [When an authored rule is already earned](#when-an-authored-rule-is-already-earned)
|
|
29
39
|
|
|
30
40
|
## Authored class in the shipped cascade
|
|
31
41
|
|
|
32
|
-
- **Property.** Every class
|
|
33
|
-
|
|
34
|
-
- **Population.**
|
|
35
|
-
|
|
36
|
-
- **Reading.**
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
- **Negative control.**
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
`class`
|
|
43
|
-
|
|
44
|
-
- **Coverage.** The fed negative control covers the subtraction. The appended negative control covers the extractor,
|
|
45
|
-
and it is what fails a reading that never leaves the root or that drops SVG tokens by reaching for
|
|
46
|
-
`className`, where the value is an `SVGAnimatedString` rather than a string. Together they prove
|
|
47
|
-
authored tokens are a subset of the cascade. The instrument says nothing about a cascade rule
|
|
48
|
-
nobody authored, a token a build step or a script adds after the read, or whether a resolved rule
|
|
49
|
-
paints what the author intended.
|
|
42
|
+
- **Property.** Every styling class the surface authors resolves in the loaded CSS. Separately name
|
|
43
|
+
legitimate behavior/test hooks that require no CSS; never excuse an intended utility as a hook.
|
|
44
|
+
- **Population.** Authored class tokens, including SVG and conditional states, against vendor,
|
|
45
|
+
skin, dependency, generated-utility, and project stylesheets actually loaded.
|
|
46
|
+
- **Reading.** Parse selectors, subtract the defined styling tokens from the authored set, and
|
|
47
|
+
report each unresolved token with its source. Enumerate declared conditional classes not reached
|
|
48
|
+
in the mounted tree separately; an unreachable stylesheet is an open dependency, not an empty one.
|
|
49
|
+
- **Negative control.** Feed an undefined styling token to the reader, then append a harness SVG
|
|
50
|
+
carrying that token through the same tree extractor. Both must be reported.
|
|
51
|
+
- **Coverage.** The two controls cover set comparison and extraction, including SVG's non-string
|
|
52
|
+
`className`. Use `getAttribute('class')` or an equivalent safe reader. Resolution does not prove
|
|
53
|
+
the rule wins the cascade, paints the intended result, or covers a state never enumerated.
|
|
50
54
|
|
|
51
55
|
## Declared class combinations
|
|
52
56
|
|
|
53
|
-
- **Property.**
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
- **Negative control.**
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
- **Coverage.** The fed negative control covers the match against the declared set. The appended negative
|
|
65
|
-
control covers the extractor, and it is what fails a reading that never leaves the root or that drops SVG
|
|
66
|
-
tokens by reaching for `className`. Together they prove reused chrome is declared. The instrument
|
|
67
|
-
does not prove a declared invariant is true, and it does not read a single utility used alone.
|
|
68
|
-
- **Never substitute a cancellation heuristic.** A rule that flags a string for its utility count, or
|
|
69
|
-
for mixing categories, refuses the legitimate transparent read chrome that keeps a read view and an
|
|
70
|
-
edit view from reflowing.
|
|
57
|
+
- **Property.** Reused multi-utility chrome has one named declaration and a stated invariant.
|
|
58
|
+
- **Population.** Declared combinations and the authored instances of those reusable patterns.
|
|
59
|
+
Declare the pattern scope; do not require a registry entry for every one-off layout string.
|
|
60
|
+
- **Reading.** Compare token sets within that scope to the named contracts. Report an undeclared
|
|
61
|
+
or divergent instance. Keep utility order irrelevant unless the host's class merger makes it
|
|
62
|
+
meaningful; record that merger when it applies.
|
|
63
|
+
- **Negative control.** Feed a combination one utility away from its contract, then append an
|
|
64
|
+
instance carrying that mutation through the same extractor, including an SVG fixture. Report both.
|
|
65
|
+
- **Coverage.** This proves instances match declarations, not that an invariant renders correctly.
|
|
66
|
+
Pair geometry or contrast invariants with their own measurements. Never substitute utility-count
|
|
67
|
+
or mixed-category heuristics; a valid transparent read-only treatment can use several utilities.
|
|
71
68
|
|
|
72
69
|
## Style escapes
|
|
73
70
|
|
|
74
|
-
- **Property.**
|
|
75
|
-
- **Population.**
|
|
76
|
-
|
|
77
|
-
- **Reading.**
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
- **Negative control.** An element carrying an inline declaration, built in the harness rather
|
|
85
|
-
than taken from the surface, fed to the reading. It sits outside the surface's own markup and the
|
|
86
|
-
reading must report it.
|
|
87
|
-
- **Coverage.** The instrument reads authored markup at mount. It does not see a style a component
|
|
88
|
-
writes after the person interacts, a rule authored in a stylesheet, or an escape inside a
|
|
89
|
-
third-party component's own markup.
|
|
71
|
+
- **Property.** Authored markup carries no `style` attribute or `<style>` element.
|
|
72
|
+
- **Population.** Authored templates and the freshly mounted, undriven tree. Keep source and mounted
|
|
73
|
+
readings distinct so generated framework styles are not mistaken for authored declarations.
|
|
74
|
+
- **Reading.** Report inline declarations and embedded style elements with their source or element.
|
|
75
|
+
Record framework/runtime exemptions by producer and purpose, never a blanket component exemption.
|
|
76
|
+
Bootstrap overlay positioning and conditional-visibility directives may write runtime styles.
|
|
77
|
+
- **Negative control.** Feed an element with an inline declaration, then append an inline-styled
|
|
78
|
+
element and a `<style>` element to the harness tree. Every non-exempt fixture must be reported.
|
|
79
|
+
- **Coverage.** This covers authored and mount-time escapes, not later interactions or third-party
|
|
80
|
+
internals outside the declared scope. Drive later states separately when making claims about them.
|
|
90
81
|
|
|
91
82
|
## Token discipline
|
|
92
83
|
|
|
93
|
-
- **Property.**
|
|
94
|
-
token in each color mode
|
|
95
|
-
- **Population.**
|
|
96
|
-
custom-painted
|
|
97
|
-
- **Reading.**
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
84
|
+
- **Property.** Literal colors live only in declared primitive definitions. Semantic and component
|
|
85
|
+
paint resolve through the declared token layers in each shipped color mode.
|
|
86
|
+
- **Population.** Project-authored color declarations and token references, the named primitive
|
|
87
|
+
definition locations, and custom-painted properties reached in each theme and state.
|
|
88
|
+
- **Reading.** Parse declarations, not color-looking text in comments or strings. Permit raw colors
|
|
89
|
+
only in the named primitive definitions; reject literals in component paint, unresolved or cyclic
|
|
90
|
+
references, and a component bypassing semantic tokens. Check RGB partners where consumed. A theme
|
|
91
|
+
pair may resolve identically unless the design contract requires it to differ.
|
|
92
|
+
- **Negative control.** Accept a valid primitive definition as a positive fixture. Feed a literal
|
|
93
|
+
component fill and an undefined token reference; append both to a harness stylesheet through the
|
|
94
|
+
same extractor. The valid definition must survive and every invalid fixture must fail.
|
|
95
|
+
- **Coverage.** This proves declared paint follows the token boundary in the read scope. It does not
|
|
96
|
+
prove mode adaptation, foreground ownership, legibility, or visual quality. Use Color-mode inheritance for the cascade contract. Vendor literals are not authored violations;
|
|
97
|
+
rendered contrast still measures their effect. Inline paint belongs to Style escapes.
|
|
98
|
+
|
|
99
|
+
## Declared design scales
|
|
100
|
+
|
|
101
|
+
- **Property.** Authored type, spacing, width, radius, and elevation treatments use declared roles,
|
|
102
|
+
shipped scale steps, or documented extensions rather than untracked one-off values.
|
|
103
|
+
- **Population.** The project's scale/role definitions and authored declarations consuming them.
|
|
104
|
+
Include breakpoint rules, component variants, and any declared fluid sizing formulas.
|
|
105
|
+
- **Reading.** Resolve each treatment to its role or accepted step. Report undeclared values,
|
|
106
|
+
missing generated selectors, `em` font sizes, and `.small` nested inside `.small`. Validate fluid formulas against their declared bounds; do not reject
|
|
107
|
+
legitimate intermediate computed values as off-scale. Confirm required grouping relationships in
|
|
108
|
+
the rendered review rather than inferring them from token names.
|
|
109
|
+
- **Negative control.** Feed an undeclared spacing value and append an off-scale type declaration
|
|
110
|
+
through the stylesheet extractor. Report both. Accept a declared fluid value inside its bounds.
|
|
111
|
+
- **Coverage.** This checks consistency with a system, not whether the system suits the task. A
|
|
112
|
+
perfectly on-scale layout can still have ambiguous grouping, poor line breaks, or the wrong density.
|
|
106
113
|
|
|
107
114
|
## Custom rule doing a utility's job
|
|
108
115
|
|
|
109
|
-
- **Property.**
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
- **
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
116
|
+
- **Property.** Each authored selector expresses a need no shipped utility expresses, or records
|
|
117
|
+
why the utility does not fit. Declared component-variable overrides and generated utilities stay
|
|
118
|
+
on their extension rung; they are not automatically bespoke styling violations.
|
|
119
|
+
- **Population.** Project-authored selectors, their declarations, and the loaded utility rules.
|
|
120
|
+
- **Reading.** Compare declarations and name the equivalent utility when one exists. Report a
|
|
121
|
+
duplicate without a recorded reason. Read mixed-purpose rules too; adding an unrelated declaration
|
|
122
|
+
does not excuse the duplicated part.
|
|
123
|
+
- **Negative control.** Feed a rule that exactly repeats a shipped padding utility, then append it
|
|
124
|
+
through the stylesheet extractor. Report it in both runs.
|
|
125
|
+
- **Coverage.** This checks expressible equivalence, not the intent or merit of an exception. Review
|
|
126
|
+
the reason and styling-rung authorization separately; specificity and state scope can matter.
|
|
127
|
+
|
|
128
|
+
## Color-mode inheritance
|
|
129
|
+
|
|
130
|
+
- **Property.** Ordinary content inherits its body or component foreground. Quiet adaptive fills
|
|
131
|
+
add no arbitrary text color. Intentional solid and local-mode boundaries own a measured pair;
|
|
132
|
+
native component states retain their foreground behavior. Take the contract from
|
|
133
|
+
[color-modes.md](color-modes.md).
|
|
134
|
+
- **Population.** Rendered text, status marks, badges, tags, links, fields, selected controls, table
|
|
135
|
+
cells, and overlays in the actual loaded build. Include supported nested modes, skin overrides,
|
|
136
|
+
and portal mount points; name the boundaries that own an explicit foreground.
|
|
137
|
+
- **Reading.** Drive the existing mounted tree from light to dark and back. Read computed text,
|
|
138
|
+
painted backgrounds, relevant custom properties, and winning declarations after each transition.
|
|
139
|
+
Confirm quiet ordinary text matches its intended inherited foreground; identify the owner when
|
|
140
|
+
a component legitimately differs. Check supported system preference and reload behavior when the
|
|
141
|
+
mode controller is in scope. A class-name match or a changing variable alone does not pass.
|
|
142
|
+
- **Negative control.** Add fixed `text-dark` on a dark body surface, a stock `.badge` with a subtle
|
|
143
|
+
fill but no inheritance reset in light mode, and an opposite-mode plain region without its owned
|
|
144
|
+
foreground/background pair. Require the reader to detect each violated contract. For projects
|
|
145
|
+
using aliases, add a root-resolved foreground alias inherited into an opposite-mode scope.
|
|
146
|
+
Verify each control is invalid in that build; a class name alone does not establish the defect.
|
|
147
|
+
- **Coverage.** Pair the cascade reading with Composited contrast; correct inheritance can still
|
|
148
|
+
produce insufficient contrast on a changed surface. An isolated stock fixture establishes only
|
|
149
|
+
that fixture's behavior, not the host skin or application. Unreached states and mounts stay open.
|
|
119
150
|
|
|
120
151
|
## Composited contrast in both themes
|
|
121
152
|
|
|
122
|
-
- **Property.** Every pairing the
|
|
123
|
-
|
|
124
|
-
- **Population.**
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
pairing
|
|
129
|
-
the bars.
|
|
130
|
-
- **Negative control.**
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
the layers under it. Together they measure what rendered, in the themes and viewports the run
|
|
138
|
-
entered. A pairing that appears only in a state the run never reached is unmeasured, so name the
|
|
139
|
-
states the run covered beside the result.
|
|
153
|
+
- **Property.** Every measured pairing meets the package bar: 4.5:1 for information-bearing text,
|
|
154
|
+
3:1 for meaningful textless marks and state/focus chrome, in each declared theme and reached state.
|
|
155
|
+
- **Population.** Rendered text and meaningful graphics, their actual surfaces, and all paint layers
|
|
156
|
+
affecting contrast. Name exemptions for disabled controls; do not exempt readable metadata.
|
|
157
|
+
- **Reading.** Composite translucent backgrounds onto the opaque base and translucent foregrounds
|
|
158
|
+
onto that result before calculating contrast. Include ancestor opacity where relevant. Report the
|
|
159
|
+
pairing, ratio, bar, theme, and state for each failure. Take the mechanics from
|
|
160
|
+
[bootstrap-reference.md](bootstrap-reference.md) → Measuring the bars.
|
|
161
|
+
- **Negative control.** Feed an opaque pair known to fail and a translucent stack whose composited
|
|
162
|
+
ratio fails although a flat read would pass. Append both through the rendered-pair extractor and
|
|
163
|
+
require all failures. Include the same theme scopes and paint mechanism as the production run.
|
|
164
|
+
- **Coverage.** Flat computed colors cannot settle text over images, gradients, masks, blend modes,
|
|
165
|
+
or unsupported compositing. Read the actual background under the text with an appropriate method,
|
|
166
|
+
or mark the pairing open. Never average an image into a passing color. Name unvisited states;
|
|
167
|
+
measurements from one surface, theme, or crop do not establish another.
|
|
140
168
|
|
|
141
169
|
## One glyph, one meaning
|
|
142
170
|
|
|
143
|
-
- **Property.** Each status meaning takes one glyph
|
|
144
|
-
|
|
145
|
-
- **Population.** The
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
- **Negative control.**
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
171
|
+
- **Property.** Each registered status meaning takes one glyph; each registered glyph serves one
|
|
172
|
+
status meaning and resolves in the icon set the product ships.
|
|
173
|
+
- **Population.** The surface's status registry and the shipped icon set. Keep generic action icons
|
|
174
|
+
outside this status-only contract unless the project explicitly includes them.
|
|
175
|
+
- **Reading.** Report duplicate meanings, a status glyph bound to two meanings, and missing glyphs.
|
|
176
|
+
- **Negative control.** Feed a second meaning for a registered glyph and an unavailable glyph name;
|
|
177
|
+
append equivalent invalid entries through the registry extractor. Report both kinds of failure.
|
|
178
|
+
- **Coverage.** This proves registry consistency, not that the markup uses the correct glyph or that
|
|
179
|
+
its optical size and contrast work. Capture the states that use the marks and inspect their names.
|
|
180
|
+
|
|
181
|
+
## Responsive task and reflow
|
|
182
|
+
|
|
183
|
+
- **Property.** The declared task remains readable and operable without unintended page overflow,
|
|
184
|
+
concealed content, or clipped controls at the widths in [responsive-layout.md](responsive-layout.md).
|
|
185
|
+
- **Population.** Changed routes, responsive regions, required task fields/actions, local scrollers,
|
|
186
|
+
and their reached data states. Include conditional content and loaded fonts/assets. Name the
|
|
187
|
+
Bootstrap build and every environment substitution; a missing dependency is not a passing page.
|
|
188
|
+
- **Reading.** Record viewport and container bounds, document width, local client/scroll dimensions,
|
|
189
|
+
critical text bounds, effective target sizes, and required content/action visibility. Check both
|
|
190
|
+
sides of each actual transition. Use a small declared rounding tolerance. Keep intentional data
|
|
191
|
+
scrolling separate from document overflow; identify the owner and prove reach to its final item.
|
|
192
|
+
Read task regions as well as `documentElement.scrollWidth`; hidden overflow is not a repair.
|
|
193
|
+
- **Negative control.** Feed a too-wide region to the bounds reader; append an oversized child,
|
|
194
|
+
conceal it behind a clipping parent, and hide a required primary action in separate harness runs.
|
|
195
|
+
Each defect must be reported by the same production extraction path. Include a positive local
|
|
196
|
+
table scroller so the reader cannot pass by banning all overflow.
|
|
197
|
+
- **Coverage.** Test 320/390 CSS px, a wide view, each used boundary, long content, and short height.
|
|
198
|
+
Record enlarged-text and real browser-zoom tests separately. Reducing the viewport is a reflow
|
|
199
|
+
proxy, not execution of 400% browser zoom. Geometry does not establish aesthetics, full text
|
|
200
|
+
contrast, real-device keyboard behavior, or an exhaustive accessibility result.
|
|
201
|
+
|
|
202
|
+
## Responsive interaction continuity
|
|
203
|
+
|
|
204
|
+
- **Property.** Narrow/wide changes preserve access, state, and meaningful focus; responsive chrome
|
|
205
|
+
does not leave a stale overlay, scroll lock, or trap.
|
|
206
|
+
- **Population.** Navigation triggers/panels, forms, selections, filters, sort/pagination, disclosures,
|
|
207
|
+
and overlays changed by a breakpoint. Record which controls are functional and which are fixtures.
|
|
208
|
+
- **Reading.** Complete the narrow primary flow. Open/close navigation with pointer and keyboard,
|
|
209
|
+
test Escape/focus return, resize while open, and return below the threshold. Carry selected IDs,
|
|
210
|
+
filters, sort, field values, and active detail context through both directions. Check reachable
|
|
211
|
+
dialog actions in a short viewport and with enlarged text. Confirm actual row/filter changes,
|
|
212
|
+
not merely `aria-sort`, labels, or a success message.
|
|
213
|
+
- **Negative control.** Remove the required narrow trigger, break its target, and erase a selected
|
|
214
|
+
record during a harness resize. Drive the same interaction assertions; each must fail. Mark an
|
|
215
|
+
absent component not applicable rather than treating an empty locator set as success.
|
|
216
|
+
- **Coverage.** Desktop mouse, keyboard, and emulated touch are separate runs. Keep real-device
|
|
217
|
+
browser chrome/soft keyboard, unsupported engines, persistence, and server actions open unless
|
|
218
|
+
exercised. For dual presentations, inspect IDs and the accessibility tree: only the active view
|
|
219
|
+
may expose its controls. Attribute presence alone does not establish any interaction result.
|
|
220
|
+
|
|
221
|
+
## Rendered design review
|
|
222
|
+
|
|
223
|
+
Use captures for these judgments, not synthetic negative controls. Record the criterion, capture,
|
|
224
|
+
viewport/theme/state, finding, and disposition. A missing capture leaves the judgment open. For a
|
|
225
|
+
requested review round or campaign, use `orkestrel-polish-surface` rather than creating one here.
|
|
226
|
+
|
|
227
|
+
- **Task and hierarchy:** the main information and action lead; supporting content remains readable;
|
|
228
|
+
labels, semantics, and destructive rank match the work. Check a grayscale view as a hierarchy aid.
|
|
229
|
+
- **Grouping and density:** inter-group gaps exceed internal gaps; labels/help/errors stay with the
|
|
230
|
+
right control after wrapping. Width serves the content; rails, forms, and tables use it deliberately.
|
|
231
|
+
- **Type and reflow:** line length, baseline alignment, line-height, numeric comparison, and fallback
|
|
232
|
+
text work at the declared widths and enlarged text. No essential content is clipped or hidden.
|
|
233
|
+
- **Color, depth, and imagery:** light/dark transitions preserve hierarchy without gratuitous text overrides; color has a second encoding;
|
|
234
|
+
elevation describes layers; crops and icon sizes preserve useful detail; the frame stays quiet.
|
|
235
|
+
- **States and restraint:** first-use, filtered-empty, loading, partial, and error retain a useful
|
|
236
|
+
next step. Long or missing content holds up. The signature belongs to the brief; accessories do not
|
|
237
|
+
compete with the task. Motion-free operation remains complete.
|
|
238
|
+
|
|
239
|
+
A visual review does not establish keyboard behavior, contrast arithmetic, or full WCAG conformance.
|
|
240
|
+
Pair each such claim with the relevant instrument or interaction test and its actual coverage.
|
|
154
241
|
|
|
155
242
|
## When an authored rule is already earned
|
|
156
243
|
|
|
157
|
-
Leave rung 4 to the developer, per [SKILL.md](../SKILL.md) → When custom CSS is justified. Write
|
|
158
|
-
|
|
244
|
+
Leave rung 4 to the developer, per [SKILL.md](../SKILL.md) → When custom CSS is justified. Write a
|
|
245
|
+
rule without asking only when every condition holds:
|
|
159
246
|
|
|
160
|
-
- an instrument
|
|
161
|
-
status text
|
|
162
|
-
|
|
163
|
-
-
|
|
164
|
-
- the rule
|
|
165
|
-
|
|
247
|
+
- an instrument reports a vendor failure against a stated requirement, such as a focus ring below
|
|
248
|
+
3:1 or information-bearing status text below 4.5:1;
|
|
249
|
+
- the rule cites the instrument, failing reading, and required bar beside it;
|
|
250
|
+
- rungs 1–3 cannot restore the requirement, and the rule repairs that failure without unrelated polish;
|
|
251
|
+
- the rule uses `--bs-*` paint tokens and declared scales, and the repaired result is re-measured in
|
|
252
|
+
every affected theme and state.
|
|
166
253
|
|
|
167
|
-
Treat anything wider as a proposal: name
|
|
254
|
+
A visual preference alone does not open this exception. Treat anything wider as a proposal: name
|
|
255
|
+
what the rule would buy and stop until authorized.
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# Responsive layout
|
|
2
|
+
|
|
3
|
+
> Part of the `enterprise-bootstrap` package. Use before composing a screen, shell, toolbar,
|
|
4
|
+
> form, overlay, or data view. Operate layer: [SKILL.md](../SKILL.md).
|
|
5
|
+
|
|
6
|
+
## Contents
|
|
7
|
+
|
|
8
|
+
- [Declare the contract](#declare-the-contract)
|
|
9
|
+
- [Build the base](#build-the-base)
|
|
10
|
+
- [Expand by available space](#expand-by-available-space)
|
|
11
|
+
- [Keep the task intact](#keep-the-task-intact)
|
|
12
|
+
- [Handle navigation and overlays](#handle-navigation-and-overlays)
|
|
13
|
+
- [Prove the result](#prove-the-result)
|
|
14
|
+
|
|
15
|
+
## Declare the contract
|
|
16
|
+
|
|
17
|
+
Record one row per distinct region before writing its layout. Reuse a region's contract instead
|
|
18
|
+
of repeating it on every screen. Take the host's supported range; absent one, prove normal content
|
|
19
|
+
at 320 CSS px and compose first at a representative 390 CSS px. These are verification widths,
|
|
20
|
+
not new Bootstrap breakpoints or guarantees about physical devices.
|
|
21
|
+
|
|
22
|
+
| Region | Narrow behavior | Expansion condition | Information/actions retained | Overflow |
|
|
23
|
+
| ---------------- | ------------------------------------------------------------- | --------------------------------------- | -------------------------------------------------- | ---------------------------- |
|
|
24
|
+
| Navigation | Named trigger opens a drawer | Rail plus usable main content fit | Same destinations and current state | Drawer body only when needed |
|
|
25
|
+
| Search/actions | Search and actions stack; filters wrap or disclose | Labels and hit areas fit together | Search, active filters, clear path, primary action | None |
|
|
26
|
+
| Record list | Identity, decision fields, primary action; details disclosure | Comparison columns fit beside any rail | Same data, sorting, selection, actions | None for the list |
|
|
27
|
+
| Comparison table | Named, keyboard-operable local scroller | Columns fit without a scroller | All comparison columns and row identity | Table region only |
|
|
28
|
+
| Form/dialog | One reading column; natural height | Related fields or explanation have room | Labels, errors, consequences, cancel/commit | One vertical owner |
|
|
29
|
+
| Hero/preview | Copy, actions, then legible evidence | Both columns remain useful | Thesis, primary action, useful demonstration | Decorative layer only |
|
|
30
|
+
|
|
31
|
+
Name the actual thresholds used and why. Do not give every region the same breakpoint by habit.
|
|
32
|
+
Build and use the narrow primary flow before adding desktop chrome or finishing details.
|
|
33
|
+
|
|
34
|
+
## Build the base
|
|
35
|
+
|
|
36
|
+
Use Bootstrap's mobile-first direction: unprefixed rules apply from the smallest width; `sm`,
|
|
37
|
+
`md`, `lg`, `xl`, and `xxl` add behavior at their minimum widths. `xs` has no class infix.
|
|
38
|
+
Take the installed breakpoint map, not device labels, from
|
|
39
|
+
[Breakpoints & layout](bootstrap-reference.md#breakpoints--layout).
|
|
40
|
+
|
|
41
|
+
Prefer shipped structure before custom media queries:
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<!-- One field per row until the content supports a pair. -->
|
|
45
|
+
<div class="row g-3">
|
|
46
|
+
<div class="col-12 col-md-6"><!-- labelled field --></div>
|
|
47
|
+
<div class="col-12 col-md-6"><!-- related labelled field --></div>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
<!-- Stretch actions at the base; use their natural widths from sm. -->
|
|
51
|
+
<div class="d-grid gap-2 d-sm-flex flex-sm-wrap">
|
|
52
|
+
<button type="submit" class="btn btn-primary">Save changes</button>
|
|
53
|
+
<button type="button" class="btn btn-outline-secondary">Cancel</button>
|
|
54
|
+
</div>
|
|
55
|
+
|
|
56
|
+
<!-- Give search its own narrow row rather than crushing its input. -->
|
|
57
|
+
<form class="row g-2 align-items-end" role="search" aria-label="Find invoices">
|
|
58
|
+
<div class="col-12 col-md">
|
|
59
|
+
<label class="form-label" for="invoice-search">Search invoices</label>
|
|
60
|
+
<input class="form-control" id="invoice-search" type="search" />
|
|
61
|
+
</div>
|
|
62
|
+
<div class="col-12 col-sm-6 col-md-auto">
|
|
63
|
+
<label class="form-label" for="invoice-status">Status</label>
|
|
64
|
+
<select class="form-select" id="invoice-status">
|
|
65
|
+
<option>All statuses</option>
|
|
66
|
+
</select>
|
|
67
|
+
</div>
|
|
68
|
+
</form>
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Keep DOM order meaningful before arranging columns. Do not use visual `order-*` to separate focus
|
|
72
|
+
order from reading order. Use `p-3 p-lg-4` and `g-3 g-lg-4` to grow outer space independently of
|
|
73
|
+
control size. Keep `.row` gutters inside a compatible container or padded parent; do not add
|
|
74
|
+
unbudgeted `gap-*` to percentage columns whose widths already total the row.
|
|
75
|
+
|
|
76
|
+
Check the generated CSS. Stock width/height, overflow, and general position utilities do not all
|
|
77
|
+
ship breakpoint variants. Do not invent `w-md-auto`, `overflow-lg-auto`, `position-lg-sticky`, or
|
|
78
|
+
`min-w-0`. Responsive sticky helpers are a separate shipped family. Take missing roles through
|
|
79
|
+
[Layout and type extensions](bootstrap-reference.md#layout-and-type-extensions).
|
|
80
|
+
|
|
81
|
+
## Expand by available space
|
|
82
|
+
|
|
83
|
+
Measure the content container after rails, gutters, and panel padding. A wide viewport can contain
|
|
84
|
+
a narrow main region, split pane, or dialog. Delay columns, keep an intrinsic layout, or use an
|
|
85
|
+
authorized container-query extension when reuse requires it. A viewport breakpoint alone does not
|
|
86
|
+
prove the component fits.
|
|
87
|
+
|
|
88
|
+
Let flex/grid children shrink: use the project's zero-inline-minimum role and, for custom grids,
|
|
89
|
+
`minmax(0, 1fr)` where appropriate. Break long identifiers at safe opportunities; expose complete
|
|
90
|
+
values through a usable detail view when truncation is unavoidable. Never shrink amounts, labels,
|
|
91
|
+
or input text to rescue a desktop row. Let identity/amount headers wrap independently and bound
|
|
92
|
+
long action labels to their container; a wrapping parent does not constrain an oversized child.
|
|
93
|
+
Preserve native input scrolling for long editable values.
|
|
94
|
+
|
|
95
|
+
Use a content-led maximum width, not an unconditional fixed width or `vw-100` inside a padded
|
|
96
|
+
container. Let content set height. Prefer ordinary page scrolling to a phone-sized nested viewport;
|
|
97
|
+
reserve bounded table scrolling for a documented comparison task. Do not use `vh-100`, transforms,
|
|
98
|
+
CSS zoom, or root `overflow-x-hidden` to make an oversized layout appear to fit.
|
|
99
|
+
|
|
100
|
+
Keep large typography and presentation space responsive without shrinking body text or hit areas.
|
|
101
|
+
Bootstrap RFS scales supported type; it does not reflow navigation, dialogs, or preview content.
|
|
102
|
+
A readable line count beats mechanically preserving a desktop hero's proportions.
|
|
103
|
+
|
|
104
|
+
## Keep the task intact
|
|
105
|
+
|
|
106
|
+
Choose a data strategy by the task, not a fixed ranking:
|
|
107
|
+
|
|
108
|
+
- **Record work:** use a compact list or labelled stack when the job is finding and acting on one
|
|
109
|
+
record. Keep identity, status, amount, due date, and the relevant action directly discoverable;
|
|
110
|
+
put secondary details behind a named disclosure. Generate variants from one data/state model.
|
|
111
|
+
- **Comparison work:** retain a semantic table when column comparison is essential. Local horizontal
|
|
112
|
+
scrolling is valid; name the region, provide a scroll cue, and verify keyboard reach to both ends.
|
|
113
|
+
Keep search and pagination outside it. Do not turn every comparison into cards.
|
|
114
|
+
- **Priority columns:** omit a column from the narrow presentation only when the same information is
|
|
115
|
+
available through an operable detail path. `d-none` alone is not a content strategy.
|
|
116
|
+
|
|
117
|
+
Do not render two independent forms or state stores for narrow/wide variants. Keep IDs unique and
|
|
118
|
+
only the active representation in the accessibility/focus tree. Preserve filters, values, selected
|
|
119
|
+
record IDs, sort, and open-detail context across a live resize. Restore focus to the equivalent
|
|
120
|
+
visible control if its representation disappears; do not steal unrelated focus. Track the control
|
|
121
|
+
before hiding it: the browser may move focus to the body before a media-query listener runs.
|
|
122
|
+
A dialog closed after reflow returns to the visible equivalent of its original trigger.
|
|
123
|
+
|
|
124
|
+
Keep search and action bars in normal flow. Stack or wrap ordinary controls before considering a
|
|
125
|
+
scroller; put additional filters behind a working disclosure with active-filter count and reset.
|
|
126
|
+
Use a wrapping group of independent buttons or a select, not a joined `.btn-group` bent over two
|
|
127
|
+
rows. Keep consequential button labels visible. Preserve the current page and previous/next when
|
|
128
|
+
reducing a pager's numbered links.
|
|
129
|
+
|
|
130
|
+
Keep record actions outside a clipped table wrapper when necessary. Popper placement alone does
|
|
131
|
+
not guarantee escape from an overflow ancestor. Prefer a root-mounted dialog or an existing
|
|
132
|
+
portal implementation over z-index escalation.
|
|
133
|
+
|
|
134
|
+
Make touch targets comfortable without making text larger: prefer 44×44 CSS px for primary mobile
|
|
135
|
+
controls; retain the package's 24×24 minimum for every applicable target. Enlarge the actual button
|
|
136
|
+
or associated label, not merely the icon's surrounding decoration. Keep action affordances visible
|
|
137
|
+
without hover. Measure effective label hit areas for native checkboxes and switches.
|
|
138
|
+
|
|
139
|
+
## Handle navigation and overlays
|
|
140
|
+
|
|
141
|
+
Use `navbar-expand-*` or responsive `offcanvas-*` from the installed build. Match the trigger's
|
|
142
|
+
visibility threshold to the inline panel. Preserve one destination set, a named trigger, current
|
|
143
|
+
state, keyboard operation, Escape, and focus return. Exercise a drawer opened below a threshold,
|
|
144
|
+
resized above it, then returned below; no stale backdrop, body scroll lock, or invisible focus trap
|
|
145
|
+
may remain. Do not assume the host wrapper behaves exactly like the stock plugin.
|
|
146
|
+
|
|
147
|
+
Keep overlay width within the viewport and height content-led with an explicit vertical scroll
|
|
148
|
+
owner. Bootstrap's `modal-fullscreen-*-down` belongs to its modal structure, not a native `<dialog>`.
|
|
149
|
+
For native dialogs, declare a bounded logical size in the stylesheet when needed; keep consequences,
|
|
150
|
+
fields, safe dismissal, and commit reachable on short screens and with enlarged text. Check the
|
|
151
|
+
initial view as well as the scrolled footer. When action focus would hide the beginning, focus a
|
|
152
|
+
static top heading with `tabindex="-1"`; keep a safe dismissal in the tab sequence. Follow the
|
|
153
|
+
[dialog focus guidance](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/).
|
|
154
|
+
|
|
155
|
+
Let nonessential sticky chrome become static on narrow or short screens. Where fixed controls are
|
|
156
|
+
required, reserve their space, account for safe-area insets, and check focus visibility. Use a
|
|
157
|
+
supported dynamic viewport unit only for a genuine viewport-bound requirement; it does not prove
|
|
158
|
+
virtual-keyboard behavior. Test the soft keyboard and browser chrome on a real supported device,
|
|
159
|
+
or leave that coverage open.
|
|
160
|
+
|
|
161
|
+
Keep theme ownership intact during reflow. A dark hero or drawer on a light page establishes its
|
|
162
|
+
foreground/background at its boundary; ordinary descendants inherit. Take adaptive subtle fills
|
|
163
|
+
and exceptions from [color-modes.md](color-modes.md), not a separate mobile palette.
|
|
164
|
+
|
|
165
|
+
## Prove the result
|
|
166
|
+
|
|
167
|
+
Run [Responsive task and reflow](inspection.md#responsive-task-and-reflow) and
|
|
168
|
+
[Responsive interaction continuity](inspection.md#responsive-interaction-continuity). Check 320 and
|
|
169
|
+
390 CSS px, one wide view, and `b−1`, `b`, `b+1` for each used breakpoint; deduplicate overlaps.
|
|
170
|
+
Check narrow/short landscape, long unbroken identifiers, expanded copy, enlarged text, and the
|
|
171
|
+
states actually used. Cross light/dark with the important narrow/wide states.
|
|
172
|
+
|
|
173
|
+
Require both geometry and task evidence. A page with no horizontal overflow can still hide its
|
|
174
|
+
primary action, clip a menu, or push decision fields into an undiscoverable scroller. Conversely,
|
|
175
|
+
a valid local two-dimensional scroller is not a page-level reflow failure.
|
|
176
|
+
|
|
177
|
+
Capture narrow output first and inspect it before desktop. Preserve before/after evidence for
|
|
178
|
+
regressions; run known-invalid controls through the same readers. State the Bootstrap build,
|
|
179
|
+
browser, assets, CSS viewport, state, and exclusions. Do not call a screenshot, class scan, reduced
|
|
180
|
+
viewport, device-pixel-ratio change, or emulated touch a real-device or complete accessibility pass.
|
|
181
|
+
|
|
182
|
+
Take upstream behavior from Bootstrap's [breakpoints](https://getbootstrap.com/docs/5.3/layout/breakpoints/),
|
|
183
|
+
[grid](https://getbootstrap.com/docs/5.3/layout/grid/), [flex](https://getbootstrap.com/docs/5.3/utilities/flex/),
|
|
184
|
+
[offcanvas](https://getbootstrap.com/docs/5.3/components/offcanvas/), and
|
|
185
|
+
[tables](https://getbootstrap.com/docs/5.3/content/tables/). Distinguish this package's test matrix
|
|
186
|
+
from the requirements and two-dimensional-content exception in
|
|
187
|
+
[WCAG reflow](https://www.w3.org/WAI/WCAG22/Understanding/reflow.html).
|