remarque-tokens 0.16.0 → 0.18.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/AGENT_RULES.md +6 -0
- package/CHANGELOG.md +122 -0
- package/REMARQUE.md +182 -0
- package/essay.css +3 -0
- package/forms.css +424 -0
- package/package.json +4 -1
- package/scripts/audit.mjs +14 -0
- package/scripts/theme.mjs +137 -0
- package/scripts/tokens-json.mjs +1 -0
- package/theme.css +8 -0
- package/tokens-core.css +16 -0
- package/tokens-palette.css +45 -0
- package/tokens.d.ts +52 -3
- package/tokens.json +92 -1
package/AGENT_RULES.md
CHANGED
|
@@ -62,12 +62,14 @@ These are not guidelines. Agents must follow them literally.
|
|
|
62
62
|
- Within the centered column, use `.content-reading` for prose-width sections (46rem, auto-centered within the 72rem column)
|
|
63
63
|
- Do NOT use Tailwind's `max-w-reading` or `max-w-standard` on page sections — these only set max-width without centering. Use the CSS classes `.content-reading` / `.content-standard` instead, which include `margin-inline: auto`
|
|
64
64
|
- Code blocks (`<pre>`) inherit the width of their parent container — no special wrapping needed when the parent is already constrained
|
|
65
|
+
- Stacking order is structural, not personalization: never author a bare `z-index` number — reference `tokens-core.css`'s `--z-*` scale (`--z-base`/`--z-sticky`/`--z-dropdown`/`--z-overlay`/`--z-modal`/`--z-toast`/`--z-skip-link`). Tailwind v4 has no `--z-index-*` theme namespace, so use arbitrary values (`z-[var(--z-modal)]`) rather than bare Tailwind numbers. See REMARQUE.md "Stacking."
|
|
65
66
|
|
|
66
67
|
### Color
|
|
67
68
|
|
|
68
69
|
- Accent color is used for exactly two things: inline links and one interactive element per viewport
|
|
69
70
|
- Dark mode is not an inverted light mode — it must be independently tuned for readability
|
|
70
71
|
- Background colors use `--color-bg`, never pure white (#fff) or pure black (#000)
|
|
72
|
+
- State colors (`--color-error`/`--color-success`/`--color-warning`/`--color-disabled`, plus the `-subtle` banner-background companions on the first three) are for feedback moments only — form validation, status banners, disabled controls — never for decoration. The one-accent rule above still governs everything else. See REMARQUE.md "State Colors."
|
|
71
73
|
|
|
72
74
|
### Components
|
|
73
75
|
|
|
@@ -143,6 +145,7 @@ project/
|
|
|
143
145
|
├── prose.css # .remarque-prose long-form styling (aggregated by tokens.css; own subpath for opt-out)
|
|
144
146
|
├── essay.css # Optional Essay module: sidenotes + sticky TOC rail (own subpath, NOT aggregated — import explicitly)
|
|
145
147
|
├── broadsheet.css # Optional Broadsheet pattern: masthead, lead, entry list, post kicker (own subpath, NOT aggregated — import explicitly)
|
|
148
|
+
├── forms.css # Optional form control primitives: field/input/checkbox/radio/button, state-color wiring (own subpath, NOT aggregated — import explicitly)
|
|
146
149
|
├── print.css # Print stylesheet (own subpath, NOT aggregated — import explicitly)
|
|
147
150
|
├── theme.css # Tailwind v4 adapter (@theme inline) — import after tailwindcss + tokens
|
|
148
151
|
├── tailwind.config.js # Tailwind v3 ONLY — v4 projects use theme.css instead
|
|
@@ -205,6 +208,7 @@ Before considering any implementation complete, verify:
|
|
|
205
208
|
- [ ] Every page maps to an archetype (Essay, Dossier, Notebook, Landing, Reference/Docs, Changelog, Gallery)
|
|
206
209
|
- [ ] If the Essay uses sidenotes/a TOC rail (`remarque-tokens/essay`): `.remarque-sidenote-ref`/`.remarque-sidenote` alternate in strict DOM order, the rail never intrudes into `.remarque-prose`'s own measure, and the page renders correctly with `essay.css`'s `@media` block deleted (the narrow-viewport/no-JS fallback)
|
|
207
210
|
- [ ] If a Landing/archive page uses the Broadsheet pattern (`remarque-tokens/broadsheet`): entry numerals are generated from `data-entry-number` via `attr()` (not `counter()`), the entry list stays a `<ul>` (not `<ol>` — the numeral is `aria-hidden` and decorative), and every kicker/dateline row uses `font-variant-caps: all-small-caps`, never `text-transform: uppercase`
|
|
211
|
+
- [ ] If a page uses form controls (`remarque-tokens/forms`): checkboxes/radios are styled with `accent-color` only — never `appearance: none` plus a hand-drawn replacement; every control (input, button, checkbox/radio label) is ≥44×44px; validation state lives on `.remarque-field[data-state]` AND a real `aria-invalid`/`aria-describedby` pair on the input, not `data-state` alone; disabled controls use `--color-disabled`, never a state color
|
|
208
212
|
- [ ] Mobile version is roomy — not a compressed desktop layout
|
|
209
213
|
- [ ] Mobile nav links have ≥44px touch targets
|
|
210
214
|
- [ ] No pure white or pure black backgrounds
|
|
@@ -212,6 +216,8 @@ Before considering any implementation complete, verify:
|
|
|
212
216
|
- [ ] Muted text placed on `--color-surface` still meets 4.5:1 (check the surface pairing, not just bg)
|
|
213
217
|
- [ ] All transitions use the motion duration tokens (reduced-motion support depends on it)
|
|
214
218
|
- [ ] Skip-to-content link present and functional
|
|
219
|
+
- [ ] If state colors are used (error/success/warning/disabled): only for feedback moments (validation, banners, disabled controls), never decoration; every state text color and `-subtle` companion passes `npm run audit`
|
|
220
|
+
- [ ] No bare `z-index` numbers anywhere in the page's CSS — every stacking layer references `tokens-core.css`'s `--z-*` scale
|
|
215
221
|
- [ ] OG meta tags present (og:title, og:description, og:image)
|
|
216
222
|
- [ ] `<html lang="en">` attribute set
|
|
217
223
|
- [ ] The site looks more like a book than a web app
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,128 @@ All notable changes to `remarque-tokens` are documented here. Token value
|
|
|
4
4
|
changes always state the design rationale — downstream sites pin against
|
|
5
5
|
these entries when syncing.
|
|
6
6
|
|
|
7
|
+
## 0.18.0 — 2026-07-23
|
|
8
|
+
|
|
9
|
+
Form control primitives + reference components (closes #27, closes #30).
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
- **`forms.css` — form control primitives module (issue #27).** New own-subpath
|
|
13
|
+
module (`remarque-tokens/forms`, `remarque-tokens/forms.css`), NOT aggregated
|
|
14
|
+
into `tokens.css` — matches `essay.css`/`broadsheet.css`/`print.css`'s
|
|
15
|
+
opt-in convention. Spec-native (built directly from the issue, not
|
|
16
|
+
graduated from a downstream site — no prior flagship implementation to
|
|
17
|
+
re-express).
|
|
18
|
+
- `.remarque-field` (label + control + help/error message vertical stack),
|
|
19
|
+
`.remarque-field-label` (meta voice, same declarations as `.text-label`),
|
|
20
|
+
`.remarque-field-required`, `.remarque-field-message`.
|
|
21
|
+
- `.remarque-input` — shared class across `<input>`/`<textarea>`/`<select>`:
|
|
22
|
+
body-voice text, `--color-border-bold` boundary (functional, 3:1-checked),
|
|
23
|
+
`--radius-sm` (tighter than the general 8px ceiling — form controls stay
|
|
24
|
+
more precise-reading), ≥44px tall, `::placeholder` at `--color-muted`
|
|
25
|
+
(a conscious AA choice, documented — placeholder is supplementary hint
|
|
26
|
+
copy, never the field's only label).
|
|
27
|
+
- `.remarque-checkbox` / `.remarque-radio` — `accent-color` only, no
|
|
28
|
+
`appearance: none`, no hand-drawn replacement; native controls keep every
|
|
29
|
+
platform accessibility behavior. Sized at `--space-5` (24px), wrapped in
|
|
30
|
+
a `<label>` carrying the 44px touch target.
|
|
31
|
+
- `.remarque-button` (+ `--primary` variant) — quiet by rule: bordered,
|
|
32
|
+
transparent, body-voice text by default; `--primary` is the one
|
|
33
|
+
sanctioned accent placement per viewport, still unfilled (accent
|
|
34
|
+
text/border, hover washes in `--color-accent-subtle`, never a solid
|
|
35
|
+
fill). Disabled state (native `:disabled`) uses `--color-disabled`.
|
|
36
|
+
- Validation state wiring on the 0.17.0 state-color tokens:
|
|
37
|
+
`.remarque-field[data-state="error"|"success"|"warning"]` recolors the
|
|
38
|
+
input border and message text together; always pairs with a real
|
|
39
|
+
`aria-invalid`/`aria-describedby` on the input (`data-state` is paint
|
|
40
|
+
only). `.remarque-input:user-invalid`, guarded with
|
|
41
|
+
`@supports selector(:user-invalid)`, is a zero-JS bonus layer.
|
|
42
|
+
- `.remarque-table` / `.remarque-table-wrap` — a standalone-table
|
|
43
|
+
re-scoping of `prose.css`'s table rules (mono `th`, 2px header rule, 1px
|
|
44
|
+
row rules, `.num` tabular-lining columns) for data tables that shouldn't
|
|
45
|
+
be wrapped in the full `.remarque-prose` container. Lives in `forms.css`
|
|
46
|
+
rather than a fifth subpath — AGENT_RULES.md's build order already
|
|
47
|
+
groups tables with buttons/cards as one supplementary-UI step.
|
|
48
|
+
- REMARQUE.md "Forms" section — full markup contract, state-wiring rules,
|
|
49
|
+
restraint rules restated (radius/touch-targets/no-fake-replacements/
|
|
50
|
+
quiet-buttons/placeholder-contrast), standalone-tables note, and "when
|
|
51
|
+
NOT to use" (Remarque is editorial-first — contact/search/newsletter
|
|
52
|
+
moments, not app UIs). AGENT_RULES.md's File Structure Convention and
|
|
53
|
+
Quality Checklist gain matching entries.
|
|
54
|
+
- `scripts/audit.mjs`'s `--src .` invocation covers `forms.css` for free
|
|
55
|
+
(font-floor + no-hardcoded-color scans — no new pairings needed, this
|
|
56
|
+
module introduces no new color tokens).
|
|
57
|
+
- **Reference components (demo site, issue #30)** — `site/src/components/`:
|
|
58
|
+
`Button.astro`, `Input.astro` (a `.remarque-field` wrapper — label/help/
|
|
59
|
+
error props, wires `for`/`id`/`aria-describedby`/`aria-invalid`),
|
|
60
|
+
`Table.astro` (`.remarque-table`, standalone). New demo page
|
|
61
|
+
`site/pages/components` exercises every input state (default/focus/error/
|
|
62
|
+
success/disabled), both button variants, and a sample table in both
|
|
63
|
+
themes — added to `site/tests/helpers.ts`'s `PAGES` for visual-regression
|
|
64
|
+
coverage (new baselines for this page only; no existing baseline changed)
|
|
65
|
+
and linked from the site nav.
|
|
66
|
+
|
|
67
|
+
## 0.17.0 — 2026-07-23
|
|
68
|
+
|
|
69
|
+
Semantic state colors + z-index scale (closes #26, closes #29).
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
- **State colors (`tokens-palette.css`, PALETTE tier)** — four semantic slots for feedback
|
|
73
|
+
moments (form validation, status banners, disabled controls), never decoration; the
|
|
74
|
+
one-accent rule still governs everything else. Hand-authored from the house ANSI hue
|
|
75
|
+
conventions, both themes, all three dark-mode conventions (`@media
|
|
76
|
+
prefers-color-scheme: dark`, `[data-theme="dark"]`, `:root.dark`):
|
|
77
|
+
- `--color-error` (hue 25, ANSI red) — light `oklch(0.52 0.12 25)` 5.44:1 bg / 5.28:1
|
|
78
|
+
surface; dark `oklch(0.62 0.11 26)` 5.07:1 bg / 4.82:1 surface.
|
|
79
|
+
- `--color-success` (hue 145, ANSI green) — light `oklch(0.51 0.12 145)` 5.08:1 bg /
|
|
80
|
+
4.93:1 surface; dark `oklch(0.61 0.11 145)` 5.36:1 bg / 5.10:1 surface.
|
|
81
|
+
- `--color-warning` (hue 85, ANSI yellow) — light `oklch(0.52 0.105 85)` 5.17:1 bg /
|
|
82
|
+
5.02:1 surface; dark `oklch(0.62 0.11 85)` 5.29:1 bg / 5.03:1 surface. The hard case:
|
|
83
|
+
yellow's low luminance-contrast means this slot solves noticeably darker in light
|
|
84
|
+
mode than error/success, the same shape as `--color-syntax-constant`'s solve.
|
|
85
|
+
- `--color-disabled` — aliased to `var(--color-muted)` in both themes: neutral
|
|
86
|
+
hue-80 muted family, deliberately **not** ANSI-derived.
|
|
87
|
+
- `-subtle` banner-background companions on the first three (`--color-error-subtle`/
|
|
88
|
+
`--color-success-subtle`/`--color-warning-subtle`, modeled on `--color-accent-subtle`
|
|
89
|
+
— near-bg lightness, state hue, low chroma) verified so `--color-fg` stays ≥4.5:1 on
|
|
90
|
+
them (the pairing that matters for callout/banner body text). No `-subtle` for
|
|
91
|
+
`--color-disabled` — a disabled control is quieter, not tinted.
|
|
92
|
+
- Every state text color ≥4.5:1 against `--color-bg` **and** `--color-surface`, both
|
|
93
|
+
themes; `scripts/audit.mjs` gains the 11 new pairings, `scripts/test-audit.mjs`'s
|
|
94
|
+
fixtures cover all seven tokens plus a must-fail case (`state-color-fails.css`).
|
|
95
|
+
- `scripts/theme.mjs` (`remarque-theme`) derives error/success/warning from a source
|
|
96
|
+
theme's red/green/yellow ANSI slots — keep-if-passing lightness checked against the
|
|
97
|
+
**stricter** of `--color-bg`/`--color-surface` at once (a new dual-target solver,
|
|
98
|
+
`keepOrSolveDual`/`solveDual`), not just one target like every other slot. Disabled
|
|
99
|
+
aliases the already-derived `--color-muted`. `-subtle` companions derive like
|
|
100
|
+
`--color-accent-subtle` (fixed 0.95 / bg+0.06 starting lightness — not the theme's
|
|
101
|
+
own solved bg lightness, which can exceed 0.95), nudged toward the extreme only if a
|
|
102
|
+
pathological theme doesn't already clear 4.5:1 against `--color-fg`. Self-verify
|
|
103
|
+
`CHECKS` mirrors `audit.mjs`'s new pairings exactly.
|
|
104
|
+
- `scripts/palette-golden.mjs` golden-gates all seven new tokens for free (it already
|
|
105
|
+
iterates whatever the bridge emits) — ΔE2000 ≤ 2.0 against `remarque-light`/
|
|
106
|
+
`remarque-dark`'s ANSI derivation, same identity/serialization contract as the rest
|
|
107
|
+
of the default palette. All new tokens land at ΔE ≤ 0.5 (see the PR description for
|
|
108
|
+
the full per-token table).
|
|
109
|
+
- REMARQUE.md "State Colors" — semantics, usage table, derivation note; Enforcement
|
|
110
|
+
Checklist gains the state-color pairing line.
|
|
111
|
+
- **Z-index scale (`tokens-core.css`, CORE tier)** — stacking is structural, not
|
|
112
|
+
personalization. A small ordinal scale, sparse gaps of 10: `--z-base` (0), `--z-sticky`
|
|
113
|
+
(10), `--z-dropdown` (20), `--z-overlay` (30), `--z-modal` (40), `--z-toast` (50),
|
|
114
|
+
`--z-skip-link` (60, tops everything). Wired into `essay.css`'s sticky TOC rail
|
|
115
|
+
(`z-index: var(--z-sticky)`) and the demo site's skip-to-content link
|
|
116
|
+
(`focus:z-[var(--z-skip-link)]`, replacing a hardcoded Tailwind `focus:z-50`).
|
|
117
|
+
`theme.css`'s header comment documents the Tailwind v4 workaround — v4 has no
|
|
118
|
+
`--z-index-*` theme namespace, so `z-*` utilities can't map to these directly; use
|
|
119
|
+
arbitrary values (`z-[var(--z-modal)]`) instead, same pattern as the motion durations.
|
|
120
|
+
REMARQUE.md "Stacking" — the scale, and the rule that consumer CSS must never author a
|
|
121
|
+
bare `z-index` number. AGENT_RULES.md's Layout/Quality Checklist sections gain matching
|
|
122
|
+
lines.
|
|
123
|
+
|
|
124
|
+
### Changed
|
|
125
|
+
- **`scripts/tokens-json.mjs`** — `typeOf()` now types `--z-*` tokens as `number`
|
|
126
|
+
(unitless stacking-order integers), matching the existing `--leading-*` treatment,
|
|
127
|
+
instead of falling through to the generic `string` type.
|
|
128
|
+
|
|
7
129
|
## 0.16.0 — 2026-07-23
|
|
8
130
|
|
|
9
131
|
Broadsheet pattern — masthead, lead article, numbered entry list, post-header kicker, graduated from the flagship (closes #36).
|
package/REMARQUE.md
CHANGED
|
@@ -90,6 +90,23 @@ The audit remains the gate regardless of provenance — `remarque-theme` self-ve
|
|
|
90
90
|
|
|
91
91
|
---
|
|
92
92
|
|
|
93
|
+
## State Colors
|
|
94
|
+
|
|
95
|
+
Four semantic slots — `--color-error`, `--color-success`, `--color-warning`, `--color-disabled` — for feedback moments: form validation, status banners, disabled controls. **These are for feedback, not decoration.** The one-accent rule ("Visual Rules" / "Changing the Accent Hue") still governs expressive color everywhere else — a state color says "this specific thing failed/succeeded/needs attention/can't be used right now," not "this section is important." Don't recolor headings, borders, or chrome with a state color; reserve it for the actual feedback element (an inline error message, a success toast, a disabled button's text).
|
|
96
|
+
|
|
97
|
+
Three of the four carry a `-subtle` companion — `--color-error-subtle`, `--color-success-subtle`, `--color-warning-subtle` — a faint tinted background for callout/banner-style feedback (an error banner, a success toast), sized the same way `--color-accent-subtle` is: near-`--color-bg` lightness, the state's hue, low chroma. `--color-disabled` has no `-subtle` companion — a disabled control is quieter than its enabled state, not tinted; use `--color-surface`/`--color-bg-subtle` for a disabled control's background if it needs one.
|
|
98
|
+
|
|
99
|
+
| Slot | Use for | `-subtle` companion |
|
|
100
|
+
|---|---|---|
|
|
101
|
+
| `--color-error` | Validation errors, failure states, destructive-action confirmation text | `--color-error-subtle` (banner/callout background) |
|
|
102
|
+
| `--color-success` | Confirmation messages, completed states | `--color-success-subtle` |
|
|
103
|
+
| `--color-warning` | Caution messages, states needing attention before proceeding | `--color-warning-subtle` |
|
|
104
|
+
| `--color-disabled` | Text/icon color for a disabled control | — (no subtle background; see above) |
|
|
105
|
+
|
|
106
|
+
**Derivation:** hand-authored in `tokens-palette.css` from the house ANSI hue conventions — error hue 25 (red), success hue 145 (green), warning hue 85 (yellow) — the same conventions `--color-syntax-string`/`--color-syntax-constant` already use for green/yellow. `scripts/remarque-theme` derives all three from a source theme's `red`/`green`/`yellow` ANSI slots (keep-if-passing lightness, checked against the **stricter** of `--color-bg` and `--color-surface` at once, not just one), exactly like every other slot in "Color Providers." `--color-disabled` is deliberately **not** ANSI-derived — it aliases the already-derived neutral `--color-muted` family, since a disabled state is a muted/quiet register, not a hue. Warning (hue 85, yellow) is the hard case in light mode — yellow has low luminance-contrast against a light background, so its solved lightness sits noticeably darker than the other two states, the same shape as `--color-syntax-constant`'s solve. Every state text color holds ≥ 4.5:1 against `--color-bg` **and** `--color-surface` in both themes; every `-subtle` background holds `--color-fg` ≥ 4.5:1 on it (the pairing that matters for a callout's body text) — both enforced by `scripts/audit.mjs` and golden-gated (ΔE2000 ≤ 2.0) against the upstream themes like the rest of the default palette.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
93
110
|
## Font Slots
|
|
94
111
|
|
|
95
112
|
Remarque uses a three-slot font system. Each slot has a strict role, and each slot accepts a small set of approved faces — swap the face, keep the role.
|
|
@@ -365,6 +382,26 @@ Motion in Remarque is nearly invisible. The only permitted motion:
|
|
|
365
382
|
|
|
366
383
|
---
|
|
367
384
|
|
|
385
|
+
## Stacking
|
|
386
|
+
|
|
387
|
+
Stacking order is structural, not personalization — `tokens-core.css` (CORE tier, never overridden) carries a small ordinal `--z-*` scale:
|
|
388
|
+
|
|
389
|
+
| Token | Value | Use for |
|
|
390
|
+
|---|---:|---|
|
|
391
|
+
| `--z-base` | 0 | Default stacking context — the implicit baseline |
|
|
392
|
+
| `--z-sticky` | 10 | Sticky headers/rails (essay.css's TOC rail) |
|
|
393
|
+
| `--z-dropdown` | 20 | Dropdown/select menus |
|
|
394
|
+
| `--z-overlay` | 30 | Overlays/backdrops |
|
|
395
|
+
| `--z-modal` | 40 | Modal dialogs |
|
|
396
|
+
| `--z-toast` | 50 | Toast/notification stacks |
|
|
397
|
+
| `--z-skip-link` | 60 | The skip-to-content link — tops everything; it must never be obscured when focused |
|
|
398
|
+
|
|
399
|
+
**The rule: never a bare `z-index` number in consumer CSS.** Reference one of these seven tokens instead — an unnamed `z-index: 999` (or any other asserted integer) can't be reasoned about against the rest of the page's stacking contexts, and it's the same "hardcoded value bypasses the token system" problem as a literal hex color or a bare font-size. The scale is deliberately sparse (gaps of 10) so a future layer can be inserted between two existing rungs without renumbering everything above it.
|
|
400
|
+
|
|
401
|
+
Tailwind v4 ships `z-*` as a static, non-themable utility scale — there's no `--z-index-*` entry in its default `@theme` to map these into. `theme.css` (the Tailwind v4 adapter) documents the workaround in its header comment: use arbitrary values with the tokens, `z-[var(--z-modal)]` / `focus:z-[var(--z-skip-link)]`, the same pattern already used for motion durations (`duration-[var(--motion-fast)]`).
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
368
405
|
## USWDS Accessibility Compliance
|
|
369
406
|
|
|
370
407
|
Remarque adopts typography and accessibility standards from the [US Web Design System (USWDS)](https://designsystem.digital.gov/documentation/accessibility/) and [WCAG 2.1](https://www.w3.org/WAI/WCAG21/Understanding/):
|
|
@@ -419,6 +456,8 @@ Every PR that ships Remarque pages MUST pass (`npm run audit` automates the colo
|
|
|
419
456
|
- [ ] No hardcoded hex/rgb colors — only `var(--color-*)` tokens.
|
|
420
457
|
- [ ] Body line-height ≥ 1.5 (Remarque target: 1.75).
|
|
421
458
|
- [ ] Every `--color-syntax-*` slot ≥ 4.5:1 against `--color-code-bg` in both themes (see "Syntax Highlighting").
|
|
459
|
+
- [ ] Every `--color-error`/`--color-success`/`--color-warning`/`--color-disabled` ≥ 4.5:1 against `--color-bg` **and** `--color-surface` in both themes; every `-subtle` background keeps `--color-fg` ≥ 4.5:1 on it (see "State Colors"). State colors used only for feedback moments, never decoration.
|
|
460
|
+
- [ ] No bare `z-index` number in consumer CSS — reference `tokens-core.css`'s `--z-*` scale (see "Stacking").
|
|
422
461
|
|
|
423
462
|
Agents reviewing PRs should reject changes that violate any line above without explicit rationale.
|
|
424
463
|
|
|
@@ -939,6 +978,149 @@ the archive itself.
|
|
|
939
978
|
|
|
940
979
|
---
|
|
941
980
|
|
|
981
|
+
## Forms
|
|
982
|
+
|
|
983
|
+
Native form-control primitives — field wrapper, text input, checkbox,
|
|
984
|
+
radio, button — shipped as their own subpath, `remarque-tokens/forms`
|
|
985
|
+
(issue #27). Unlike the Essay Module and the Broadsheet pattern, this
|
|
986
|
+
module was not graduated from a downstream site implementation; it is
|
|
987
|
+
spec-native, built directly from the issue rather than re-expressing an
|
|
988
|
+
existing literal.
|
|
989
|
+
|
|
990
|
+
### Markup contract
|
|
991
|
+
|
|
992
|
+
```html
|
|
993
|
+
<div class="remarque-field">
|
|
994
|
+
<label class="remarque-field-label" for="email">Email</label>
|
|
995
|
+
<input class="remarque-input" type="email" id="email" name="email"
|
|
996
|
+
aria-describedby="email-help" />
|
|
997
|
+
<p class="remarque-field-message" id="email-help">
|
|
998
|
+
We'll never share your email.
|
|
999
|
+
</p>
|
|
1000
|
+
</div>
|
|
1001
|
+
|
|
1002
|
+
<div class="remarque-field" data-state="error">
|
|
1003
|
+
<label class="remarque-field-label" for="email2">Email</label>
|
|
1004
|
+
<input class="remarque-input" type="email" id="email2" name="email2"
|
|
1005
|
+
aria-invalid="true" aria-describedby="email2-message" required />
|
|
1006
|
+
<p class="remarque-field-message" id="email2-message" role="alert">
|
|
1007
|
+
Enter a valid email address.
|
|
1008
|
+
</p>
|
|
1009
|
+
</div>
|
|
1010
|
+
|
|
1011
|
+
<label class="remarque-checkbox">
|
|
1012
|
+
<input type="checkbox" name="subscribe" />
|
|
1013
|
+
<span>Subscribe to updates</span>
|
|
1014
|
+
</label>
|
|
1015
|
+
|
|
1016
|
+
<label class="remarque-radio">
|
|
1017
|
+
<input type="radio" name="plan" value="a" />
|
|
1018
|
+
<span>Plan A</span>
|
|
1019
|
+
</label>
|
|
1020
|
+
|
|
1021
|
+
<button class="remarque-button" type="button">Cancel</button>
|
|
1022
|
+
<button class="remarque-button remarque-button--primary" type="submit">Submit</button>
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
| Class | Applies to | Notes |
|
|
1026
|
+
|---|---|---|
|
|
1027
|
+
| `.remarque-field` | wrapping `<div>` | Label + control + message vertical stack. Layout only — no border/background of its own. |
|
|
1028
|
+
| `.remarque-field-label` | `<label>` | Meta voice (mono, small caps, `--color-muted`) — same declarations as `.text-label`, repeated per the non-mixin precedent essay.css/broadsheet.css already set. |
|
|
1029
|
+
| `.remarque-field-required` | `<span aria-hidden="true">` inside the label | Accent-colored asterisk. `aria-hidden` — the input's own `required` attribute is the real signal a screen reader announces. |
|
|
1030
|
+
| `.remarque-field-message` | `<p>` after the control | Help text by default; recolored by the parent's `data-state`. Wire `aria-describedby` on the input to this element's `id` in every case, valid or not. |
|
|
1031
|
+
| `.remarque-input` | `<input>` / `<textarea>` / `<select>` | Body-voice text, `--color-border-bold` boundary, `--radius-sm`, ≥44px tall. |
|
|
1032
|
+
| `.remarque-checkbox` / `.remarque-radio` | wrapping `<label>` | `accent-color` on the native control — no `appearance: none`, no hand-drawn replacement. The wrapping label carries the 44px touch target; the control itself stays at its natural (enlarged) size. |
|
|
1033
|
+
| `.remarque-button` | `<button>` | Quiet default: bordered, transparent, body-voice text. |
|
|
1034
|
+
| `.remarque-button--primary` | `<button>` | The one sanctioned accent placement per viewport (Visual Rules) — accent text + accent border, never a solid accent fill. Hover washes in `--color-accent-subtle`, it does not darken to a filled block. |
|
|
1035
|
+
|
|
1036
|
+
### State wiring
|
|
1037
|
+
|
|
1038
|
+
`data-state="error"` / `"success"` / `"warning"` on `.remarque-field`
|
|
1039
|
+
recolors both the input's border and the message text from the 0.17.0
|
|
1040
|
+
state-color tokens (`--color-error`/`--color-success`/`--color-warning`).
|
|
1041
|
+
`data-state` is the PAINT layer only — always pair it with the real
|
|
1042
|
+
accessibility signal on the input itself: `aria-invalid="true"` (screen
|
|
1043
|
+
readers announce this; `data-state` alone is invisible to them) and
|
|
1044
|
+
`aria-describedby` pointing at the `.remarque-field-message` id. A
|
|
1045
|
+
disabled control never gets a `data-state` — it uses the native
|
|
1046
|
+
`:disabled`/`disabled` state and `--color-disabled`, which is a muted
|
|
1047
|
+
register, not one of the three feedback hues (REMARQUE.md "State Colors":
|
|
1048
|
+
disabled is deliberately not ANSI-derived).
|
|
1049
|
+
|
|
1050
|
+
As a zero-JS bonus layer, `.remarque-input:user-invalid` (guarded with
|
|
1051
|
+
`@supports selector(:user-invalid)`) picks up the same error border once
|
|
1052
|
+
a browser supports the pseudo-class and the user has actually interacted
|
|
1053
|
+
with an invalid field — it never replaces authoring `data-state="error"`
|
|
1054
|
+
explicitly, since `:user-invalid` alone has no matching text-message
|
|
1055
|
+
recolor and no `aria-invalid` wiring of its own.
|
|
1056
|
+
|
|
1057
|
+
### Restraint rules restated
|
|
1058
|
+
|
|
1059
|
+
- **Border radius**: form controls cap at `--radius-sm` (4px) — a
|
|
1060
|
+
tighter ceiling than AGENT_RULES.md's general `--radius-md` (8px)
|
|
1061
|
+
maximum for other chrome. A smaller, more precise-reading radius suits
|
|
1062
|
+
a control the user directly manipulates.
|
|
1063
|
+
- **Touch targets**: every interactive control — input, textarea,
|
|
1064
|
+
select, button, and the `<label>` wrapping a checkbox/radio — is
|
|
1065
|
+
≥44×44px (WCAG 2.5.5 AAA, USWDS floor; see "Touch Targets" above and
|
|
1066
|
+
`.nav-link`'s identical convention in the demo site's `globals.css`).
|
|
1067
|
+
- **No fake replacements**: checkboxes and radios stay native elements
|
|
1068
|
+
recolored with `accent-color` only. No `appearance: none` plus a
|
|
1069
|
+
hand-drawn box/dot — that would trade away native keyboard behavior,
|
|
1070
|
+
forced-colors-mode support, and screen-reader state announcements for
|
|
1071
|
+
a purely cosmetic win this system doesn't need.
|
|
1072
|
+
- **Buttons stay quiet**: text-only or bordered, never filled/solid by
|
|
1073
|
+
default — the primary variant included. Accent appears as text/border
|
|
1074
|
+
color, never as a background fill (Visual Rules' one-accent rule and
|
|
1075
|
+
Components' "never filled/solid as default" both still govern the
|
|
1076
|
+
emphasized variant).
|
|
1077
|
+
- **Placeholder contrast**: `--color-muted` (4.5:1 on `--color-bg`/
|
|
1078
|
+
`--color-surface`), a conscious choice — placeholder text is
|
|
1079
|
+
supplementary hint copy, never the field's only label, so AA is the
|
|
1080
|
+
correct tier rather than `--color-fg-muted`'s AAA.
|
|
1081
|
+
|
|
1082
|
+
### Standalone tables
|
|
1083
|
+
|
|
1084
|
+
`forms.css` also ships `.remarque-table` / `.remarque-table-wrap`
|
|
1085
|
+
(issue #30) — the same visual language as `.remarque-prose table`
|
|
1086
|
+
(mono `th` voice, 2px header rule, 1px row rules, `.num` for tabular-
|
|
1087
|
+
lining right-aligned numeric columns), re-scoped under a top-level
|
|
1088
|
+
class so a standalone data grid doesn't have to wrap itself in the full
|
|
1089
|
+
`.remarque-prose` container (which also applies oldstyle proportional
|
|
1090
|
+
numerals and prose spacing rhythm a data table doesn't want):
|
|
1091
|
+
|
|
1092
|
+
```html
|
|
1093
|
+
<div class="remarque-table-wrap">
|
|
1094
|
+
<table class="remarque-table">
|
|
1095
|
+
<caption>Example</caption>
|
|
1096
|
+
<thead>
|
|
1097
|
+
<tr><th>Name</th><th class="num">Count</th></tr>
|
|
1098
|
+
</thead>
|
|
1099
|
+
<tbody>
|
|
1100
|
+
<tr><td>Rows</td><td class="num">42</td></tr>
|
|
1101
|
+
</tbody>
|
|
1102
|
+
</table>
|
|
1103
|
+
</div>
|
|
1104
|
+
```
|
|
1105
|
+
|
|
1106
|
+
Lives in `forms.css` rather than its own subpath — AGENT_RULES.md's
|
|
1107
|
+
build order already groups tables with buttons/cards/code blocks as one
|
|
1108
|
+
"supplementary UI" step, and this table variant is a small re-scoping,
|
|
1109
|
+
not enough surface area to justify a fourth optional module.
|
|
1110
|
+
|
|
1111
|
+
### When NOT to use
|
|
1112
|
+
|
|
1113
|
+
Remarque is editorial-first. This module exists for the handful of
|
|
1114
|
+
form moments a written-word site actually needs — a contact form, a
|
|
1115
|
+
site search box, a newsletter signup — not for building application
|
|
1116
|
+
UIs. If a page needs more than a few fields, conditional multi-step
|
|
1117
|
+
logic, inline data tables of editable rows, or anything that starts to
|
|
1118
|
+
resemble a settings/dashboard screen, that is out of scope for
|
|
1119
|
+
Remarque's forms primitives; reach for a dedicated UI/form library
|
|
1120
|
+
instead and keep Remarque to the page's editorial chrome around it.
|
|
1121
|
+
|
|
1122
|
+
---
|
|
1123
|
+
|
|
942
1124
|
## Signature Moves
|
|
943
1125
|
|
|
944
1126
|
These are the repeatable visual tells that make a Remarque site recognizable:
|
package/essay.css
CHANGED
|
@@ -421,6 +421,9 @@
|
|
|
421
421
|
align-self: start;
|
|
422
422
|
justify-self: start;
|
|
423
423
|
position: sticky;
|
|
424
|
+
/* --z-sticky (tokens-core.css, issue #29) — never a bare z-index
|
|
425
|
+
number in consumer CSS. */
|
|
426
|
+
z-index: var(--z-sticky);
|
|
424
427
|
top: var(--space-6);
|
|
425
428
|
width: 100%;
|
|
426
429
|
max-height: calc(100vh - var(--space-8));
|