palace-ui 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SPEC.md +175 -59
- package/catalog.html +887 -674
- package/package.json +8 -2
- package/palace.css +132 -49
package/SPEC.md
CHANGED
|
@@ -75,25 +75,31 @@ Or if consuming via npm with a build tool:
|
|
|
75
75
|
| Token | Value | Usage |
|
|
76
76
|
|---|---|---|
|
|
77
77
|
| `--p-space-xs` | `4px` | Tight gaps |
|
|
78
|
-
| `--p-space-sm` | `8px` | Button gaps,
|
|
79
|
-
| `--p-space-md` | `16px` |
|
|
78
|
+
| `--p-space-sm` | `8px` | Button gaps, label to control |
|
|
79
|
+
| `--p-space-md` | `16px` | Space between cards and fields, standard padding |
|
|
80
80
|
| `--p-space-lg` | `24px` | Card padding, section spacing |
|
|
81
81
|
| `--p-space-xl` | `32px` | Intermediate section gaps |
|
|
82
82
|
| `--p-space-2xl` | `48px` | Hero padding, major section gaps |
|
|
83
83
|
|
|
84
84
|
### Spacing Rules
|
|
85
85
|
|
|
86
|
-
|
|
86
|
+
Spacing comes from the container, never from the component inside it.
|
|
87
87
|
|
|
88
|
-
1. **`
|
|
88
|
+
1. **`space-*` between children.** A container spaces its direct children vertically with the owl selector (`> * + *` gets `margin-top`). Use it for any column: paragraphs, fields, cards, sections.
|
|
89
89
|
|
|
90
|
-
2. **`gap
|
|
90
|
+
2. **`gap-*` in rows and grids.** A flex or grid container sets its `gap`. Its children get no margin.
|
|
91
91
|
|
|
92
|
-
3.
|
|
92
|
+
3. **Margin only for a single exception.** One element that needs more or less space than its container gives it gets its own margin, with a comment saying why.
|
|
93
93
|
|
|
94
|
-
**
|
|
94
|
+
4. **Padding is the inside of a box**, never the space between things.
|
|
95
95
|
|
|
96
|
-
**
|
|
96
|
+
5. **Components set no outer margin.** A component styles its inside only: `.card`, `.card-static`, `label`, `.stat-row`, `.page-header` and dialog parts have no margin around them. An outer margin would add to a `gap` or fight a `space-*`. Components that space their own children (`.page-header`, `.code-reveal`, `dialog`, list items in a container) do it with `:where()` rules, so a `space-*` utility on them always wins.
|
|
97
|
+
|
|
98
|
+
6. **Missing values become tokens.** When a value is missing, add it to palace as a token instead of writing a raw number in an app. A raw value is only for a genuine one-off, with a comment saying why.
|
|
99
|
+
|
|
100
|
+
Sizes for both: `xs` (4px), `sm` (8px), `md` (16px), `lg` (24px), `xl` (32px), `2xl` (48px), the `--p-space-*` scale.
|
|
101
|
+
|
|
102
|
+
**Exceptions:** dividers (`.divider`, `.divider-danger`, `.gradient-stripe`) use top and bottom margin because they are separators by nature. `margin: auto` centres containers and dialogs. The `.stat-label` 2px optical nudge and the rules between the navbar menu's groups are part of those components.
|
|
97
103
|
|
|
98
104
|
### Layout
|
|
99
105
|
|
|
@@ -103,6 +109,14 @@ Three mechanisms for spacing, each with a clear use case:
|
|
|
103
109
|
| `--p-container-narrow` | `420px` |
|
|
104
110
|
| `--p-navbar-height` | `52px` |
|
|
105
111
|
|
|
112
|
+
### Controls
|
|
113
|
+
|
|
114
|
+
| Token | Value | Usage |
|
|
115
|
+
|---|---|---|
|
|
116
|
+
| `--p-control-height` | `44px` | Text inputs, selects, number input, buttons |
|
|
117
|
+
| `--p-control-height-sm` | `32px` | `.btn-sm`, a button inside `.input-action` |
|
|
118
|
+
| `--p-control-height-lg` | `52px` | `.btn-lg`, `.cta` |
|
|
119
|
+
|
|
106
120
|
## Component Catalog
|
|
107
121
|
|
|
108
122
|
### Page Shell
|
|
@@ -198,7 +212,7 @@ Light variant for pages that need a white navbar:
|
|
|
198
212
|
|
|
199
213
|
### Page Header
|
|
200
214
|
|
|
201
|
-
Standard spacing for non-hero pages (after navbar). Provides `48px` top padding and
|
|
215
|
+
Standard spacing for non-hero pages (after navbar). Provides `48px` top padding and `8px` between its children.
|
|
202
216
|
|
|
203
217
|
```html
|
|
204
218
|
<div class="container page-header">
|
|
@@ -218,18 +232,30 @@ Combines with any container class:
|
|
|
218
232
|
</div>
|
|
219
233
|
```
|
|
220
234
|
|
|
221
|
-
Spacing: `48px` top padding
|
|
235
|
+
Spacing: `48px` top padding and `8px` between its children; it has no outer margin. To give the content more room than the heading, group the heading and subtitle and put a `space-*` class on the header:
|
|
236
|
+
|
|
237
|
+
```html
|
|
238
|
+
<div class="container page-header space-xl">
|
|
239
|
+
<div class="space-sm">
|
|
240
|
+
<h1>Page Title</h1>
|
|
241
|
+
<p class="subtitle">Helpful subtitle</p>
|
|
242
|
+
</div>
|
|
243
|
+
<!-- content -->
|
|
244
|
+
</div>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Do **not** use on landing/hero pages (those use custom hero spacing).
|
|
222
248
|
|
|
223
249
|
### Hero Section (Landing Pages)
|
|
224
250
|
|
|
225
251
|
```html
|
|
226
|
-
<div class="container" style="padding-top: 80px; padding-bottom: 48px;">
|
|
252
|
+
<div class="container space-lg" style="padding-top: 80px; padding-bottom: 48px;">
|
|
227
253
|
<p class="brand">App Name</p>
|
|
228
254
|
<h1 class="h1-hero">Main Headline Here</h1>
|
|
229
255
|
<p class="tagline">
|
|
230
256
|
A sentence or two explaining what this does. Keep it short.
|
|
231
257
|
</p>
|
|
232
|
-
<div style="display: flex;
|
|
258
|
+
<div class="gap-sm" style="display: flex; flex-wrap: wrap;">
|
|
233
259
|
<a href="/signup" class="cta cta-primary">Sign Up</a>
|
|
234
260
|
<a href="/login" class="cta cta-secondary">Log In</a>
|
|
235
261
|
</div>
|
|
@@ -239,8 +265,8 @@ Spacing: `48px` top padding, `8px` below h1, `32px` below `.subtitle`. Do **not*
|
|
|
239
265
|
When the app has a visual mark/icon, use `.brand-lockup` instead of a standalone `.brand`:
|
|
240
266
|
|
|
241
267
|
```html
|
|
242
|
-
<div class="container" style="padding-top: 80px; padding-bottom: 48px;">
|
|
243
|
-
<div class="brand-lockup"
|
|
268
|
+
<div class="container space-xl" style="padding-top: 80px; padding-bottom: 48px;">
|
|
269
|
+
<div class="brand-lockup">
|
|
244
270
|
<img src="/icons/app-icon.svg" alt="">
|
|
245
271
|
<div>
|
|
246
272
|
<p class="brand" style="font-size: 17px; letter-spacing: 3px;">App Name</p>
|
|
@@ -270,10 +296,10 @@ Use in hero sections and landing pages where the app has a visual mark. The `.br
|
|
|
270
296
|
|
|
271
297
|
### Card List (3-Color Rotation)
|
|
272
298
|
|
|
273
|
-
When you have a list of cards, the accent color auto-rotates via `nth-child
|
|
299
|
+
When you have a list of cards, the accent color auto-rotates via `nth-child`. Cards have no margin; the list spaces them with `space-md` (or `gap-md` in a grid):
|
|
274
300
|
|
|
275
301
|
```html
|
|
276
|
-
<div class="container">
|
|
302
|
+
<div class="container space-md">
|
|
277
303
|
<div class="card">
|
|
278
304
|
<h2>First Card</h2>
|
|
279
305
|
<p>Description goes here. Color will be accent-1 (pink).</p>
|
|
@@ -302,9 +328,11 @@ For explicit accent control (e.g. server-rendered cards), use the `--accent` cus
|
|
|
302
328
|
For cards used as form containers or static content that should not lift on hover:
|
|
303
329
|
|
|
304
330
|
```html
|
|
305
|
-
<div class="card-static">
|
|
306
|
-
<
|
|
307
|
-
|
|
331
|
+
<div class="card-static space-md">
|
|
332
|
+
<div class="field">
|
|
333
|
+
<label for="name">Name</label>
|
|
334
|
+
<input type="text" id="name" placeholder="Enter your name">
|
|
335
|
+
</div>
|
|
308
336
|
</div>
|
|
309
337
|
```
|
|
310
338
|
|
|
@@ -312,7 +340,7 @@ Use `.card-static` instead of `.card` when the card is a container (e.g. auth fo
|
|
|
312
340
|
|
|
313
341
|
### Buttons
|
|
314
342
|
|
|
315
|
-
Size modifiers compose with any color variant. `.btn` works on `<button>` and on `<a>` alike:
|
|
343
|
+
Size modifiers compose with any color variant. `.btn` works on `<button>` and on `<a>` alike: a button and a link button of the same size are the same height (44px default, 32px `.btn-sm`, 52px `.btn-lg` and `.cta`, from the control height tokens) and line up side by side. The height is a minimum: a button grows when its label wraps.
|
|
316
344
|
|
|
317
345
|
```html
|
|
318
346
|
<!-- Size modifiers -->
|
|
@@ -345,37 +373,86 @@ Size modifiers compose with any color variant. `.btn` works on `<button>` and on
|
|
|
345
373
|
|
|
346
374
|
### Forms
|
|
347
375
|
|
|
376
|
+
A `.field` holds a label, its control and an optional hint or error, with 8px between them. Labels have no margin of their own; always put a label and its control in a `.field`. Space a column of fields with `space-md`.
|
|
377
|
+
|
|
348
378
|
```html
|
|
349
|
-
<
|
|
350
|
-
<
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
</div>
|
|
379
|
+
<form class="card-static space-md">
|
|
380
|
+
<div class="field">
|
|
381
|
+
<label for="name">Your Name</label>
|
|
382
|
+
<input type="text" id="name" placeholder="Enter your name">
|
|
383
|
+
</div>
|
|
384
|
+
<div class="field">
|
|
385
|
+
<label for="email">Email</label>
|
|
386
|
+
<input type="email" id="email" aria-invalid="true" aria-describedby="email-error">
|
|
387
|
+
<p class="field-error" id="email-error">Enter an email address with a domain, like you@example.com.</p>
|
|
388
|
+
</div>
|
|
389
|
+
<div class="field">
|
|
390
|
+
<label for="pass">Password</label>
|
|
391
|
+
<input type="password" id="pass" aria-describedby="pass-hint">
|
|
392
|
+
<p class="field-hint" id="pass-hint">At least 8 characters.</p>
|
|
393
|
+
</div>
|
|
394
|
+
<button class="btn btn-primary btn-block">Submit</button>
|
|
395
|
+
</form>
|
|
354
396
|
```
|
|
355
397
|
|
|
398
|
+
`.field-hint` is muted small text; `.field-error` is small red text. Connect either to the control with `aria-describedby`. `aria-invalid="true"` on an input, select or textarea gives it a red border, and a red shadow on focus.
|
|
399
|
+
|
|
400
|
+
All controls share one height. Text inputs, selects and the number input are exactly `--p-control-height` (44px) tall; buttons have it as a minimum and grow when a label wraps. A textarea starts at the control height. A field and a button beside it line up by construction.
|
|
401
|
+
|
|
356
402
|
A `<select>` is styled like the text inputs, with a drawn chevron:
|
|
357
403
|
|
|
358
404
|
```html
|
|
359
|
-
<
|
|
360
|
-
<
|
|
405
|
+
<div class="field">
|
|
406
|
+
<label for="direction">Direction</label>
|
|
407
|
+
<select id="direction"><option>Anticlockwise</option><option>Clockwise</option></select>
|
|
408
|
+
</div>
|
|
361
409
|
```
|
|
362
410
|
|
|
363
|
-
|
|
411
|
+
A `.control-row` puts inputs, fields and buttons on one line, aligned to the bottom, 8px apart. Inputs, selects, textareas, `.input-action`s and fields grow and share the width, starting from `--control-row-min` (12rem); buttons keep their natural width, may wrap their label, and the row wraps when it is narrow.
|
|
412
|
+
|
|
413
|
+
The row aligns its items to the bottom of each `.field`, so a field in a row holds only its label and control. Put the row's hint or error below the row, not inside the `.field`, or the button no longer lines up with the control. Space them with `space-sm` on a wrapper.
|
|
364
414
|
|
|
365
415
|
```html
|
|
366
|
-
<div
|
|
367
|
-
<input type="text" placeholder="Label"
|
|
368
|
-
<button class="btn-primary">Create</button>
|
|
416
|
+
<div class="control-row">
|
|
417
|
+
<input type="text" placeholder="Label" aria-label="Label">
|
|
418
|
+
<button class="btn btn-primary">Create</button>
|
|
419
|
+
</div>
|
|
420
|
+
|
|
421
|
+
<div class="control-row">
|
|
422
|
+
<div class="field">
|
|
423
|
+
<label for="driver">Driver</label>
|
|
424
|
+
<input type="text" id="driver">
|
|
425
|
+
</div>
|
|
426
|
+
<div class="field">
|
|
427
|
+
<label for="car">Car</label>
|
|
428
|
+
<select id="car"><option>Red</option><option>Blue</option></select>
|
|
429
|
+
</div>
|
|
430
|
+
<button class="btn btn-primary">Add Driver</button>
|
|
431
|
+
</div>
|
|
432
|
+
|
|
433
|
+
<div class="space-sm">
|
|
434
|
+
<div class="control-row">
|
|
435
|
+
<div class="field">
|
|
436
|
+
<label for="code">Transponder</label>
|
|
437
|
+
<input type="text" id="code" aria-invalid="true" aria-describedby="code-error">
|
|
438
|
+
</div>
|
|
439
|
+
<button class="btn btn-primary">Assign</button>
|
|
440
|
+
</div>
|
|
441
|
+
<p class="field-error" id="code-error">That transponder is already assigned.</p>
|
|
369
442
|
</div>
|
|
370
443
|
```
|
|
371
444
|
|
|
372
|
-
|
|
445
|
+
Form grids and column layouts are not part of palace: build them with `gap-*` and `space-*`.
|
|
446
|
+
|
|
447
|
+
A field with a button inside, at its right end (show/hide a password, paste, copy). The input reserves the button's width plus its 8px inset from the edge (`--input-action-width` is the button's width, default `4.75rem`); the button is centred in the input's box and lifts with the input on focus, so they stay aligned. The button is the small control height. Use `.btn-sm`, a real `<button type="button">`, and for a toggle let the visible text and the accessible name change together ("Show" / `aria-label="Show password"` and "Hide" / "Hide password"). Pick one way to say the state: a changing name, or a fixed name with `aria-pressed` — never both.
|
|
373
448
|
|
|
374
449
|
```html
|
|
375
|
-
<
|
|
376
|
-
<
|
|
377
|
-
<
|
|
378
|
-
|
|
450
|
+
<div class="field">
|
|
451
|
+
<label for="pw">Password</label>
|
|
452
|
+
<div class="input-action">
|
|
453
|
+
<input type="password" id="pw" autocomplete="off">
|
|
454
|
+
<button type="button" class="btn btn-sm btn-outline" aria-label="Show password">Show</button>
|
|
455
|
+
</div>
|
|
379
456
|
</div>
|
|
380
457
|
```
|
|
381
458
|
|
|
@@ -441,14 +518,14 @@ Standard code block:
|
|
|
441
518
|
};</pre>
|
|
442
519
|
```
|
|
443
520
|
|
|
444
|
-
Dark reveal panel (for secrets, API keys, terminal output):
|
|
521
|
+
Dark reveal panel (for secrets, API keys, terminal output). It puts 8px between its children:
|
|
445
522
|
```html
|
|
446
523
|
<div class="code-reveal">
|
|
447
|
-
<p class="eyebrow" style="color: var(--p-accent-3);
|
|
524
|
+
<p class="eyebrow" style="color: var(--p-accent-3);">
|
|
448
525
|
Copy this — you won't see it again
|
|
449
526
|
</p>
|
|
450
527
|
<code>sk_live_abc123def456</code>
|
|
451
|
-
<div style="display: flex;
|
|
528
|
+
<div class="gap-sm" style="display: flex;">
|
|
452
529
|
<button class="btn-secondary">Copy</button>
|
|
453
530
|
</div>
|
|
454
531
|
</div>
|
|
@@ -483,21 +560,30 @@ Dark reveal panel (for secrets, API keys, terminal output):
|
|
|
483
560
|
</div>
|
|
484
561
|
```
|
|
485
562
|
|
|
486
|
-
###
|
|
563
|
+
### Space and Gap
|
|
487
564
|
|
|
488
|
-
|
|
565
|
+
`space-*` puts the same vertical space between the direct children of a container. Apply it to the parent.
|
|
489
566
|
|
|
490
567
|
```html
|
|
491
|
-
<div class="
|
|
568
|
+
<div class="space-md">
|
|
492
569
|
<p>First item</p>
|
|
493
|
-
<p>16px
|
|
494
|
-
<p>16px
|
|
570
|
+
<p>16px above</p>
|
|
571
|
+
<p>16px above</p>
|
|
572
|
+
</div>
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
`gap-*` sets the gap of a flex or grid container, for rows and grids.
|
|
576
|
+
|
|
577
|
+
```html
|
|
578
|
+
<div class="gap-sm" style="display: flex; flex-wrap: wrap;">
|
|
579
|
+
<span class="tag">One</span>
|
|
580
|
+
<span class="tag">Two</span>
|
|
495
581
|
</div>
|
|
496
582
|
```
|
|
497
583
|
|
|
498
|
-
Available: `
|
|
584
|
+
Available: `xs` (4px) · `sm` (8px) · `md` (16px) · `lg` (24px) · `xl` (32px) · `2xl` (48px), as `space-md`, `gap-md` and so on.
|
|
499
585
|
|
|
500
|
-
|
|
586
|
+
`.stack-*` is a deprecated alias of `space-*` and will be removed in a later release.
|
|
501
587
|
|
|
502
588
|
### Dividers
|
|
503
589
|
|
|
@@ -513,7 +599,7 @@ For flex/grid parents, prefer `gap` instead. `.stack-*` is for flow-layout conte
|
|
|
513
599
|
|
|
514
600
|
```html
|
|
515
601
|
<hr class="divider-danger">
|
|
516
|
-
<div class="danger-zone">
|
|
602
|
+
<div class="danger-zone space-sm">
|
|
517
603
|
<h2>Danger Zone</h2>
|
|
518
604
|
<p>This will permanently delete your account. This cannot be undone.</p>
|
|
519
605
|
<button class="btn btn-danger btn-block">Delete My Account</button>
|
|
@@ -626,9 +712,22 @@ Lists inside `.container` or `.container-narrow` are automatically styled with p
|
|
|
626
712
|
|
|
627
713
|
### Dialog
|
|
628
714
|
|
|
629
|
-
A native `<dialog>` styled as a card: border, purple offset shadow, overlay backdrop. Actions go in a `<menu
|
|
715
|
+
A native `<dialog>` styled as a card: border, purple offset shadow, overlay backdrop. It spaces its own children — its direct children, or children of a direct `<form>` (`<form method="dialog">`): 4px below the heading, 8px after a paragraph, 24px after the subtitle and before the actions. Actions go in a `<menu>`, one `<li>` per button; the buttons share the width equally. A modal dialog stays centred in any container.
|
|
630
716
|
|
|
631
717
|
```html
|
|
718
|
+
<dialog>
|
|
719
|
+
<form method="dialog">
|
|
720
|
+
<h2>Title</h2>
|
|
721
|
+
<p class="subtitle">Supporting line</p>
|
|
722
|
+
<p>Body text.</p>
|
|
723
|
+
<menu>
|
|
724
|
+
<li><button class="btn" value="cancel">Cancel</button></li>
|
|
725
|
+
<li><button class="btn btn-primary" value="confirm">Confirm</button></li>
|
|
726
|
+
</menu>
|
|
727
|
+
</form>
|
|
728
|
+
</dialog>
|
|
729
|
+
|
|
730
|
+
<!-- Without a form, the same rhythm on its direct children -->
|
|
632
731
|
<dialog>
|
|
633
732
|
<h2>Title</h2>
|
|
634
733
|
<p class="subtitle">Supporting line</p>
|
|
@@ -668,7 +767,7 @@ It is absolutely positioned where the text would have been, with no `top` or `le
|
|
|
668
767
|
|
|
669
768
|
### Focus Visible
|
|
670
769
|
|
|
671
|
-
All interactive elements (buttons, links, inputs, checkboxes, radio buttons, `<summary>`) have `:focus-visible` styles with a `2px` outline in accent-2 (purple) and `2px` offset. Buttons also get a lift + shadow on focus. Text inputs show focus with a purple border and shadow instead. The navbar menu's summary keeps its own cyan ring.
|
|
770
|
+
All interactive elements (buttons, links, inputs, checkboxes, radio buttons, `<summary>`) have `:focus-visible` styles with a `2px` outline in accent-2 (purple) and `2px` offset. Buttons also get a lift + shadow on focus. Text inputs show focus with a purple border and shadow instead; an input with `aria-invalid="true"` shows a red border and shadow. The navbar menu's summary keeps its own cyan ring.
|
|
672
771
|
|
|
673
772
|
### Reduced Motion
|
|
674
773
|
|
|
@@ -696,14 +795,16 @@ Use `container-narrow page-header` (420px). No navbar. Centered with top padding
|
|
|
696
795
|
|
|
697
796
|
```html
|
|
698
797
|
<body>
|
|
699
|
-
<div class="container-narrow page-header">
|
|
700
|
-
<
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
<!-- form contents -->
|
|
798
|
+
<div class="container-narrow page-header space-lg">
|
|
799
|
+
<div class="space-sm">
|
|
800
|
+
<p class="brand">App Name</p>
|
|
801
|
+
<h1>Page Title</h1>
|
|
802
|
+
<p class="subtitle">Helpful subtitle</p>
|
|
705
803
|
</div>
|
|
706
|
-
<
|
|
804
|
+
<form class="card-static space-md">
|
|
805
|
+
<!-- fields -->
|
|
806
|
+
</form>
|
|
807
|
+
<p style="text-align: center; font-size: 13px; color: var(--p-text-muted);">
|
|
707
808
|
Already in? <a href="/login">Log in</a>
|
|
708
809
|
</p>
|
|
709
810
|
</div>
|
|
@@ -717,9 +818,11 @@ Navbar + container with `page-header`. Use `divider` between major sections.
|
|
|
717
818
|
```html
|
|
718
819
|
<body>
|
|
719
820
|
<nav class="navbar">...</nav>
|
|
720
|
-
<div class="container page-header">
|
|
721
|
-
<
|
|
722
|
-
|
|
821
|
+
<div class="container page-header space-xl">
|
|
822
|
+
<div class="space-sm">
|
|
823
|
+
<h1>Dashboard</h1>
|
|
824
|
+
<p class="subtitle">Manage your stuff</p>
|
|
825
|
+
</div>
|
|
723
826
|
<!-- content sections -->
|
|
724
827
|
<hr class="divider">
|
|
725
828
|
<!-- more sections -->
|
|
@@ -808,3 +911,16 @@ Palace CSS handles h1, container, and card adjustments automatically. For page-s
|
|
|
808
911
|
.cta-row { flex-direction: column; }
|
|
809
912
|
}
|
|
810
913
|
```
|
|
914
|
+
|
|
915
|
+
## Migrating to 0.14
|
|
916
|
+
|
|
917
|
+
0.14 moves spacing from components to containers. Check every page:
|
|
918
|
+
|
|
919
|
+
- Rename `stack-*` to `space-*`. `.stack-*` is deprecated: it still works for now, as an alias of `space-*`, and will be removed in a later major version.
|
|
920
|
+
- `.card` and `.card-static` have no margin. Wrap a list of cards in `space-md`, or `gap-md` in a flex or grid container.
|
|
921
|
+
- Labels have no margin. Put each label and its control in a `.field`.
|
|
922
|
+
- `.page-header`, `.stat-row`, `.code-reveal` and dialog parts set no outer margin. Give the space after them from the parent with `space-*` or `gap-*`.
|
|
923
|
+
- A dialog, `.page-header` and `.code-reveal` now space only their own children (a dialog: its direct children, or those of a direct `<form>`), with `:where()` rules, so a `space-*` on them wins. Content nested deeper gets no space from them: give its wrapper a `space-*`.
|
|
924
|
+
- Inputs, selects and the number input are exactly 44px tall. Buttons are at least 44px (32px `.btn-sm`, 52px `.btn-lg` and `.cta`) and grow when a label wraps. Check rows of fields and buttons against them; a `.control-row` lines them up.
|
|
925
|
+
- In a `.control-row`, put a field's hint or error below the row, not inside the `.field`.
|
|
926
|
+
- Replace a margin that spaced siblings with `space-*` or `gap-*` on their parent.
|