@orkestrel/scaffold 0.0.65 → 0.0.67
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/dist/host/agents/skills/enterprise-bootstrap/SKILL.md +58 -38
- package/dist/host/agents/skills/enterprise-bootstrap/references/bootstrap-reference.md +63 -33
- package/dist/host/agents/skills/enterprise-bootstrap/references/color-modes.md +131 -16
- package/dist/host/agents/skills/enterprise-bootstrap/references/components.md +21 -13
- package/dist/host/agents/skills/enterprise-bootstrap/references/frontend-design.md +41 -46
- package/dist/host/agents/skills/enterprise-bootstrap/references/inputs.md +37 -29
- package/dist/host/agents/skills/enterprise-bootstrap/references/inspection.md +51 -16
- package/dist/host/agents/skills/enterprise-bootstrap/references/responsive-layout.md +57 -7
- package/dist/host/agents/skills/enterprise-bootstrap/references/utilities.md +11 -6
- package/dist/host/claude/agents/orkestrel.md +24 -24
- package/dist/host/claude/skills/enterprise-bootstrap/SKILL.md +1 -1
- package/dist/host/manifest.json +12 -12
- 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 +0 -0
- package/dist/src/core/index.cjs +8 -8
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.js +8 -8
- package/dist/src/core/index.js.map +1 -1
- package/package.json +8 -8
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
Pick an affordance from what the person is asked for, not from the name a schema gives the field.
|
|
4
4
|
Where one category draws several ways, let the density and the list size decide.
|
|
5
5
|
|
|
6
|
+
Each **Default** and **Alternate** names the styling rung it sits on. Take the rung names and their
|
|
7
|
+
order from [SKILL.md](../SKILL.md) → The styling ladder.
|
|
8
|
+
|
|
6
9
|
Read [The fixed state set](#the-fixed-state-set) before the catalog: every affordance handles that
|
|
7
10
|
same set, and each category names only what it adds or changes. Take the data states a whole surface
|
|
8
11
|
ships — ideal, empty, loading, partial, error — from
|
|
@@ -52,13 +55,14 @@ value is a set.
|
|
|
52
55
|
switches without shrinking the text. Emulated viewport tests do not prove soft-keyboard behavior.
|
|
53
56
|
|
|
54
57
|
- **Keep a read-only field on the same affordance the edit state uses.** Take `readonly`, or
|
|
55
|
-
`disabled` plus a carrier, and neutralize the chrome with one transparent combination
|
|
56
|
-
|
|
57
|
-
|
|
58
|
+
`disabled` plus a carrier, and neutralize the chrome with one transparent combination the project
|
|
59
|
+
declares by name in its own stylesheet and token layer. The project chooses that combination; this
|
|
60
|
+
skill prescribes none. Reuse the declared name rather than retyping the utilities at each site.
|
|
61
|
+
Never swap to `form-control-plaintext`: it drops the horizontal padding,
|
|
58
62
|
so the read view and the edit view reflow against each other.
|
|
59
63
|
- **Give a locked select `disabled` and a hidden input beside it.** A native select cannot be
|
|
60
64
|
read-only, so `disabled` stops its value submitting and the hidden input carries that value.
|
|
61
|
-
- **Verify a chosen filter in
|
|
65
|
+
- **Verify a chosen filter in every declared theme.** Keep its native checked/pressed state and a
|
|
62
66
|
distinguishable visual treatment; take selection rules from [components.md](components.md) →
|
|
63
67
|
Selection fills. Do not prescribe an accent color as a substitute for that check.
|
|
64
68
|
- **Keep native control foregrounds and states.** For quiet chip or group backgrounds, inherit
|
|
@@ -78,7 +82,9 @@ value is a set.
|
|
|
78
82
|
|
|
79
83
|
### One line of text
|
|
80
84
|
|
|
81
|
-
**Default.** An `input.form-control` under its own `label.form-label`, at rung
|
|
85
|
+
**Default.** An `input.form-control` under its own `label.form-label`, at the component rung.
|
|
86
|
+
|
|
87
|
+
The stock control border is `var(--bs-border-color)` — 1.3:1 on the light body and 1.9:1 on the dark one — so it is decorative; the label, the field's fill against the page, and the focus ring carry recognition. Where the boundary is the only cue (a field on a same-color surface), set `--bs-border-color: var(--bs-secondary-color)` on the form scope — adaptive, about 5.6:1 light and 7:1 dark — and re-measure; never a fixed `border-dark`.
|
|
82
88
|
|
|
83
89
|
```html
|
|
84
90
|
<label for="account-name" class="form-label">Account name</label>
|
|
@@ -97,7 +103,7 @@ declared transparent combination rather than dropping the control.
|
|
|
97
103
|
### Text over many lines
|
|
98
104
|
|
|
99
105
|
**Default.** A `textarea.form-control` with a `rows` attribute sized to the expected answer, at
|
|
100
|
-
rung
|
|
106
|
+
the component rung.
|
|
101
107
|
|
|
102
108
|
```html
|
|
103
109
|
<label for="incident-notes" class="form-label">Notes</label>
|
|
@@ -114,7 +120,7 @@ count in the `.form-text`, and keep it out of a live region unless the cap is cl
|
|
|
114
120
|
|
|
115
121
|
### A secret
|
|
116
122
|
|
|
117
|
-
**Default.** An `input[type=password].form-control` under a visible label, at rung
|
|
123
|
+
**Default.** An `input[type=password].form-control` under a visible label, at the component rung.
|
|
118
124
|
|
|
119
125
|
```html
|
|
120
126
|
<label for="passphrase" class="form-label">Passphrase</label>
|
|
@@ -133,8 +139,8 @@ one-time code the person must read back.
|
|
|
133
139
|
|
|
134
140
|
### A number
|
|
135
141
|
|
|
136
|
-
**Default.** An `input[type=number].form-control`, at rung
|
|
137
|
-
`text-end font-monospace` so the digits align, at rung
|
|
142
|
+
**Default.** An `input[type=number].form-control`, at the component rung. In a column of figures add
|
|
143
|
+
`text-end font-monospace` so the digits align, at the utility rung.
|
|
138
144
|
|
|
139
145
|
```html
|
|
140
146
|
<label for="unit-count" class="form-label">Units</label>
|
|
@@ -149,7 +155,7 @@ than a quantity, take the one-line-of-text category instead.
|
|
|
149
155
|
|
|
150
156
|
### A number in a bounded range
|
|
151
157
|
|
|
152
|
-
**Default.** An `input.form-range`, at rung
|
|
158
|
+
**Default.** An `input.form-range`, at the component rung, and only when a minimum, a maximum, and a step are all
|
|
153
159
|
fixed.
|
|
154
160
|
|
|
155
161
|
```html
|
|
@@ -168,7 +174,7 @@ hand-roll: Bootstrap ships one thumb per input.
|
|
|
168
174
|
|
|
169
175
|
### A date
|
|
170
176
|
|
|
171
|
-
**Default.** An `input[type=date].form-control`, at rung
|
|
177
|
+
**Default.** An `input[type=date].form-control`, at the component rung. Take the calendar, the keyboard model,
|
|
172
178
|
and the locale format from the platform rather than authoring any of them.
|
|
173
179
|
|
|
174
180
|
```html
|
|
@@ -184,7 +190,7 @@ help text, because a native picker takes no per-day exclusion.
|
|
|
184
190
|
|
|
185
191
|
### A time
|
|
186
192
|
|
|
187
|
-
**Default.** An `input[type=time].form-control`, at rung
|
|
193
|
+
**Default.** An `input[type=time].form-control`, at the component rung, with `step` set to the granularity the
|
|
188
194
|
value actually carries.
|
|
189
195
|
|
|
190
196
|
```html
|
|
@@ -200,7 +206,7 @@ select is the lighter control.
|
|
|
200
206
|
|
|
201
207
|
### A date and time
|
|
202
208
|
|
|
203
|
-
**Default.** An `input[type=datetime-local].form-control`, at rung
|
|
209
|
+
**Default.** An `input[type=datetime-local].form-control`, at the component rung.
|
|
204
210
|
|
|
205
211
|
```html
|
|
206
212
|
<label for="window-opens" class="form-label">Window opens</label>
|
|
@@ -215,7 +221,7 @@ stored in; a local datetime carries none.
|
|
|
215
221
|
|
|
216
222
|
### A color
|
|
217
223
|
|
|
218
|
-
**Default.** An `input.form-control-color[type=color]`, at rung
|
|
224
|
+
**Default.** An `input.form-control-color[type=color]`, at the component rung.
|
|
219
225
|
|
|
220
226
|
```html
|
|
221
227
|
<label for="brand-tint" class="form-label">Brand tint</label>
|
|
@@ -223,7 +229,8 @@ stored in; a local datetime carries none.
|
|
|
223
229
|
```
|
|
224
230
|
|
|
225
231
|
**Alternates.** Pair the swatch with a text field when the value is copied, pasted, or read aloud
|
|
226
|
-
between people.
|
|
232
|
+
between people. Hold the swatch to the target floor in
|
|
233
|
+
[bootstrap-reference.md](bootstrap-reference.md) → WCAG 2.2 requirements for app UI.
|
|
227
234
|
|
|
228
235
|
**States.** The fixed set. A color input has no empty value, so give the field a default and say what
|
|
229
236
|
it is.
|
|
@@ -231,7 +238,7 @@ it is.
|
|
|
231
238
|
### One on/off answer
|
|
232
239
|
|
|
233
240
|
**Default.** A `.form-check` holding one `input.form-check-input[type=checkbox]` and its
|
|
234
|
-
`label.form-check-label`, at rung
|
|
241
|
+
`label.form-check-label`, at the component rung.
|
|
235
242
|
|
|
236
243
|
```html
|
|
237
244
|
<div class="form-check">
|
|
@@ -250,7 +257,7 @@ flight, and reverts visibly when it fails.
|
|
|
250
257
|
|
|
251
258
|
### One of a few
|
|
252
259
|
|
|
253
|
-
**Default.** A radio group: `fieldset` and `legend` around `.form-check` rows, at rung
|
|
260
|
+
**Default.** A radio group: `fieldset` and `legend` around `.form-check` rows, at the component rung.
|
|
254
261
|
|
|
255
262
|
```html
|
|
256
263
|
<fieldset>
|
|
@@ -266,7 +273,7 @@ flight, and reverts visibly when it fails.
|
|
|
266
273
|
</fieldset>
|
|
267
274
|
```
|
|
268
275
|
|
|
269
|
-
**Alternates.** Take a segmented `.btn-group` of `.btn-check` radios, at rung
|
|
276
|
+
**Alternates.** Take a segmented `.btn-group` of `.btn-check` radios, at the utility rung, when the choice
|
|
270
277
|
sits in a toolbar or a filter bar and every option fits on one row without wrapping; give the group
|
|
271
278
|
`role="radiogroup"` and one accessible name. A radio group and a segmented group draw the same
|
|
272
279
|
question, and the list size decides between them. Verify the chosen-state contract rather than
|
|
@@ -277,7 +284,7 @@ name it in the message, and keep the error under the last row.
|
|
|
277
284
|
|
|
278
285
|
### One of many
|
|
279
286
|
|
|
280
|
-
**Default.** A `select.form-select`, at rung
|
|
287
|
+
**Default.** A `select.form-select`, at the component rung.
|
|
281
288
|
|
|
282
289
|
```html
|
|
283
290
|
<label for="territory" class="form-label">Territory</label>
|
|
@@ -297,7 +304,7 @@ hidden input. A select whose options are loading is `busy`.
|
|
|
297
304
|
|
|
298
305
|
### One of many with an unlisted value admitted
|
|
299
306
|
|
|
300
|
-
**Default.** An `input.form-control` bound to a `<datalist>`, at rung
|
|
307
|
+
**Default.** An `input.form-control` bound to a `<datalist>`, at the component rung. The list suggests; the
|
|
301
308
|
person can still submit a value it does not hold.
|
|
302
309
|
|
|
303
310
|
```html
|
|
@@ -316,7 +323,7 @@ re-target every test and journey that finds this field by role.
|
|
|
316
323
|
|
|
317
324
|
### Any of a few
|
|
318
325
|
|
|
319
|
-
**Default.** `fieldset` and `legend` around `.form-check` checkbox rows sharing one name, at rung
|
|
326
|
+
**Default.** `fieldset` and `legend` around `.form-check` checkbox rows sharing one name, at the component rung.
|
|
320
327
|
|
|
321
328
|
```html
|
|
322
329
|
<fieldset>
|
|
@@ -338,7 +345,7 @@ text and validate it on the group.
|
|
|
338
345
|
|
|
339
346
|
### Any of many
|
|
340
347
|
|
|
341
|
-
**Default.** A bounded, scrollable list of `.form-check` rows inside a bordered box, at rung
|
|
348
|
+
**Default.** A bounded, scrollable list of `.form-check` rows inside a bordered box, at the utility rung, with
|
|
342
349
|
a filter field preceding it so the person can narrow the list before choosing.
|
|
343
350
|
|
|
344
351
|
```html
|
|
@@ -362,7 +369,7 @@ one-action way to clear it.
|
|
|
362
369
|
|
|
363
370
|
### A value picked from a searched list
|
|
364
371
|
|
|
365
|
-
**Default.** A combobox composed from shipped classes at rung
|
|
372
|
+
**Default.** A combobox composed from shipped classes at the utility rung, with the keyboard model
|
|
366
373
|
hand-rolled against the APG combobox pattern: an `input.form-control` carrying `role="combobox"`,
|
|
367
374
|
`aria-expanded`, `aria-controls`, `aria-autocomplete="list"`, and `aria-activedescendant`, over a
|
|
368
375
|
`ul.dropdown-menu[role=listbox]` of `.dropdown-item` buttons.
|
|
@@ -395,7 +402,7 @@ the input stays operable throughout.
|
|
|
395
402
|
|
|
396
403
|
### Files
|
|
397
404
|
|
|
398
|
-
**Default.** An `input[type=file].form-control`, at rung
|
|
405
|
+
**Default.** An `input[type=file].form-control`, at the component rung.
|
|
399
406
|
|
|
400
407
|
```html
|
|
401
408
|
<label for="statement" class="form-label">Statement</label>
|
|
@@ -413,7 +420,7 @@ toast.
|
|
|
413
420
|
|
|
414
421
|
### An ordered set of tags
|
|
415
422
|
|
|
416
|
-
**Default.** Bootstrap ships no tags input. Compose one at rung
|
|
423
|
+
**Default.** Bootstrap ships no tags input. Compose one at the utility rung from a text field that commits on
|
|
417
424
|
Enter plus a row of quiet chips, each carrying a `btn-close` with its own accessible name.
|
|
418
425
|
Use a utility-composed span so text inherits and the close control retains its normal font size.
|
|
419
426
|
|
|
@@ -432,7 +439,8 @@ Use a utility-composed span so text inherits and the close control retains its n
|
|
|
432
439
|
```
|
|
433
440
|
|
|
434
441
|
Keep tag text inherited and let the close icon follow the active mode. Measure the close button
|
|
435
|
-
against the chip and its hit area against the
|
|
442
|
+
against the chip and its hit area against the target floor in
|
|
443
|
+
[bootstrap-reference.md](bootstrap-reference.md) → WCAG 2.2 requirements for app UI. Take a retained `.badge`
|
|
436
444
|
through [color-modes.md](color-modes.md) → Badges and removable tags.
|
|
437
445
|
|
|
438
446
|
**Alternates.** Where the tags come from a fixed vocabulary, this is the any-of-many category and the
|
|
@@ -444,10 +452,10 @@ control per chip.
|
|
|
444
452
|
|
|
445
453
|
### A rating
|
|
446
454
|
|
|
447
|
-
**Default.** Bootstrap ships no rating. Draw the interactive form as a radio group at rung
|
|
455
|
+
**Default.** Bootstrap ships no rating. Draw the interactive form as a radio group at the utility rung — one
|
|
448
456
|
radio per value, restyled through `.btn-check` — so the keyboard model, the name, and the submitted
|
|
449
457
|
value come from the platform. Star chrome over that structure is an authored class contract at
|
|
450
|
-
rung
|
|
458
|
+
the authored rung.
|
|
451
459
|
|
|
452
460
|
```html
|
|
453
461
|
<fieldset>
|
|
@@ -467,7 +475,7 @@ per [components.md](components.md) → Status glyph marks; it is not a control.
|
|
|
467
475
|
|
|
468
476
|
### A step in a sequence
|
|
469
477
|
|
|
470
|
-
**Default.** Draw a step indicator from shipped parts at rung
|
|
478
|
+
**Default.** Draw a step indicator from shipped parts at the component rung — a `nav` or `.list-group-numbered`
|
|
471
479
|
whose current item carries `aria-current="step"`, with a `.progress` bar over a long sequence. A step
|
|
472
480
|
indicator reports where the person is and holds no value, so it is not a field.
|
|
473
481
|
|
|
@@ -30,8 +30,9 @@ a pass label alone.
|
|
|
30
30
|
- [Declared design scales](#declared-design-scales)
|
|
31
31
|
- [Custom rule doing a utility's job](#custom-rule-doing-a-utilitys-job)
|
|
32
32
|
- [Color-mode inheritance](#color-mode-inheritance)
|
|
33
|
-
- [Composited contrast in
|
|
33
|
+
- [Composited contrast in every declared theme](#composited-contrast-in-every-declared-theme)
|
|
34
34
|
- [One glyph, one meaning](#one-glyph-one-meaning)
|
|
35
|
+
- [Fixed and adaptive pairing](#fixed-and-adaptive-pairing)
|
|
35
36
|
- [Responsive task and reflow](#responsive-task-and-reflow)
|
|
36
37
|
- [Responsive interaction continuity](#responsive-interaction-continuity)
|
|
37
38
|
- [Rendered design review](#rendered-design-review)
|
|
@@ -48,7 +49,7 @@ a pass label alone.
|
|
|
48
49
|
in the mounted tree separately; an unreachable stylesheet is an open dependency, not an empty one.
|
|
49
50
|
- **Negative control.** Feed an undefined styling token to the reader, then append a harness SVG
|
|
50
51
|
carrying that token through the same tree extractor. Both must be reported.
|
|
51
|
-
- **Coverage.** The
|
|
52
|
+
- **Coverage.** The controls cover set comparison and extraction, including SVG's non-string
|
|
52
53
|
`className`. Use `getAttribute('class')` or an equivalent safe reader. Resolution does not prove
|
|
53
54
|
the rule wins the cascade, paints the intended result, or covers a state never enumerated.
|
|
54
55
|
|
|
@@ -68,14 +69,22 @@ a pass label alone.
|
|
|
68
69
|
|
|
69
70
|
## Style escapes
|
|
70
71
|
|
|
71
|
-
- **Property.** Authored markup carries no `style` attribute
|
|
72
|
+
- **Property.** Authored markup carries no `style` attribute, and the surface's only `<style>`
|
|
73
|
+
element is the standalone-HTML project stylesheet in `<head>` that
|
|
74
|
+
[SKILL.md](../SKILL.md) → The styling ladder permits. A component-scoped `<style>` block fails.
|
|
72
75
|
- **Population.** Authored templates and the freshly mounted, undriven tree. Keep source and mounted
|
|
73
76
|
readings distinct so generated framework styles are not mistaken for authored declarations.
|
|
74
|
-
- **Reading.** Report inline declarations and
|
|
75
|
-
Record
|
|
76
|
-
|
|
77
|
+
- **Reading.** Report inline declarations and non-permitted style elements with their source or
|
|
78
|
+
element. Record each runtime exemption by producer, element, and the property it writes — never a
|
|
79
|
+
blanket component exemption, and never a producer that writes a property outside its purpose.
|
|
80
|
+
Bootstrap overlay positioning and conditional-visibility directives write runtime styles. The host
|
|
81
|
+
script for progress owns the `width` declaration on the elements specified in
|
|
82
|
+
[components.md](components.md) → Progress.
|
|
77
83
|
- **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
|
|
84
|
+
element and a component-scoped `<style>` element to the harness tree. Every non-exempt fixture
|
|
85
|
+
must be reported. Add a permitted fixture the reader must leave alone — the project stylesheet's
|
|
86
|
+
own `<head>` block, and a recorded runtime producer writing only its declared property — so the
|
|
87
|
+
reader cannot pass by rejecting every style element.
|
|
79
88
|
- **Coverage.** This covers authored and mount-time escapes, not later interactions or third-party
|
|
80
89
|
internals outside the declared scope. Drive later states separately when making claims about them.
|
|
81
90
|
|
|
@@ -134,7 +143,7 @@ a pass label alone.
|
|
|
134
143
|
- **Population.** Rendered text, status marks, badges, tags, links, fields, selected controls, table
|
|
135
144
|
cells, and overlays in the actual loaded build. Include supported nested modes, skin overrides,
|
|
136
145
|
and portal mount points; name the boundaries that own an explicit foreground.
|
|
137
|
-
- **Reading.** Drive the existing mounted tree
|
|
146
|
+
- **Reading.** Drive the existing mounted tree through every declared mode and back. Read computed text,
|
|
138
147
|
painted backgrounds, relevant custom properties, and winning declarations after each transition.
|
|
139
148
|
Confirm quiet ordinary text matches its intended inherited foreground; identify the owner when
|
|
140
149
|
a component legitimately differs. Check supported system preference and reload behavior when the
|
|
@@ -144,14 +153,15 @@ a pass label alone.
|
|
|
144
153
|
foreground/background pair. Require the reader to detect each violated contract. For projects
|
|
145
154
|
using aliases, add a root-resolved foreground alias inherited into an opposite-mode scope.
|
|
146
155
|
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
|
|
156
|
+
- **Coverage.** Pair the cascade reading with Composited contrast in every declared theme; correct inheritance can still
|
|
148
157
|
produce insufficient contrast on a changed surface. An isolated stock fixture establishes only
|
|
149
158
|
that fixture's behavior, not the host skin or application. Unreached states and mounts stay open.
|
|
150
159
|
|
|
151
|
-
## Composited contrast in
|
|
160
|
+
## Composited contrast in every declared theme
|
|
152
161
|
|
|
153
|
-
- **Property.** Every measured pairing meets the
|
|
154
|
-
|
|
162
|
+
- **Property.** Every measured pairing meets the bars in [SKILL.md](../SKILL.md) → Surfaces, color,
|
|
163
|
+
contrast, in each declared theme and reached state. That section owns the bars; read them there
|
|
164
|
+
rather than from a copy here.
|
|
155
165
|
- **Population.** Rendered text and meaningful graphics, their actual surfaces, and all paint layers
|
|
156
166
|
affecting contrast. Name exemptions for disabled controls; do not exempt readable metadata.
|
|
157
167
|
- **Reading.** Composite translucent backgrounds onto the opaque base and translucent foregrounds
|
|
@@ -178,6 +188,31 @@ a pass label alone.
|
|
|
178
188
|
- **Coverage.** This proves registry consistency, not that the markup uses the correct glyph or that
|
|
179
189
|
its optical size and contrast work. Capture the states that use the marks and inspect their names.
|
|
180
190
|
|
|
191
|
+
## Fixed and adaptive pairing
|
|
192
|
+
|
|
193
|
+
- **Property.** Every text, icon, and border color resolves against the surface it sits on with
|
|
194
|
+
tokens of the same kind: adaptive on adaptive, or fixed on a fixed fill that names its own
|
|
195
|
+
foreground or carries a `data-bs-theme` scope.
|
|
196
|
+
- **Population.** Every element with a color class, and every component with a fixed foreground
|
|
197
|
+
or fill (`btn-outline-*`, `table-*`, `badge`, `progress-bar`), including template branches,
|
|
198
|
+
portals, and inline SVG with literal fills.
|
|
199
|
+
- **Reading.** For each element, resolve the nearest ancestor that paints a background — class,
|
|
200
|
+
component, or scope — and classify both sides from
|
|
201
|
+
[color-modes.md](color-modes.md#fixed-and-adaptive-classes). Report mixed pairs, fixed fills
|
|
202
|
+
with inherited text — including a `data-bs-theme` scope on a fixed fill that does not carry
|
|
203
|
+
`text-body` on the same element — fixed neutrals on adaptive surfaces (`bg-light`, `bg-white`,
|
|
204
|
+
`text-dark`), `text-dark-emphasis` inside a dark scope, and outline buttons outside a measured
|
|
205
|
+
scope. Report `text-muted`, `navbar-light`, `navbar-dark`, and `btn-close-white` under a separate
|
|
206
|
+
deprecation finding: they are 5.3 deprecations rather than pairing defects, and `text-muted` pairs
|
|
207
|
+
correctly. The scan predicts a pairing failure; the contrast instrument in each declared theme
|
|
208
|
+
establishes it.
|
|
209
|
+
- **Negative control.** Append `bg-light` with inherited text, `text-white` on `bg-body`,
|
|
210
|
+
`text-primary` inside a `data-bs-theme="dark"` region, and a `bg-dark` region with
|
|
211
|
+
`data-bs-theme="dark"` and plain text but no `text-body`, in a harness; each must be reported by
|
|
212
|
+
the same reader.
|
|
213
|
+
- **Coverage.** Mechanical class analysis only; it does not see custom CSS, `currentColor`
|
|
214
|
+
resolution, image content, or composited opacity. Measure those in the render.
|
|
215
|
+
|
|
181
216
|
## Responsive task and reflow
|
|
182
217
|
|
|
183
218
|
- **Property.** The declared task remains readable and operable without unintended page overflow,
|
|
@@ -230,7 +265,7 @@ requested review round or campaign, use `orkestrel-polish-surface` rather than c
|
|
|
230
265
|
right control after wrapping. Width serves the content; rails, forms, and tables use it deliberately.
|
|
231
266
|
- **Type and reflow:** line length, baseline alignment, line-height, numeric comparison, and fallback
|
|
232
267
|
text work at the declared widths and enlarged text. No essential content is clipped or hidden.
|
|
233
|
-
- **Color, depth, and imagery:**
|
|
268
|
+
- **Color, depth, and imagery:** transitions between declared themes preserve hierarchy without gratuitous text overrides; color has a second encoding;
|
|
234
269
|
elevation describes layers; crops and icon sizes preserve useful detail; the frame stays quiet.
|
|
235
270
|
- **States and restraint:** first-use, filtered-empty, loading, partial, and error retain a useful
|
|
236
271
|
next step. Long or missing content holds up. The signature belongs to the brief; accessories do not
|
|
@@ -241,13 +276,13 @@ Pair each such claim with the relevant instrument or interaction test and its ac
|
|
|
241
276
|
|
|
242
277
|
## When an authored rule is already earned
|
|
243
278
|
|
|
244
|
-
Leave rung
|
|
245
|
-
rule without asking only when every condition holds:
|
|
279
|
+
Leave the authored rung to the developer, per [SKILL.md](../SKILL.md) → When custom CSS is
|
|
280
|
+
justified. Write a rule without asking only when every condition holds:
|
|
246
281
|
|
|
247
282
|
- an instrument reports a vendor failure against a stated requirement, such as a focus ring below
|
|
248
283
|
3:1 or information-bearing status text below 4.5:1;
|
|
249
284
|
- the rule cites the instrument, failing reading, and required bar beside it;
|
|
250
|
-
- rungs
|
|
285
|
+
- the component, utility, and extension rungs cannot restore the requirement, and the rule repairs that failure without unrelated polish;
|
|
251
286
|
- the rule uses `--bs-*` paint tokens and declared scales, and the repaired result is re-measured in
|
|
252
287
|
every affected theme and state.
|
|
253
288
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
# Responsive layout
|
|
2
2
|
|
|
3
|
-
> Part of the `enterprise-bootstrap`
|
|
3
|
+
> Part of the `enterprise-bootstrap` skill. Use before composing a screen, shell, toolbar,
|
|
4
4
|
> form, overlay, or data view. Operate layer: [SKILL.md](../SKILL.md).
|
|
5
5
|
|
|
6
6
|
## Contents
|
|
7
7
|
|
|
8
8
|
- [Declare the contract](#declare-the-contract)
|
|
9
9
|
- [Build the base](#build-the-base)
|
|
10
|
+
- [Bootstrap's responsive surface](#bootstraps-responsive-surface)
|
|
10
11
|
- [Expand by available space](#expand-by-available-space)
|
|
11
12
|
- [Keep the task intact](#keep-the-task-intact)
|
|
12
13
|
- [Handle navigation and overlays](#handle-navigation-and-overlays)
|
|
@@ -78,6 +79,55 @@ ship breakpoint variants. Do not invent `w-md-auto`, `overflow-lg-auto`, `positi
|
|
|
78
79
|
`min-w-0`. Responsive sticky helpers are a separate shipped family. Take missing roles through
|
|
79
80
|
[Layout and type extensions](bootstrap-reference.md#layout-and-type-extensions).
|
|
80
81
|
|
|
82
|
+
## Bootstrap's responsive surface
|
|
83
|
+
|
|
84
|
+
Stock 5.3.8 thresholds are `min-width` breakpoints: `sm` 576, `md` 768, `lg` 992, `xl` 1200,
|
|
85
|
+
`xxl` 1400 px; `xs` has no infix, so an unprefixed class is the base and `sm-*` applies from
|
|
86
|
+
576 px up. `.container` caps at 540 / 720 / 960 / 1140 / 1320 px; `container-{bp}` stays fluid
|
|
87
|
+
until its breakpoint; `container-fluid` always. Gutter and container padding are 1.5 rem, so a
|
|
88
|
+
320 px viewport leaves 296 px of content and a 390 px viewport 366 px. Offcanvas panels are
|
|
89
|
+
400 px wide (`w-100` on narrow viewports); modals are 300 / 500 / 800 / 1140 px.
|
|
90
|
+
|
|
91
|
+
Families that ship breakpoint infixes, read from the utilities map: `d-*`, `flex-*`,
|
|
92
|
+
`justify-content-*`, `align-items-*`, `align-self-*`, `align-content-*`, `order-*`, `float-*`,
|
|
93
|
+
`gap-*`, `row-gap-*`, `column-gap-*`, every `m*`/`p*` spacing class, `text-{bp}-start/center/end`,
|
|
94
|
+
`object-fit-*`; plus the grid (`col-*`, `row-cols-*`, `g-*`, `offset-*`), `container-*`,
|
|
95
|
+
`sticky-{bp}-top/bottom`, and the component thresholds `navbar-expand-*`, `offcanvas-*`,
|
|
96
|
+
`table-responsive-*`, `modal-fullscreen-*-down`, `dropdown-menu-{bp}-end/start`,
|
|
97
|
+
`list-group-horizontal-*`.
|
|
98
|
+
|
|
99
|
+
Families with no infix: `w-*`, `h-*`, `mw-*`, `vh-*`, `position-*`, `top/bottom/start/end-*`,
|
|
100
|
+
`overflow-*`, `border-*`, `rounded-*`, `shadow-*`, `fs-*`, `fw-*`, `lh-*`, `text-nowrap`,
|
|
101
|
+
`text-truncate`, `text-uppercase`, `opacity-*`, `hstack`/`vstack`, `btn-group-vertical`. Write
|
|
102
|
+
`d-flex flex-column flex-md-row gap-3` where a stack must become a row, and generate `w-md-auto`
|
|
103
|
+
or `overflow-lg-visible` through the utilities API with `responsive: true` when a role needs it.
|
|
104
|
+
That key reaches a `$utilities` entry and nothing else, so it generates `w-*` and `overflow-*`
|
|
105
|
+
infixes but cannot reach a component threshold, a grid class, or a helper such as `hstack`; change
|
|
106
|
+
the component's own breakpoint class instead
|
|
107
|
+
([bootstrap-reference.md](bootstrap-reference.md) → Utilities API).
|
|
108
|
+
|
|
109
|
+
Recipes:
|
|
110
|
+
|
|
111
|
+
- **Table scroller.** `<div class="table-responsive" role="region" aria-label="Invoices"
|
|
112
|
+
tabindex="0">` — the shipped class is `overflow-x: auto` only; the name and `tabindex` make it
|
|
113
|
+
keyboard-reachable. `table-responsive-{bp}` scrolls only below the breakpoint.
|
|
114
|
+
- **Menus in a scroller.** A scroller clips its `dropdown-menu`. Add
|
|
115
|
+
`data-bs-popper-config='{"strategy":"fixed"}'` to the toggle, or open row actions in a
|
|
116
|
+
root-mounted dialog.
|
|
117
|
+
- **Dual representations.** Render the narrow list and the wide table from one data array and one
|
|
118
|
+
selection set keyed by record id. Hide the inactive view with `d-none d-lg-block` /
|
|
119
|
+
`d-lg-none` so only one is in the accessibility tree; keep every `id` unique per view; re-sync
|
|
120
|
+
selection, sort, and filter state into whichever view is active. A view that resolves is not a
|
|
121
|
+
second store.
|
|
122
|
+
- **Toolbar base.** `d-grid gap-2 d-sm-flex flex-sm-wrap` stretches controls at the base and
|
|
123
|
+
releases them from `sm`; give search its own `col-12 col-md` row.
|
|
124
|
+
- **Touch.** `btn` is 38 px tall at the default size, `btn-sm` 31 px, `btn-lg` 48 px. Primary
|
|
125
|
+
mobile controls take `btn` or `btn-lg`, never a scaled-up icon inside `btn-sm`.
|
|
126
|
+
- **Pager.** Keep previous/next and the current page at every width; hide other numbers with
|
|
127
|
+
`d-none d-sm-block` on the `page-item` before shrinking targets.
|
|
128
|
+
- **Joined groups.** A `btn-group` bent over two rows loses its shared corners; below the width
|
|
129
|
+
where its labels fit, use a `form-select` or independent wrapping buttons.
|
|
130
|
+
|
|
81
131
|
## Expand by available space
|
|
82
132
|
|
|
83
133
|
Measure the content container after rails, gutters, and panel padding. A wide viewport can contain
|
|
@@ -131,10 +181,10 @@ Keep record actions outside a clipped table wrapper when necessary. Popper place
|
|
|
131
181
|
not guarantee escape from an overflow ancestor. Prefer a root-mounted dialog or an existing
|
|
132
182
|
portal implementation over z-index escalation.
|
|
133
183
|
|
|
134
|
-
Make touch targets comfortable without making text larger
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
184
|
+
Make touch targets comfortable without making text larger; take every dimension from
|
|
185
|
+
[bootstrap-reference.md](bootstrap-reference.md) → WCAG 2.2 requirements for app UI, which owns the target floor and
|
|
186
|
+
the mobile preference. Keep action affordances visible without hover. Measure effective label hit
|
|
187
|
+
areas for native checkboxes and switches.
|
|
138
188
|
|
|
139
189
|
## Handle navigation and overlays
|
|
140
190
|
|
|
@@ -168,7 +218,7 @@ Run [Responsive task and reflow](inspection.md#responsive-task-and-reflow) and
|
|
|
168
218
|
[Responsive interaction continuity](inspection.md#responsive-interaction-continuity). Check 320 and
|
|
169
219
|
390 CSS px, one wide view, and `b−1`, `b`, `b+1` for each used breakpoint; deduplicate overlaps.
|
|
170
220
|
Check narrow/short landscape, long unbroken identifiers, expanded copy, enlarged text, and the
|
|
171
|
-
states actually used. Cross
|
|
221
|
+
states actually used. Cross every declared mode with the important narrow/wide states.
|
|
172
222
|
|
|
173
223
|
Require both geometry and task evidence. A page with no horizontal overflow can still hide its
|
|
174
224
|
primary action, clip a menu, or push decision fields into an undiscoverable scroller. Conversely,
|
|
@@ -182,6 +232,6 @@ viewport, device-pixel-ratio change, or emulated touch a real-device or complete
|
|
|
182
232
|
Take upstream behavior from Bootstrap's [breakpoints](https://getbootstrap.com/docs/5.3/layout/breakpoints/),
|
|
183
233
|
[grid](https://getbootstrap.com/docs/5.3/layout/grid/), [flex](https://getbootstrap.com/docs/5.3/utilities/flex/),
|
|
184
234
|
[offcanvas](https://getbootstrap.com/docs/5.3/components/offcanvas/), and
|
|
185
|
-
[tables](https://getbootstrap.com/docs/5.3/content/tables/). Distinguish this
|
|
235
|
+
[tables](https://getbootstrap.com/docs/5.3/content/tables/). Distinguish this skill's test matrix
|
|
186
236
|
from the requirements and two-dimensional-content exception in
|
|
187
237
|
[WCAG reflow](https://www.w3.org/WAI/WCAG22/Understanding/reflow.html).
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bootstrap 5 Utilities Reference
|
|
2
2
|
|
|
3
|
-
> Part of the `enterprise-bootstrap`
|
|
3
|
+
> Part of the `enterprise-bootstrap` skill. Bootstrap **5.3.x** class index +
|
|
4
4
|
> composition notes. Component markup: [components.md](components.md).
|
|
5
5
|
> Theming, patterns, a11y: [bootstrap-reference.md](bootstrap-reference.md).
|
|
6
6
|
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
.bg-opacity-10, .bg-opacity-25, .bg-opacity-50, .bg-opacity-75, .bg-opacity-100
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
+
`bg-body`, `bg-body-secondary`, `bg-body-tertiary`, and `bg-*-subtle` adapt; `bg-{theme}`, `bg-light`, `bg-dark`, `bg-white`, `bg-black`, and `bg-gradient` are fixed. Inherited text on a fixed fill is never a pair — measure it in each declared mode (stock `bg-light` measures 1.2:1 in dark); a fixed fill takes `text-bg-*`, its component's foreground, or a `data-bs-theme` scope with `text-body` on the same element (the scope changes variables only; plain text inherits the outer mode's painted color).
|
|
28
|
+
|
|
27
29
|
Prefer `bg-body`, `bg-body-secondary`, `bg-body-tertiary`, and `bg-*-subtle` for quiet surfaces; inherit text without an added foreground class. Treat original contextual `bg-*`, including `bg-light` and `bg-dark`, as non-adaptive in stock 5.3. Take ownership and exceptions from [color-modes.md](color-modes.md).
|
|
28
30
|
|
|
29
31
|
### Borders
|
|
@@ -43,7 +45,7 @@ Use adaptive border roles for quiet separation. Measure boundaries needed to ide
|
|
|
43
45
|
|
|
44
46
|
- **`border-{1..5}` sets `border-width` on every side.** On a component that already has a border (`.card`, `.alert`) it thickens the whole box. For a one-side accent, zero first, restore one side, then widen — `card border-0 border-top border-4 border-primary` — utility source order (`border` → `border-{side}` → `border-width`) makes it hold, and the cleared sides have no border style so their width never paints.
|
|
45
47
|
- Strengthen a rule that reads too faint with `border-2` on its soft color, not with a darker color; heavier width keeps the softness.
|
|
46
|
-
- `border-{color}` is the fixed brand color in
|
|
48
|
+
- `border-{color}` is the fixed brand color in light and dark; check an accent against a dark `bg-*-subtle` before shipping it.
|
|
47
49
|
|
|
48
50
|
### Colors (Text)
|
|
49
51
|
|
|
@@ -57,7 +59,7 @@ Use adaptive border roles for quiet separation. Measure boundaries needed to ide
|
|
|
57
59
|
.text-opacity-25, .text-opacity-50, .text-opacity-75, .text-opacity-100
|
|
58
60
|
```
|
|
59
61
|
|
|
60
|
-
Default ordinary text to inheritance.
|
|
62
|
+
Default ordinary text to inheritance. `text-{theme}`, `text-white`, `text-black`, `text-light`, `text-dark`, and their `-50` variants are fixed in light and dark; `text-body*`, `text-muted` (alias), and `text-*-emphasis` adapt — pair them with adaptive surfaces only ([color-modes.md](color-modes.md) → Fixed and adaptive classes). Classification and deprecation are separate axes: `text-muted` adapts and pairs correctly, and 5.3 deprecates it, so replace it with `text-body-secondary` on the deprecation rather than on a contrast reading. `text-body-secondary` (body color at .75 alpha) clears 4.5:1 on every stock body surface in light and dark; `text-body-tertiary` (.5 alpha) measures 3.0–4.1:1 there and is decoration or disabled only. Those readings bound stock 5.3.8 — re-measure under a declared theme or skin. Neither, nor `text-white-50`, is a quiet tier on a colored fill — take the same-hue token from [color-modes.md](color-modes.md) → Text tiers. Do not add emphasis text automatically to subtle fills, and do not replace a component's native foreground without inspecting its state contract.
|
|
61
63
|
|
|
62
64
|
### Display
|
|
63
65
|
|
|
@@ -165,13 +167,15 @@ Opacity is not a text tier: it reads as disabled and lets the surface show throu
|
|
|
165
167
|
.translate-middle, .translate-middle-x, .translate-middle-y
|
|
166
168
|
```
|
|
167
169
|
|
|
170
|
+
Responsive infixes: `d`, `flex`, `justify-content`, `align-*`, `order`, `float`, `gap`, spacing, `text-{bp}-start/center/end`, and `object-fit` ship them; `w`, `h`, `position`, `overflow`, `border`, `rounded`, `shadow`, `fs`, `fw`, `lh`, `text-nowrap`, `text-truncate`, `hstack`/`vstack` do not ([responsive-layout.md](responsive-layout.md) → Bootstrap's responsive surface). Generate a missing infix only where a `$utilities` entry owns the property; `hstack` and `vstack` are helpers with no entry, so no key makes them responsive ([bootstrap-reference.md](bootstrap-reference.md) → Utilities API).
|
|
171
|
+
|
|
168
172
|
### Shadows
|
|
169
173
|
|
|
170
174
|
```css
|
|
171
175
|
.shadow-none, .shadow-sm, .shadow, .shadow-lg
|
|
172
176
|
```
|
|
173
177
|
|
|
174
|
-
|
|
178
|
+
Assign the shipped elevation steps by layer role: `shadow-sm` (`0 .125rem .25rem` at .075) for slightly raised cards and controls, `shadow` (`0 .5rem 1rem` at .15) for floating menus and a dragged item, `shadow-lg` (`0 1rem 3rem` at .175) for dialogs. Stock dropdowns, popovers, toasts, and modals all sit on `--bs-box-shadow`; lift a modal to the top step through `--bs-modal-box-shadow` ([bootstrap-reference.md](bootstrap-reference.md) → Elevation and depth). No shadow is a valid role.
|
|
175
179
|
|
|
176
180
|
### Sizing
|
|
177
181
|
|
|
@@ -370,7 +374,8 @@ flex-sm-wrap` or `col-md-auto` only when the container fits. Do not default to a
|
|
|
370
374
|
- **RTL:** use `ms-*`/`me-*`/`ps-*`/`pe-*`, `text-start`/`text-end`, and logical custom properties;
|
|
371
375
|
verify the matching RTL build and the content's writing direction.
|
|
372
376
|
- **Density:** drive compact/comfortable variants from shared tokens or a wrapper, not scattered
|
|
373
|
-
per-element tweaks. Dense data retains readable text and
|
|
377
|
+
per-element tweaks. Dense data retains readable text and control targets at the floor in
|
|
378
|
+
[bootstrap-reference.md](bootstrap-reference.md) → WCAG 2.2 requirements for app UI.
|
|
374
379
|
- **Boundaries and depth:** separate with spacing first, then a surface change, then a shadow, then
|
|
375
380
|
a line: `bg-body-tertiary` panels instead of bordered ones; `card border-0 shadow-sm` on a page
|
|
376
381
|
surface that differs from the card; `list-group-flush`, `accordion-flush`, `table-borderless`,
|
|
@@ -379,7 +384,7 @@ flex-sm-wrap` or `col-md-auto` only when the container fits. Do not default to a
|
|
|
379
384
|
recognition survive. Assign `shadow-sm`, `shadow`, and `shadow-lg` by layer role; do not shadow
|
|
380
385
|
every panel or replace the focus indicator with depth. A `bg-body` panel on `bg-body-tertiary`
|
|
381
386
|
reads raised and `bg-body-secondary` inside `bg-body` reads inset — depth with no shadow, in
|
|
382
|
-
|
|
387
|
+
light and dark.
|
|
383
388
|
- **Accents and decoration:** one accent border per region (see [Borders](#borders)); the shipped
|
|
384
389
|
`nav-underline` is the active-item accent. Alternate `bg-body` and `bg-body-tertiary` sections
|
|
385
390
|
before decorating; a `bg-primary-subtle` band emphasizes one panel. `bg-gradient` is a
|