fertig 4.0.3 → 4.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -436
- package/fertig.css +226 -107
- package/fertig.min.css +1 -1
- package/package.json +10 -10
- package/CHANGELOG.md +0 -481
package/CHANGELOG.md
DELETED
|
@@ -1,481 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to this project are documented here. This project follows
|
|
4
|
-
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). The public surface
|
|
5
|
-
is the token names, the class names (the seven, plus the layout utilities),
|
|
6
|
-
and the ARIA attributes the component layer reads — changes to any of those
|
|
7
|
-
are breaking.
|
|
8
|
-
|
|
9
|
-
## Unreleased
|
|
10
|
-
|
|
11
|
-
## [4.0.3] — 2026-09-01
|
|
12
|
-
|
|
13
|
-
### Fixed
|
|
14
|
-
|
|
15
|
-
- **Disabled filled buttons look disabled.** Primary and submit controls now
|
|
16
|
-
return to the quiet control surface with muted text instead of retaining the
|
|
17
|
-
enabled accent fill.
|
|
18
|
-
- **Every published tab example is a real tab widget.** Examples now pair each
|
|
19
|
-
tab with a labelled panel, keep only the active tab in the Tab sequence and
|
|
20
|
-
support Left, Right, Home and End keys through one shared controller.
|
|
21
|
-
|
|
22
|
-
## [4.0.2] — 2026-09-01
|
|
23
|
-
|
|
24
|
-
### Changed
|
|
25
|
-
|
|
26
|
-
- **Body-level page containers are full width by default.** fertig keeps the
|
|
27
|
-
responsive page gutter but no longer applies a maximum width to direct body
|
|
28
|
-
children or supported app-root children. Explicit `max-w-*`
|
|
29
|
-
utilities remain available when a page needs a constrained measure.
|
|
30
|
-
|
|
31
|
-
## [4.0.1] — 2026-09-01
|
|
32
|
-
|
|
33
|
-
### Changed
|
|
34
|
-
|
|
35
|
-
- **Buttons are flat and stay put.** The raised shadow, filled-button highlight
|
|
36
|
-
and active press nudge are gone. Hover contrast, focus-visible outlines,
|
|
37
|
-
disabled feedback and coarse-pointer target sizing remain intact.
|
|
38
|
-
- **The public documentation speaks only about fertig.** Comparative product
|
|
39
|
-
names, size rankings and survey links were removed from every published page.
|
|
40
|
-
|
|
41
|
-
### Fixed
|
|
42
|
-
|
|
43
|
-
- **Shared mobile controls now have reliable touch targets.** Navigation,
|
|
44
|
-
theme, colour, catalogue filter and sidebar controls reach 44 by 44 pixels;
|
|
45
|
-
catalogue filters stay in one horizontal row instead of building a tall
|
|
46
|
-
stack on narrow screens.
|
|
47
|
-
- **Theme and copy feedback are clearer.** The theme control names its target,
|
|
48
|
-
while clipboard fallbacks select the text and use platform-neutral wording.
|
|
49
|
-
|
|
50
|
-
## [4.0.0] — 2026-09-01
|
|
51
|
-
|
|
52
|
-
### Changed
|
|
53
|
-
|
|
54
|
-
- **The palette is new and intentionally direct.** `gray`, `blue`, `cyan`,
|
|
55
|
-
`green`, `amber`, `red` and `violet` replace the former
|
|
56
|
-
`stone/sage/sky/clay/plum/gold` ramps. Each ships at 100/300/500/700/900,
|
|
57
|
-
stays inside sRGB and uses a consistent OKLCH progression. Blue is the new
|
|
58
|
-
default accent; `ok`, `warn` and `err` now map directly to green, amber and
|
|
59
|
-
red.
|
|
60
|
-
- **The default finish is platform-neutral.** Opaque toolbar and surface
|
|
61
|
-
colors, restrained 8px control geometry, ordinary rounded buttons and generic
|
|
62
|
-
system font fallbacks replace the OS-specific translucent treatment. The
|
|
63
|
-
optional squircle enhancement and decorative backdrop blur are gone.
|
|
64
|
-
- **The default hierarchy is clearer and the page gutter is responsive.**
|
|
65
|
-
`h1` and `h2` now use a restrained fluid type scale, while the new
|
|
66
|
-
`--fertig-g` token grows from 1.15rem on narrow phones to 1.9rem on larger
|
|
67
|
-
screens. Desktop density is unchanged; small screens recover useful space.
|
|
68
|
-
- **The generic toolbar stays composed on phones.** A navigation list gets one
|
|
69
|
-
horizontally scrollable row beneath the identity and trailing control instead
|
|
70
|
-
of wrapping around them in an uneven cluster.
|
|
71
|
-
|
|
72
|
-
### Removed
|
|
73
|
-
|
|
74
|
-
- **The former palette and named accents.** Old ramp tokens and
|
|
75
|
-
`data-accent="indigo|sky|sage|clay|plum|gold|slate"` are not retained as
|
|
76
|
-
aliases. Use `data-accent="blue|cyan|green|amber|red|violet|gray"`.
|
|
77
|
-
- **Legacy mockup pages and static social-preview screenshots.** The site build
|
|
78
|
-
no longer copies them or emits metadata pointing at deleted preview images.
|
|
79
|
-
|
|
80
|
-
### Fixed
|
|
81
|
-
|
|
82
|
-
- **Responsive tables scroll before their cells become unreadable.** Below
|
|
83
|
-
40rem, cell content keeps its intrinsic width inside the existing table scroll
|
|
84
|
-
container instead of wrapping almost word-by-word.
|
|
85
|
-
- **Size synchronization cannot rewrite third-party measurements.** Published
|
|
86
|
-
claims are now an explicit manifest of fertig-specific contexts. A changed or
|
|
87
|
-
missing context fails the command, and a regression test protects unrelated
|
|
88
|
-
values that happen to match fertig's previous size.
|
|
89
|
-
|
|
90
|
-
## [3.1.0] — 2026-09-01
|
|
91
|
-
|
|
92
|
-
### Changed
|
|
93
|
-
|
|
94
|
-
- **The 72rem default is now a page shell, not a prose measure.**
|
|
95
|
-
`.max-w-prose` keeps long-form copy at 38rem, while `.wide` provides an 80rem
|
|
96
|
-
application column. The documentation and customiser now use the same
|
|
97
|
-
defaults and terminology as the stylesheet.
|
|
98
|
-
- **The documentation toolbar stays compact on phones.** Its primary controls
|
|
99
|
-
occupy the first row and its links scroll horizontally on the second instead
|
|
100
|
-
of wrapping into a tall stack. The Components page is now present in the
|
|
101
|
-
shared navigation.
|
|
102
|
-
|
|
103
|
-
### Fixed
|
|
104
|
-
|
|
105
|
-
- **The minified build preserves descendant selectors.** The old punctuation
|
|
106
|
-
regex changed selectors such as `nav :is(…)` into `nav:is(…)`, silently
|
|
107
|
-
breaking row controls and popover menus. The minifier now understands CSS
|
|
108
|
-
strings and comments, with focused regression tests for both failure modes.
|
|
109
|
-
- **Reduced-transparency preferences reach framework wrappers.** A toolbar
|
|
110
|
-
inside `#root`, `#app`, `#__next` or `[data-fertig]` now drops its backdrop
|
|
111
|
-
blur just like a toolbar that is a direct child of `body`.
|
|
112
|
-
|
|
113
|
-
## [3.0.0] — 2026-08-31
|
|
114
|
-
|
|
115
|
-
The breaking change is one mechanical line: **every public token now carries a
|
|
116
|
-
`--fertig-` prefix, and the old names are gone** — no aliases, no shims. The
|
|
117
|
-
classes, the layout utilities and the ARIA attributes the component layer reads
|
|
118
|
-
are all untouched. The sheet does exactly what it did; the migration is a
|
|
119
|
-
rename.
|
|
120
|
-
|
|
121
|
-
`--fertig-a1` / `--fertig-a2` already carried the prefix for the reason the rest
|
|
122
|
-
receive it now: a short, unprefixed custom property is a bet you only lose
|
|
123
|
-
once. `--ac` collided with your own `--ac`; the prefix makes every token yours
|
|
124
|
-
to override, and no future rename is ever needed again.
|
|
125
|
-
|
|
126
|
-
**To migrate:** prefix whatever you override. `--w` → `--fertig-w`,
|
|
127
|
-
`--ac` / `--on-ac` → `--fertig-ac` / `--fertig-on-ac`, the radii
|
|
128
|
-
`--r` / `--rs` / `--rw` → `--fertig-*`, the surfaces (`--bg`, `--el`, `--face`,
|
|
129
|
-
`--fg`, `--mut`, `--bd`, `--tb`, `--nw`), the depth tokens (`--up`, `--up2`,
|
|
130
|
-
`--dn`, `--sh`, `--sh1`, `--sh2`, and the `@property` alphas `--a1` / `--a2`),
|
|
131
|
-
the motion tokens (`--ease`, `--ease-in`, `--ease-out`, `--dur-1`, `--dur-2`),
|
|
132
|
-
`--caps`, and the colour ramps (`--stone-*`, `--sage-*`, `--sky-*`, `--clay-*`,
|
|
133
|
-
`--plum-*`, `--gold-*`). The rule is one line: **any `--name` you set becomes
|
|
134
|
-
`--fertig-name`.** Nothing changed meaning.
|
|
135
|
-
|
|
136
|
-
### Changed
|
|
137
|
-
|
|
138
|
-
- **The palette moves to a cooler voice.** Neutrals are a cool graphite
|
|
139
|
-
(hue ≈ 258) with a faint violet cast, replacing the warm stone; the accent is
|
|
140
|
-
a violet-blue (hue 266), replacing indigo. Measured: the accent clears 6.21:1
|
|
141
|
-
as link text on paper and 6.39:1 for a white label on the fill in light,
|
|
142
|
-
8.62:1 in dark — both sit inside sRGB. The
|
|
143
|
-
`@supports not (color: light-dark(…))` flat-sRGB fallback is restated to match,
|
|
144
|
-
and every pair still clears WCAG AA in both schemes.
|
|
145
|
-
- **Buttons are fully rounded.** The shared button rule takes a new
|
|
146
|
-
`--fertig-rp` (pill) token instead of the control radius. It matches the
|
|
147
|
-
badge, the switch and the progress bar, which were already pills. Set
|
|
148
|
-
`--fertig-rp: var(--fertig-r)` for square-shouldered buttons.
|
|
149
|
-
- **One radius, and the rest derived from it.** `--fertig-r` (12px) is the base;
|
|
150
|
-
`--fertig-rs` is `calc(var(--fertig-r) * .5)` and `--fertig-rw` is
|
|
151
|
-
`calc(var(--fertig-r) * 1.33)`, so setting the base on `:root` rescales the
|
|
152
|
-
whole sheet instead of desynchronising it. Windows — cards, dialogs, popover
|
|
153
|
-
menus, the select picker, `pre`, `details`, `fieldset`, `aside`, toasts —
|
|
154
|
-
now take `--fertig-rw` rather than the control radius, and full-bleed card
|
|
155
|
-
media follows the card it bleeds into.
|
|
156
|
-
- **Badges are uppercase.** They already used the caps *size*; they never got
|
|
157
|
-
the transform that `h5`, `h6` and `th` get.
|
|
158
|
-
- **The dialog lost its banded rules.** No hairline under the header or over
|
|
159
|
-
the footer by default; the separation is spacing. The rule now arrives as
|
|
160
|
-
scroll state — a scroll-driven animation fades it in under the header once the
|
|
161
|
-
body has scrolled and out of the footer at the end — so a dialog that fits
|
|
162
|
-
shows no rules at all. Title takes `--fertig-f`, the interface face, at
|
|
163
|
-
600/1.1rem: a monospaced heading font reads as a terminal on a dialog.
|
|
164
|
-
- **The `err` tone is red, not clay.** `[data-tone=err]` borrowed
|
|
165
|
-
`--fertig-clay-700`, which at 50% lightness reads brown on a destructive
|
|
166
|
-
button. Now `oklch(52% .16 27)` / `oklch(74% .13 25)` — 5.97:1 with the white
|
|
167
|
-
label, and `--fertig-on-ac` still derives correctly in both themes.
|
|
168
|
-
- **The select picker animates open and closed**, with `display` and `overlay`
|
|
169
|
-
transitioned discretely so the close is not a pop.
|
|
170
|
-
|
|
171
|
-
### Fixed
|
|
172
|
-
|
|
173
|
-
- **`accent-color` and `caret-color` ignored every local accent.** Both were
|
|
174
|
-
declared once on `:root`. They are inherited properties, so they resolved
|
|
175
|
-
there against the root accent and every descendant inherited that *computed
|
|
176
|
-
colour* — a `[data-accent]` or `[data-tone]` subtree repainted its buttons and
|
|
177
|
-
links but left its checkboxes, radios, ranges and caret on the root's tint.
|
|
178
|
-
Both are now re-declared on the elements that consume them.
|
|
179
|
-
- **The segmented control showed a vertical scrollbar.** `overflow-x: auto`
|
|
180
|
-
makes `overflow-y` compute to `auto` as well, and Safari paints a scrollbar
|
|
181
|
-
for a sub-pixel of overflow. The block axis is now clipped (`overflow: auto
|
|
182
|
-
clip`), and group children take their focus ring inside the edge
|
|
183
|
-
(`outline-offset: -3px`) so the clip cannot slice it.
|
|
184
|
-
- **The `<select>` marker was a different shape per engine.** Engines without
|
|
185
|
-
`appearance: base-select` fell back to a solid filled triangle while the
|
|
186
|
-
styleable picker drew a thin chevron. The fallback now draws the same
|
|
187
|
-
stroked chevron.
|
|
188
|
-
- **The docs site is built with Eleventy.** The pages moved out of hand-edited
|
|
189
|
-
HTML at the repo root into `src/` templates that build to `dist/`, with the
|
|
190
|
-
version flowing from `package.json` as the single source of truth. This is how
|
|
191
|
-
the sheet's own site is maintained; it is not part of the npm package, which
|
|
192
|
-
ships the two CSS files plus the README and licence.
|
|
193
|
-
- **The demo template pages are gone.** `app.html`, `app-invoice.html` and the
|
|
194
|
-
whole `templates/` set (`dashboard`, `article`, `pricing`, `signin`) are
|
|
195
|
-
removed from the site and repo; the docs no longer point at them.
|
|
196
|
-
|
|
197
|
-
## [2.0.0] — 2026-08-31
|
|
198
|
-
|
|
199
|
-
### Breaking
|
|
200
|
-
|
|
201
|
-
- **`--a1` / `--a2` are now `--fertig-a1` / `--fertig-a2`, with no alias.**
|
|
202
|
-
These are `@property` registrations, and a registration is global — it cannot
|
|
203
|
-
be layered, scoped or overridden. A two-character name meant a consumer's own
|
|
204
|
-
`--a1` was silently retyped to `<number>`, which is a bug that only a rename
|
|
205
|
-
can fix.
|
|
206
|
-
|
|
207
|
-
**To migrate:** if you set `--a1` or `--a2`, rename them. Nothing else
|
|
208
|
-
changes — the values mean the same thing and the elevation scale is
|
|
209
|
-
untouched. If you never set them, there is nothing to do.
|
|
210
|
-
|
|
211
|
-
Every other token name is unchanged. They are ordinary custom properties,
|
|
212
|
-
they are the documented API, and they are deliberately short.
|
|
213
|
-
|
|
214
|
-
A visual refresh, an audit pass, and a component-first repositioning. One token
|
|
215
|
-
rename aside, the surface is the same — the same classes and attributes — but
|
|
216
|
-
the default look changes visibly, so treat this as a redesign rather than a
|
|
217
|
-
drop-in bump.
|
|
218
|
-
|
|
219
|
-
### Added
|
|
220
|
-
|
|
221
|
-
- **Named accents.** `data-accent="indigo|sky|sage|clay|plum|gold|slate"` on any
|
|
222
|
-
element retints everything inside it: links, focus rings, filled buttons, the
|
|
223
|
-
caret, the selection. Scoped rather than global, so one section can differ
|
|
224
|
-
from the rest of a page. Each pair is measured — the light tone clears AA as
|
|
225
|
-
link text on paper, the dark tone clears it on the dark ground.
|
|
226
|
-
- **Motion tokens.** `--ease-out`, `--ease-in`, `--ease` and the durations
|
|
227
|
-
`--dur-1` / `--dur-2`. The sheet had been animating with a bare `ease`, which
|
|
228
|
-
is the browser default and the flattest curve available.
|
|
229
|
-
- `--rs`, a small radius for inline chips and code, so they do not inherit the
|
|
230
|
-
larger control radius and read as lozenges.
|
|
231
|
-
|
|
232
|
-
### Changed
|
|
233
|
-
|
|
234
|
-
- **The default accent is indigo**, not the desaturated navy it was. Measured
|
|
235
|
-
6.28:1 as link text on paper and 6.39:1 for a white label on the fill in
|
|
236
|
-
light; 8.72:1 and 10.26:1 in dark. Both sit inside sRGB.
|
|
237
|
-
- **Cards no longer paint a tinted strip behind their header and footer.** A
|
|
238
|
-
filled bar across the top of a card is the old panel-heading pattern and is
|
|
239
|
-
what dated the sheet on sight; a hairline separates just as well and lets the
|
|
240
|
-
card read as one surface.
|
|
241
|
-
- Radii up: `--r` 6px → 9px, `--rw` 10px → 14px. Controls have more room —
|
|
242
|
-
buttons and fields gained roughly a tenth of an em of padding.
|
|
243
|
-
- More things transition, on the named curves: tabs, badges, cards, segmented
|
|
244
|
-
controls and popover items, alongside the controls that already did.
|
|
245
|
-
`:focus-visible` is explicitly excluded — a focus ring has to be there the
|
|
246
|
-
instant focus lands, not fade in after it.
|
|
247
|
-
|
|
248
|
-
### Fixed
|
|
249
|
-
|
|
250
|
-
- The tone bar on `.card[data-tone]` follows the corner radius again. It was an
|
|
251
|
-
inset shadow, which does not track the curve cleanly at the larger radius —
|
|
252
|
-
it read as a detached line with gaps at both top corners. It is a background
|
|
253
|
-
layer now, which the radius clips. The duplicate indicator on
|
|
254
|
-
`.card > header` is gone with it: the filled header used to hide it, and
|
|
255
|
-
without the fill both were painting.
|
|
256
|
-
- Navigation lists. `[data-layout=sidebar]` shipped without any styling for the
|
|
257
|
-
nav inside it, so the obvious markup — a `<menu>` in a `<nav>` — came out as
|
|
258
|
-
a boxed list group. It is navigation now: no rules between items, no bullets,
|
|
259
|
-
and the link fills the row.
|
|
260
|
-
- `aside` and `search` are block landmarks that had no vertical rhythm of their
|
|
261
|
-
own, so whatever followed sat flush against them.
|
|
262
|
-
|
|
263
|
-
### Fixed — audit pass
|
|
264
|
-
|
|
265
|
-
An audit pass. Everything here came out of `docs/known-flaws.md`, which lists
|
|
266
|
-
what was found, what was verified in a browser, and what was left alone on
|
|
267
|
-
purpose.
|
|
268
|
-
|
|
269
|
-
- **The shell survives a framework wrapper.** The page shell was `body > *`, so
|
|
270
|
-
a React, Vue, Svelte or Next app rendering into `<div id="root">` lost the
|
|
271
|
-
measure, the paper surface and the gutters with nothing on screen to say why.
|
|
272
|
-
The shell now also matches the children of a single `#root`, `#app`,
|
|
273
|
-
`#__next` or `[data-fertig]` wrapper. Every added selector sits inside
|
|
274
|
-
`:where()`, so specificity is unchanged.
|
|
275
|
-
- **A floor under the floor.** Every colour token was an unguarded
|
|
276
|
-
`light-dark()`. In an engine without it the tokens were invalid at
|
|
277
|
-
computed-value time, so backgrounds went transparent and colour was
|
|
278
|
-
inherited — a page could land unreadable rather than plain. A
|
|
279
|
-
`@supports not (color: light-dark(…))` block at the end of the layer restates
|
|
280
|
-
the palette in flat sRGB, in both schemes.
|
|
281
|
-
- **`data-size`, `data-variant` and `data-block` are scoped to controls.** As
|
|
282
|
-
bare attribute selectors they restyled any element carrying those very common
|
|
283
|
-
attribute names — a `<span data-size="sm">` picked up button padding.
|
|
284
|
-
- **The focus ring no longer reshapes what it rings.** `:focus-visible` set
|
|
285
|
-
`border-radius: var(--r)`, which is the element's own radius, not the ring's:
|
|
286
|
-
a focused `<dialog>` snapped from `--rw` (14px) to `--r` (9px). Outlines
|
|
287
|
-
already follow the element's corners, so the declaration is simply gone.
|
|
288
|
-
- **`<svg>` stays inline.** It was in the `display: block` rule with `img`,
|
|
289
|
-
`video` and `iframe`, which dropped every inline icon onto its own line.
|
|
290
|
-
- **Toasts can stack.** Two `[popover][data-toast]` elements shared one set of
|
|
291
|
-
corner coordinates and overlapped, and an open popover is in the top layer so
|
|
292
|
-
no ordinary wrapper could stack them. `<div popover="manual"
|
|
293
|
-
data-toast-region>` is now the popover, with a `<div data-toast>` per message.
|
|
294
|
-
- **A selected tab is visible in Windows High Contrast.** Its cue was a
|
|
295
|
-
`box-shadow` that the forced-colors layer removes, and the replacement set
|
|
296
|
-
`border-color` on an element with `border: 0`. It now sets a real
|
|
297
|
-
`border-bottom`.
|
|
298
|
-
- **`--on-ac` survives a custom `--ac` in shipping browsers.** The
|
|
299
|
-
`contrast-color()` guard is real but almost nothing implements it. A relative
|
|
300
|
-
colour branch reaches the same black-or-white decision from the accent's own
|
|
301
|
-
lightness, and has been cross-engine since 2024.
|
|
302
|
-
- **`interpolate-size: allow-keywords` is set on `details`, not `:root`.** It is
|
|
303
|
-
inherited, so the old placement changed how *your* `height: auto` transitions
|
|
304
|
-
behaved as a side effect of animating a disclosure.
|
|
305
|
-
- **Two universal rules narrowed to what the sheet actually styles.**
|
|
306
|
-
`scrollbar-width: thin` no longer thins the page's own scrollbar (a
|
|
307
|
-
target-size problem for imprecise pointers), and `corner-shape: squircle` no
|
|
308
|
-
longer reshapes your components.
|
|
309
|
-
- **`input[type=image]` is a button, not a text field.** It was missing from the
|
|
310
|
-
`:not()` list and got full-width sunken-field treatment.
|
|
311
|
-
- **The tooltip is flow-relative and reachable on touch** — logical inset
|
|
312
|
-
properties with a `:dir(rtl)` offset, and `:active` alongside `:hover`. It is
|
|
313
|
-
still decorative, and now says so in the sheet, the README and the docs.
|
|
314
|
-
- **`a[target=_blank]`** no longer appends an arrow to a link wrapping an image.
|
|
315
|
-
- **Print keeps the footer.** It was hidden along with the toolbar, which drops
|
|
316
|
-
the legal line, the contact and the citations from every printout.
|
|
317
|
-
- **The small variant stays small on touch.** `(pointer: coarse)` forced
|
|
318
|
-
`min-height: 44px` on everything; `data-size="sm"` opts down to 32px, still
|
|
319
|
-
above the 24px WCAG 2.5.8 floor.
|
|
320
|
-
- `package.json`'s size claim, the one string `tools/sizes.py` does not reach.
|
|
321
|
-
|
|
322
|
-
### Changed
|
|
323
|
-
|
|
324
|
-
- `--a1` / `--a2` renamed — see **Breaking** above.
|
|
325
|
-
|
|
326
|
-
## [1.0.3] — 2026-08-30
|
|
327
|
-
|
|
328
|
-
### Changed
|
|
329
|
-
|
|
330
|
-
- `--mut` lifted from 50%/70% lightness to 47%/73%. The weakest muted pairing
|
|
331
|
-
— on the desktop ground in light, on chrome in dark — was 4.96:1 and 5.99:1,
|
|
332
|
-
a hair over AA; it is 5.65:1 and 6.70:1 now. Not taken to AAA, which would need 41.5%: that
|
|
333
|
-
is close enough to `--fg` that muted text stops reading as secondary at all.
|
|
334
|
-
|
|
335
|
-
### Added
|
|
336
|
-
|
|
337
|
-
- `--nw`, the column the toolbar's contents line up with. It follows `--w`, so
|
|
338
|
-
nothing changes by default, and `<nav class="wide">` re-points it at the wide
|
|
339
|
-
column — an app screen built on `.wide` no longer gets a wordmark floating in
|
|
340
|
-
the middle of the viewport while its content spans the full width.
|
|
341
|
-
|
|
342
|
-
### Fixed
|
|
343
|
-
|
|
344
|
-
- Breadcrumb separators no longer leak into other navigation. The `/` was on
|
|
345
|
-
`nav[aria-label] li + li`, so any labelled `<nav>` containing a `<ul>` — an
|
|
346
|
-
ordinary sidebar — got breadcrumb slashes between its links. Scoped to `ol`,
|
|
347
|
-
matching the layout rule directly above it and the documented markup.
|
|
348
|
-
- A `.grid` no longer collides with the block that follows it. It is a
|
|
349
|
-
block-level container and nothing gave it vertical rhythm. The space is on
|
|
350
|
-
`.grid + *` rather than a margin on `.grid` itself, which would collapse out
|
|
351
|
-
through the top of a padding-less container and open a seam above it.
|
|
352
|
-
- A segmented control (`role="group"`) with four or more buttons no longer
|
|
353
|
-
pushes the page sideways on a narrow screen. It scrolls within its own width
|
|
354
|
-
instead of wrapping, which would break the joined run of corner radii.
|
|
355
|
-
- A `<dl>` with a long value no longer widens the page. The value column was
|
|
356
|
-
a bare `1fr`, whose automatic minimum is its content, so it could not shrink;
|
|
357
|
-
it is `minmax(0, 1fr)` now.
|
|
358
|
-
|
|
359
|
-
## [1.0.2] — 2026-08-30
|
|
360
|
-
|
|
361
|
-
### Fixed
|
|
362
|
-
|
|
363
|
-
- Menus and toasts no longer jump across the viewport as they close. The anchor
|
|
364
|
-
positioning was scoped to `[popover]:popover-open`, but the close is
|
|
365
|
-
transitioned (`display .13s allow-discrete`), so for those 130ms the popover
|
|
366
|
-
still painted while no longer matching the selector — falling back to the UA's
|
|
367
|
-
centred `inset: 0` and visibly flying to the middle of the screen. Both the
|
|
368
|
-
menu and the `[data-toast]` corner override now sit on the base selector.
|
|
369
|
-
|
|
370
|
-
## [1.0.1] — 2026-08-30
|
|
371
|
-
|
|
372
|
-
Packaging only; the stylesheet is unchanged apart from its version banner.
|
|
373
|
-
|
|
374
|
-
### Changed
|
|
375
|
-
|
|
376
|
-
- `homepage` points at the documentation site rather than the README, and the
|
|
377
|
-
repository URLs follow the repo's rename to `moji2002/fertig`.
|
|
378
|
-
- `fertig` and `fertig.css` added as keywords: the package is `fertig`, but
|
|
379
|
-
people search npm for the project's name.
|
|
380
|
-
|
|
381
|
-
## [1.0.1] - 2026-08-30
|
|
382
|
-
|
|
383
|
-
### Changed
|
|
384
|
-
|
|
385
|
-
- npm keywords only: added `css-framework`, `lightweight`, `minimalist`, `html`,
|
|
386
|
-
`frontend`, `ui` and `responsive`. `css-framework` is the term the rest of the
|
|
387
|
-
category (Pico, Water.css) registers under, and it was missing. No stylesheet
|
|
388
|
-
changes — the CSS is byte-identical to 1.0.0.
|
|
389
|
-
|
|
390
|
-
## [1.0.0] — 2026-08-30
|
|
391
|
-
|
|
392
|
-
First release. The project and the npm package are `fertig`. The stylesheet
|
|
393
|
-
file keeps the name `fertig.css`, because it is a CSS file, and the cascade
|
|
394
|
-
layer is `@layer fertig` — a dot in a layer name would declare a sub-layer.
|
|
395
|
-
|
|
396
|
-
### Added
|
|
397
|
-
|
|
398
|
-
- Classless styling for the full semantic element set: headings, prose, lists,
|
|
399
|
-
description lists, quotes, rules, code, tables, every form control,
|
|
400
|
-
fieldsets, buttons, details, dialog, figures, media and asides.
|
|
401
|
-
- Layout model where direct children of `<body>` are containers — `<nav>` is a
|
|
402
|
-
full-bleed toolbar with a vibrancy blur, and
|
|
403
|
-
`header`/`main`/`footer` are the page.
|
|
404
|
-
- Light and dark themes from a single `light-dark()` token block, with
|
|
405
|
-
`data-theme="light|dark"` to override the OS preference.
|
|
406
|
-
- Elevation scale (`--up`, `--up2`, `--dn`) whose shadow alphas step up in dark
|
|
407
|
-
mode, since a shadow on a dark ground reads as nothing on its own. The
|
|
408
|
-
shadows come off a real colour token (`--sh`) through relative colour syntax,
|
|
409
|
-
not an HSL triplet you could not use directly.
|
|
410
|
-
- Component layer addressed by ARIA rather than by class: segmented controls
|
|
411
|
-
(`role="group"`), tabs (`role="tablist"`), switches (`role="switch"`),
|
|
412
|
-
`[popover]` menus anchored to their invoker, breadcrumbs, `<dialog>` with an
|
|
413
|
-
entrance transition, `aria-busy` spinners and `data-tooltip`.
|
|
414
|
-
- Button variants (`data-variant`, `data-size`, `data-icon`, `data-block`) and
|
|
415
|
-
card anatomy (`<header>`/`<footer>`, full-bleed media, `data-tone`,
|
|
416
|
-
`<a class="card">` hover lift).
|
|
417
|
-
- Seven optional classes: `.row`, `.grid`, `.card`, `.badge`, `.muted`,
|
|
418
|
-
`.center`, `.wide`.
|
|
419
|
-
- Dialog anatomy: an optional `<header>` and `<footer>` that run edge to edge
|
|
420
|
-
and stay pinned while the body scrolls. Sticky rather than a grid, because a
|
|
421
|
-
classless sheet has no wrapper around the loose middle children to make a
|
|
422
|
-
grid row out of; the sticky offsets are negative so the chrome pins to the
|
|
423
|
-
dialog's border edge rather than its padding edge, which is where content
|
|
424
|
-
would otherwise scroll through.
|
|
425
|
-
- A max-width scale on Tailwind's names — `.max-w-xs` through `.max-w-7xl`,
|
|
426
|
-
plus `.max-w-full`, `.max-w-none` and `.max-w-prose`. Whole rather than
|
|
427
|
-
partial: a scale where `.max-w-2xl` works and `.max-w-3xl` silently does not
|
|
428
|
-
is worse than no scale. They are `max-inline-size`, so they still mean
|
|
429
|
-
"along the text" in a vertical writing mode.
|
|
430
|
-
- Layout utilities, named after Tailwind's so the names transfer: `.flex`,
|
|
431
|
-
`.flex-col`, `.flex-wrap`, `.flex-1`, `.grid-cols-2|3|4`,
|
|
432
|
-
`.items-start|center|end`, `.justify-start|center|end|between`,
|
|
433
|
-
`.gap-0|1|2|3|4|6`, `.mx-auto`, `.ms-auto`, `.me-auto`, `.w-full`,
|
|
434
|
-
`.hidden`. Layout only — no colour, type or sizing scale, and no responsive
|
|
435
|
-
variants, which would need a build step.
|
|
436
|
-
- Right-to-left support. Every inline-direction rule is flow-relative, with
|
|
437
|
-
`:dir(rtl)` rules for the two that cannot be — the switch knob's `translate`
|
|
438
|
-
and the fallback `<select>` chevron's background position. Verified by
|
|
439
|
-
rendering a Persian page in both directions.
|
|
440
|
-
- A second layer, `fertig-a11y`, declared after `fertig`. The forced-colors
|
|
441
|
-
block lives there and wins on layer order.
|
|
442
|
-
- Print styles, `prefers-reduced-motion` handling, and thin scrollbars.
|
|
443
|
-
- Robustness: `overflow-wrap: break-word`; `:required`, `:read-only` and
|
|
444
|
-
`:autofill` states; slashed, tabular numerals; `object-fit` on card media;
|
|
445
|
-
smooth in-page scrolling; `overscroll-behavior` on overlays; `@page` margins
|
|
446
|
-
with orphan and widow control.
|
|
447
|
-
- Environment queries: `inverted-colors` and `color-gamut: p3`.
|
|
448
|
-
- `anchor-size()` and `position-visibility` for menus, `::spelling-error`,
|
|
449
|
-
and Safari's native `<input switch>` styled to match `role="switch"`.
|
|
450
|
-
|
|
451
|
-
### Browser support
|
|
452
|
-
|
|
453
|
-
- Two-year support policy: the sheet targets browsers from the last two years.
|
|
454
|
-
The only thing carried for the ones before them is the flat-sRGB palette
|
|
455
|
-
above ("a floor under the floor"). It ships no vendor prefixes except the
|
|
456
|
-
three no engine has replaced (`-webkit-text-size-adjust`, the autofill
|
|
457
|
-
repaint, and the `progress` pseudo-elements).
|
|
458
|
-
- The sheet is wrapped in `@layer fertig`, so unlayered author CSS overrides it
|
|
459
|
-
at any specificity. There is no `!important` anywhere in it: inside a cascade
|
|
460
|
-
layer an important declaration outranks your own unlayered CSS, which would
|
|
461
|
-
contradict the point of shipping in a layer.
|
|
462
|
-
|
|
463
|
-
### Site
|
|
464
|
-
|
|
465
|
-
- A blocks gallery with 16 ready-to-use patterns — toolbars, stat rows, tables
|
|
466
|
-
with totals, pagination, empty states, sign-in, settings, alerts, confirm
|
|
467
|
-
dialogs, tabs, menus, pricing and shortcuts. Each snippet is generated from
|
|
468
|
-
its own live preview at runtime, so the code and the demo cannot drift apart.
|
|
469
|
-
- `llms.txt` describing the layout model, the seven classes, the ARIA
|
|
470
|
-
component conventions and the tokens.
|
|
471
|
-
|
|
472
|
-
### Verified
|
|
473
|
-
|
|
474
|
-
- All foreground/background pairs meet WCAG 2.1 AA (≥ 4.5:1) in both themes,
|
|
475
|
-
at rest and on hover; the tightest is muted text on chrome at 4.65:1.
|
|
476
|
-
- Progressive enhancement behind `@supports`: `contrast-color()`,
|
|
477
|
-
`::details-content` with `interpolate-size`, `field-sizing`,
|
|
478
|
-
`corner-shape: squircle`, `text-box: trim-both` and `@property`-typed
|
|
479
|
-
shadow alphas. None of them are required for the sheet to work.
|
|
480
|
-
- Tables scroll themselves below 40rem instead of widening the page.
|
|
481
|
-
- 28.0 KB raw, 7.6 KB gzipped, 6.7 KB brotli (`fertig.min.css`).
|