palace-ui 0.13.0 → 0.15.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 +197 -63
- package/catalog.html +892 -674
- package/package.json +8 -2
- package/palace.css +138 -53
package/SPEC.md
CHANGED
|
@@ -75,25 +75,49 @@ 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.
|
|
103
|
+
|
|
104
|
+
### Shadows
|
|
105
|
+
|
|
106
|
+
Offsets only; combine with a colour: `box-shadow: var(--p-shadow-md) var(--p-accent-2)`. Pick a size by role, never write a raw offset. Inset indicator lines (`inset 3px 0 0`) are not offset shadows and stay as they are.
|
|
107
|
+
|
|
108
|
+
| Token | Usage |
|
|
109
|
+
|---|---|
|
|
110
|
+
| `--p-shadow-xs` | Keys (`kbd`) |
|
|
111
|
+
| `--p-shadow-sm` | Small chips |
|
|
112
|
+
| `--p-shadow-md` | Controls: hover and focus |
|
|
113
|
+
| `--p-shadow-lg` | Boxes and cards: status boxes, cards, dialogs, the navbar menu panel |
|
|
114
|
+
|
|
115
|
+
Boxes, by component:
|
|
116
|
+
|
|
117
|
+
- **`lg`:** `.card-static` (`--p-text`, at rest and on hover; it never lifts), `.status` (`--p-text`), `dialog` and `.navbar-menu-panel` (`--p-accent-2`; the panel floats above the page like a dialog), and `.card` on hover (the lift casts its accent; at rest a `.card` is flat, so a list of cards shows the shadow where the pointer is).
|
|
118
|
+
- **Deliberately none:** tables (rules between rows, no outer box), `pre` and `.code-reveal` (they scroll sideways, which would clip a shadow), `.tag-sticker` and other tags (small chips, flat), and the disabled state of any control.
|
|
119
|
+
|
|
120
|
+
A shadow reaches 4px right and below its box. Leave that room inside a container that clips (`overflow: hidden`, `auto` or `scroll`); palace's own layouts clip nothing a box sits in.
|
|
97
121
|
|
|
98
122
|
### Layout
|
|
99
123
|
|
|
@@ -103,6 +127,14 @@ Three mechanisms for spacing, each with a clear use case:
|
|
|
103
127
|
| `--p-container-narrow` | `420px` |
|
|
104
128
|
| `--p-navbar-height` | `52px` |
|
|
105
129
|
|
|
130
|
+
### Controls
|
|
131
|
+
|
|
132
|
+
| Token | Value | Usage |
|
|
133
|
+
|---|---|---|
|
|
134
|
+
| `--p-control-height` | `44px` | Text inputs, selects, number input, buttons |
|
|
135
|
+
| `--p-control-height-sm` | `32px` | `.btn-sm`, a button inside `.input-action` |
|
|
136
|
+
| `--p-control-height-lg` | `52px` | `.btn-lg`, `.cta` |
|
|
137
|
+
|
|
106
138
|
## Component Catalog
|
|
107
139
|
|
|
108
140
|
### Page Shell
|
|
@@ -198,7 +230,7 @@ Light variant for pages that need a white navbar:
|
|
|
198
230
|
|
|
199
231
|
### Page Header
|
|
200
232
|
|
|
201
|
-
Standard spacing for non-hero pages (after navbar). Provides `48px` top padding and
|
|
233
|
+
Standard spacing for non-hero pages (after navbar). Provides `48px` top padding and `8px` between its children.
|
|
202
234
|
|
|
203
235
|
```html
|
|
204
236
|
<div class="container page-header">
|
|
@@ -218,18 +250,30 @@ Combines with any container class:
|
|
|
218
250
|
</div>
|
|
219
251
|
```
|
|
220
252
|
|
|
221
|
-
Spacing: `48px` top padding
|
|
253
|
+
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:
|
|
254
|
+
|
|
255
|
+
```html
|
|
256
|
+
<div class="container page-header space-xl">
|
|
257
|
+
<div class="space-sm">
|
|
258
|
+
<h1>Page Title</h1>
|
|
259
|
+
<p class="subtitle">Helpful subtitle</p>
|
|
260
|
+
</div>
|
|
261
|
+
<!-- content -->
|
|
262
|
+
</div>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
Do **not** use on landing/hero pages (those use custom hero spacing).
|
|
222
266
|
|
|
223
267
|
### Hero Section (Landing Pages)
|
|
224
268
|
|
|
225
269
|
```html
|
|
226
|
-
<div class="container" style="padding-top: 80px; padding-bottom: 48px;">
|
|
270
|
+
<div class="container space-lg" style="padding-top: 80px; padding-bottom: 48px;">
|
|
227
271
|
<p class="brand">App Name</p>
|
|
228
272
|
<h1 class="h1-hero">Main Headline Here</h1>
|
|
229
273
|
<p class="tagline">
|
|
230
274
|
A sentence or two explaining what this does. Keep it short.
|
|
231
275
|
</p>
|
|
232
|
-
<div style="display: flex;
|
|
276
|
+
<div class="gap-sm" style="display: flex; flex-wrap: wrap;">
|
|
233
277
|
<a href="/signup" class="cta cta-primary">Sign Up</a>
|
|
234
278
|
<a href="/login" class="cta cta-secondary">Log In</a>
|
|
235
279
|
</div>
|
|
@@ -239,8 +283,8 @@ Spacing: `48px` top padding, `8px` below h1, `32px` below `.subtitle`. Do **not*
|
|
|
239
283
|
When the app has a visual mark/icon, use `.brand-lockup` instead of a standalone `.brand`:
|
|
240
284
|
|
|
241
285
|
```html
|
|
242
|
-
<div class="container" style="padding-top: 80px; padding-bottom: 48px;">
|
|
243
|
-
<div class="brand-lockup"
|
|
286
|
+
<div class="container space-xl" style="padding-top: 80px; padding-bottom: 48px;">
|
|
287
|
+
<div class="brand-lockup">
|
|
244
288
|
<img src="/icons/app-icon.svg" alt="">
|
|
245
289
|
<div>
|
|
246
290
|
<p class="brand" style="font-size: 17px; letter-spacing: 3px;">App Name</p>
|
|
@@ -270,10 +314,10 @@ Use in hero sections and landing pages where the app has a visual mark. The `.br
|
|
|
270
314
|
|
|
271
315
|
### Card List (3-Color Rotation)
|
|
272
316
|
|
|
273
|
-
When you have a list of cards, the accent color auto-rotates via `nth-child
|
|
317
|
+
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
318
|
|
|
275
319
|
```html
|
|
276
|
-
<div class="container">
|
|
320
|
+
<div class="container space-md">
|
|
277
321
|
<div class="card">
|
|
278
322
|
<h2>First Card</h2>
|
|
279
323
|
<p>Description goes here. Color will be accent-1 (pink).</p>
|
|
@@ -299,12 +343,14 @@ For explicit accent control (e.g. server-rendered cards), use the `--accent` cus
|
|
|
299
343
|
|
|
300
344
|
### Static Card
|
|
301
345
|
|
|
302
|
-
For cards used as form containers or static content that should not lift on hover:
|
|
346
|
+
For cards used as form containers or static content that should not lift on hover. It keeps its `--p-shadow-lg` shadow in `--p-text`, at rest and on hover:
|
|
303
347
|
|
|
304
348
|
```html
|
|
305
|
-
<div class="card-static">
|
|
306
|
-
<
|
|
307
|
-
|
|
349
|
+
<div class="card-static space-md">
|
|
350
|
+
<div class="field">
|
|
351
|
+
<label for="name">Name</label>
|
|
352
|
+
<input type="text" id="name" placeholder="Enter your name">
|
|
353
|
+
</div>
|
|
308
354
|
</div>
|
|
309
355
|
```
|
|
310
356
|
|
|
@@ -312,7 +358,7 @@ Use `.card-static` instead of `.card` when the card is a container (e.g. auth fo
|
|
|
312
358
|
|
|
313
359
|
### Buttons
|
|
314
360
|
|
|
315
|
-
Size modifiers compose with any color variant. `.btn` works on `<button>` and on `<a>` alike:
|
|
361
|
+
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
362
|
|
|
317
363
|
```html
|
|
318
364
|
<!-- Size modifiers -->
|
|
@@ -345,37 +391,86 @@ Size modifiers compose with any color variant. `.btn` works on `<button>` and on
|
|
|
345
391
|
|
|
346
392
|
### Forms
|
|
347
393
|
|
|
394
|
+
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`.
|
|
395
|
+
|
|
348
396
|
```html
|
|
349
|
-
<
|
|
350
|
-
<
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
</div>
|
|
397
|
+
<form class="card-static space-md">
|
|
398
|
+
<div class="field">
|
|
399
|
+
<label for="name">Your Name</label>
|
|
400
|
+
<input type="text" id="name" placeholder="Enter your name">
|
|
401
|
+
</div>
|
|
402
|
+
<div class="field">
|
|
403
|
+
<label for="email">Email</label>
|
|
404
|
+
<input type="email" id="email" aria-invalid="true" aria-describedby="email-error">
|
|
405
|
+
<p class="field-error" id="email-error">Enter an email address with a domain, like you@example.com.</p>
|
|
406
|
+
</div>
|
|
407
|
+
<div class="field">
|
|
408
|
+
<label for="pass">Password</label>
|
|
409
|
+
<input type="password" id="pass" aria-describedby="pass-hint">
|
|
410
|
+
<p class="field-hint" id="pass-hint">At least 8 characters.</p>
|
|
411
|
+
</div>
|
|
412
|
+
<button class="btn btn-primary btn-block">Submit</button>
|
|
413
|
+
</form>
|
|
354
414
|
```
|
|
355
415
|
|
|
416
|
+
`.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.
|
|
417
|
+
|
|
418
|
+
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.
|
|
419
|
+
|
|
356
420
|
A `<select>` is styled like the text inputs, with a drawn chevron:
|
|
357
421
|
|
|
358
422
|
```html
|
|
359
|
-
<
|
|
360
|
-
<
|
|
423
|
+
<div class="field">
|
|
424
|
+
<label for="direction">Direction</label>
|
|
425
|
+
<select id="direction"><option>Anticlockwise</option><option>Clockwise</option></select>
|
|
426
|
+
</div>
|
|
361
427
|
```
|
|
362
428
|
|
|
363
|
-
|
|
429
|
+
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.
|
|
430
|
+
|
|
431
|
+
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
432
|
|
|
365
433
|
```html
|
|
366
|
-
<div
|
|
367
|
-
<input type="text" placeholder="Label"
|
|
368
|
-
<button class="btn-primary">Create</button>
|
|
434
|
+
<div class="control-row">
|
|
435
|
+
<input type="text" placeholder="Label" aria-label="Label">
|
|
436
|
+
<button class="btn btn-primary">Create</button>
|
|
437
|
+
</div>
|
|
438
|
+
|
|
439
|
+
<div class="control-row">
|
|
440
|
+
<div class="field">
|
|
441
|
+
<label for="driver">Driver</label>
|
|
442
|
+
<input type="text" id="driver">
|
|
443
|
+
</div>
|
|
444
|
+
<div class="field">
|
|
445
|
+
<label for="car">Car</label>
|
|
446
|
+
<select id="car"><option>Red</option><option>Blue</option></select>
|
|
447
|
+
</div>
|
|
448
|
+
<button class="btn btn-primary">Add Driver</button>
|
|
449
|
+
</div>
|
|
450
|
+
|
|
451
|
+
<div class="space-sm">
|
|
452
|
+
<div class="control-row">
|
|
453
|
+
<div class="field">
|
|
454
|
+
<label for="code">Transponder</label>
|
|
455
|
+
<input type="text" id="code" aria-invalid="true" aria-describedby="code-error">
|
|
456
|
+
</div>
|
|
457
|
+
<button class="btn btn-primary">Assign</button>
|
|
458
|
+
</div>
|
|
459
|
+
<p class="field-error" id="code-error">That transponder is already assigned.</p>
|
|
369
460
|
</div>
|
|
370
461
|
```
|
|
371
462
|
|
|
372
|
-
|
|
463
|
+
Form grids and column layouts are not part of palace: build them with `gap-*` and `space-*`.
|
|
464
|
+
|
|
465
|
+
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
466
|
|
|
374
467
|
```html
|
|
375
|
-
<
|
|
376
|
-
<
|
|
377
|
-
<
|
|
378
|
-
|
|
468
|
+
<div class="field">
|
|
469
|
+
<label for="pw">Password</label>
|
|
470
|
+
<div class="input-action">
|
|
471
|
+
<input type="password" id="pw" autocomplete="off">
|
|
472
|
+
<button type="button" class="btn btn-sm btn-outline" aria-label="Show password">Show</button>
|
|
473
|
+
</div>
|
|
379
474
|
</div>
|
|
380
475
|
```
|
|
381
476
|
|
|
@@ -441,14 +536,14 @@ Standard code block:
|
|
|
441
536
|
};</pre>
|
|
442
537
|
```
|
|
443
538
|
|
|
444
|
-
Dark reveal panel (for secrets, API keys, terminal output):
|
|
539
|
+
Dark reveal panel (for secrets, API keys, terminal output). It puts 8px between its children:
|
|
445
540
|
```html
|
|
446
541
|
<div class="code-reveal">
|
|
447
|
-
<p class="eyebrow" style="color: var(--p-accent-3);
|
|
542
|
+
<p class="eyebrow" style="color: var(--p-accent-3);">
|
|
448
543
|
Copy this — you won't see it again
|
|
449
544
|
</p>
|
|
450
545
|
<code>sk_live_abc123def456</code>
|
|
451
|
-
<div style="display: flex;
|
|
546
|
+
<div class="gap-sm" style="display: flex;">
|
|
452
547
|
<button class="btn-secondary">Copy</button>
|
|
453
548
|
</div>
|
|
454
549
|
</div>
|
|
@@ -483,21 +578,30 @@ Dark reveal panel (for secrets, API keys, terminal output):
|
|
|
483
578
|
</div>
|
|
484
579
|
```
|
|
485
580
|
|
|
486
|
-
###
|
|
581
|
+
### Space and Gap
|
|
487
582
|
|
|
488
|
-
|
|
583
|
+
`space-*` puts the same vertical space between the direct children of a container. Apply it to the parent.
|
|
489
584
|
|
|
490
585
|
```html
|
|
491
|
-
<div class="
|
|
586
|
+
<div class="space-md">
|
|
492
587
|
<p>First item</p>
|
|
493
|
-
<p>16px
|
|
494
|
-
<p>16px
|
|
588
|
+
<p>16px above</p>
|
|
589
|
+
<p>16px above</p>
|
|
495
590
|
</div>
|
|
496
591
|
```
|
|
497
592
|
|
|
498
|
-
|
|
593
|
+
`gap-*` sets the gap of a flex or grid container, for rows and grids.
|
|
499
594
|
|
|
500
|
-
|
|
595
|
+
```html
|
|
596
|
+
<div class="gap-sm" style="display: flex; flex-wrap: wrap;">
|
|
597
|
+
<span class="tag">One</span>
|
|
598
|
+
<span class="tag">Two</span>
|
|
599
|
+
</div>
|
|
600
|
+
```
|
|
601
|
+
|
|
602
|
+
Available: `xs` (4px) · `sm` (8px) · `md` (16px) · `lg` (24px) · `xl` (32px) · `2xl` (48px), as `space-md`, `gap-md` and so on.
|
|
603
|
+
|
|
604
|
+
`.stack-*` is a deprecated alias of `space-*` and will be removed in a later release.
|
|
501
605
|
|
|
502
606
|
### Dividers
|
|
503
607
|
|
|
@@ -513,7 +617,7 @@ For flex/grid parents, prefer `gap` instead. `.stack-*` is for flow-layout conte
|
|
|
513
617
|
|
|
514
618
|
```html
|
|
515
619
|
<hr class="divider-danger">
|
|
516
|
-
<div class="danger-zone">
|
|
620
|
+
<div class="danger-zone space-sm">
|
|
517
621
|
<h2>Danger Zone</h2>
|
|
518
622
|
<p>This will permanently delete your account. This cannot be undone.</p>
|
|
519
623
|
<button class="btn btn-danger btn-block">Delete My Account</button>
|
|
@@ -626,9 +730,22 @@ Lists inside `.container` or `.container-narrow` are automatically styled with p
|
|
|
626
730
|
|
|
627
731
|
### Dialog
|
|
628
732
|
|
|
629
|
-
A native `<dialog>` styled as a card: border, purple offset shadow, overlay backdrop. Actions go in a `<menu
|
|
733
|
+
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
734
|
|
|
631
735
|
```html
|
|
736
|
+
<dialog>
|
|
737
|
+
<form method="dialog">
|
|
738
|
+
<h2>Title</h2>
|
|
739
|
+
<p class="subtitle">Supporting line</p>
|
|
740
|
+
<p>Body text.</p>
|
|
741
|
+
<menu>
|
|
742
|
+
<li><button class="btn" value="cancel">Cancel</button></li>
|
|
743
|
+
<li><button class="btn btn-primary" value="confirm">Confirm</button></li>
|
|
744
|
+
</menu>
|
|
745
|
+
</form>
|
|
746
|
+
</dialog>
|
|
747
|
+
|
|
748
|
+
<!-- Without a form, the same rhythm on its direct children -->
|
|
632
749
|
<dialog>
|
|
633
750
|
<h2>Title</h2>
|
|
634
751
|
<p class="subtitle">Supporting line</p>
|
|
@@ -642,7 +759,7 @@ A native `<dialog>` styled as a card: border, purple offset shadow, overlay back
|
|
|
642
759
|
|
|
643
760
|
### Kbd
|
|
644
761
|
|
|
645
|
-
Inline keyboard key: bordered, uppercase mono, with a
|
|
762
|
+
Inline keyboard key: bordered, uppercase mono, with a pink `--p-shadow-xs` shadow.
|
|
646
763
|
|
|
647
764
|
```html
|
|
648
765
|
<kbd>Ctrl</kbd> + <kbd>Z</kbd>
|
|
@@ -668,7 +785,7 @@ It is absolutely positioned where the text would have been, with no `top` or `le
|
|
|
668
785
|
|
|
669
786
|
### Focus Visible
|
|
670
787
|
|
|
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.
|
|
788
|
+
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
789
|
|
|
673
790
|
### Reduced Motion
|
|
674
791
|
|
|
@@ -696,14 +813,16 @@ Use `container-narrow page-header` (420px). No navbar. Centered with top padding
|
|
|
696
813
|
|
|
697
814
|
```html
|
|
698
815
|
<body>
|
|
699
|
-
<div class="container-narrow page-header">
|
|
700
|
-
<
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
<!-- form contents -->
|
|
816
|
+
<div class="container-narrow page-header space-lg">
|
|
817
|
+
<div class="space-sm">
|
|
818
|
+
<p class="brand">App Name</p>
|
|
819
|
+
<h1>Page Title</h1>
|
|
820
|
+
<p class="subtitle">Helpful subtitle</p>
|
|
705
821
|
</div>
|
|
706
|
-
<
|
|
822
|
+
<form class="card-static space-md">
|
|
823
|
+
<!-- fields -->
|
|
824
|
+
</form>
|
|
825
|
+
<p style="text-align: center; font-size: 13px; color: var(--p-text-muted);">
|
|
707
826
|
Already in? <a href="/login">Log in</a>
|
|
708
827
|
</p>
|
|
709
828
|
</div>
|
|
@@ -717,9 +836,11 @@ Navbar + container with `page-header`. Use `divider` between major sections.
|
|
|
717
836
|
```html
|
|
718
837
|
<body>
|
|
719
838
|
<nav class="navbar">...</nav>
|
|
720
|
-
<div class="container page-header">
|
|
721
|
-
<
|
|
722
|
-
|
|
839
|
+
<div class="container page-header space-xl">
|
|
840
|
+
<div class="space-sm">
|
|
841
|
+
<h1>Dashboard</h1>
|
|
842
|
+
<p class="subtitle">Manage your stuff</p>
|
|
843
|
+
</div>
|
|
723
844
|
<!-- content sections -->
|
|
724
845
|
<hr class="divider">
|
|
725
846
|
<!-- more sections -->
|
|
@@ -750,7 +871,7 @@ Full container, no navbar. Hero section, then card list, then footer.
|
|
|
750
871
|
## Interaction Rules
|
|
751
872
|
|
|
752
873
|
1. **Hover = lift + shadow.** Elements move `translate(-1px, -1px)` or `translate(-2px, -2px)` and cast a hard shadow in the opposite direction. Shadow color matches the element's accent.
|
|
753
|
-
2. **Focus = border-color + shadow.** Input focus changes border to accent-2 (purple) and adds
|
|
874
|
+
2. **Focus = border-color + shadow.** Input focus changes border to accent-2 (purple) and adds the `--p-shadow-md` shadow. Number inputs focus to accent-1 (pink).
|
|
754
875
|
3. **Disabled = flat gray.** `#ddd` background, `#999` text, `#ccc` border. No transform, no shadow, `cursor: not-allowed`.
|
|
755
876
|
4. **Transitions are 0.1s.** Never slower. The UI should feel mechanical and responsive.
|
|
756
877
|
5. **Links underline with border-bottom**, not `text-decoration`. Hover swaps from accent-2 (purple) to accent-1 (pink).
|
|
@@ -773,7 +894,7 @@ Full container, no navbar. Hero section, then card list, then footer.
|
|
|
773
894
|
- Use the 3-color card rotation for any list of cards
|
|
774
895
|
- Keep `border-radius: 0` everywhere
|
|
775
896
|
- Use `2px solid` borders on cards, buttons, inputs
|
|
776
|
-
- Use hard shadows (
|
|
897
|
+
- Use hard shadows (a `--p-shadow-*` size and a colour) — never blurred shadows
|
|
777
898
|
- Use `font-weight: 700` for headings and buttons
|
|
778
899
|
- Use `letter-spacing` on all uppercase text (0.5px to 2px)
|
|
779
900
|
- Keep containers at 640px max width
|
|
@@ -808,3 +929,16 @@ Palace CSS handles h1, container, and card adjustments automatically. For page-s
|
|
|
808
929
|
.cta-row { flex-direction: column; }
|
|
809
930
|
}
|
|
810
931
|
```
|
|
932
|
+
|
|
933
|
+
## Migrating to 0.14
|
|
934
|
+
|
|
935
|
+
0.14 moves spacing from components to containers. Check every page:
|
|
936
|
+
|
|
937
|
+
- 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.
|
|
938
|
+
- `.card` and `.card-static` have no margin. Wrap a list of cards in `space-md`, or `gap-md` in a flex or grid container.
|
|
939
|
+
- Labels have no margin. Put each label and its control in a `.field`.
|
|
940
|
+
- `.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-*`.
|
|
941
|
+
- 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-*`.
|
|
942
|
+
- 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.
|
|
943
|
+
- In a `.control-row`, put a field's hint or error below the row, not inside the `.field`.
|
|
944
|
+
- Replace a margin that spaced siblings with `space-*` or `gap-*` on their parent.
|