Update @nldd/design-system to 0.8.77 and adapt to it #219

Merged
robbertbos merged 1 commit from deps/nldd-0877 into main 2026-08-05 12:33:55 +00:00
Owner

Takes @nldd/design-system to ^0.8.77, with the two code changes that upgrade needs. Replaces #212, which held the bare bump. Rebased on current main (which now carries the bundled dependency round from #218).

A full risk sweep ran across six axes (tokens, component APIs, shadow DOM, upstream changelog, runtime/a11y, packaging) covering all seven releases; every candidate finding was then adversarially verified by an independent pass. 35 candidates, 10 confirmed, 25 refuted.

Why the bare bump could not be merged

0.8.75 removed the four --primitives-font-family-*-fallback tokens. frontend/src/styles/tokens.css:46 pointed the family chain at them deliberately, because we may not use RijksSans (the licensing note is in that file). The var() reference goes invalid at computed-value time, which takes out --primitives-font-family-sans-serif, -body and -display, and with them the font shorthand on body.

Measured in Chromium on the built bundle:

0.8.70 0.8.77 unpatched 0.8.77 + this PR
font-family system-ui, sans-serif Times system-ui, sans-serif
font-size 18px 16px 18px
line-height 27px normal 27px

Custom properties inherit into shadow roots, so this is not only the document font: 39 NLDD component stylesheets lose their whole font shorthand including weight. Measured on the components' own rules, nldd-tag goes 16px/18px/475 to 16px/normal/400. The --primitives-font-size-* primitives survive, so the unpatched result is an incoherent mix rather than a uniformly smaller page.

The two changes

1. frontend/src/styles/tokens.css - an explicit system-ui, sans-serif stack, replacing the two -fallback references. The serif line is deleted outright: --primitives-font-family-serif-fallback disappeared back in 0.8.71 and 0.8.77 ships no consumer of --primitives-font-family-serif at all.

Deleting the override instead was measured and rejected. It restores 18px/27px, but the computed stack then begins with RijksSans, which only falls through because fontTuningPlugin strips the font. That plugin declares a generateBundle hook, which never runs under vite dev - so developers would work in the restricted font while production shows system-ui, and a machine with RijksSans installed locally would render it in production too. Switching main.ts to @nldd/design-system/styles/system-font was also rejected: that stylesheet carries four faces, and the two JetBrains Mono ones would go with it, which tokens.css:45 explicitly keeps.

The explicit stack keeps dev and production identical and leaves fontTuningPlugin as a second layer against redistribution rather than the only one.

2. frontend/src/components/RetentionIntroBanner.vue - removes the compensating host-padding rule. It existed because reset.css's * { padding: 0 } stripped the banner's :host padding. 0.8.75 moved that frame into a shadow wrapper, so the rule stopped compensating and started stacking: +24px height, and the tinted frame inset 12px from the card column below it. With the rule gone, the 0.8.77 rendering is pixel-identical to 0.8.70.

Both changes have to be in the same commit as the bump. On 0.8.70 without change 2 the banner text sits against its edge, so splitting them leaves a visibly broken commit.

Visual changes that come with this, no code involved

These are the design system returning spacing that Waggle's own reset removes. No action needed, but they are visible.

  • Seven error banners in Instellingen gain interior padding (host 32px to 56px). Today the icon is clamped into the rounded corner of the red panel.
  • Menu dividers regain their rhythm (1px to 9px); the TopNav menu grows ~24px.
  • Cards lose their resting drop shadow (--components-card-box-shadow default went level-1 to none in 0.8.71) and the always-present 1px ::after border becomes visibly grey. Hover, focus-visible and drag overrides are unchanged, measured identical to 0.8.70.
  • Cards on Welkom and Voorwaarden go from 0px to 10px corner radius; the two files that override the radius (CardShell.vue, Settings.vue) stay at 8px.
  • --semantics-dividers-color is one palette step lighter in light mode across 51 read sites (#D9DEE5 to #E2E6EC, dEOK 0.025). Dark mode is unchanged.

The card shadow and the corner radius are worth a deliberate decision rather than inheriting them by accident; they do not block this PR.

What no gate catches

Every one of these passes typecheck, eslint, vitest, the build and the Playwright e2e suite. There is no toHaveScreenshot or toMatchSnapshot anywhere in the repo, vitest runs on happy-dom where the Lit components never boot, and no e2e test asserts on computed style or geometry. The app could ship rendering in Times with a fully green pipeline.

The cheapest durable net is a static token guard: a vitest test that resolves every var(--primitives-*/--semantics-*/--components-*) used in frontend/src/** against the installed design system's CSS and fails on a missing name. No browser, no flake. It would have caught this, it catches the --components-banner-padding rename in 0.8.78, and it catches the already-dead reference to --semantics-buttons-primary-tinted-background-color in emojiSuggest.module.css:40. Not included here to keep this PR to the upgrade itself.

A note on the range

^0.8.70 already resolves to >=0.8.70 <0.9.0-0, so it always admitted 0.8.75 and 0.8.77 - only the lockfile held Waggle on 0.8.70. The font-chain break was therefore reachable by any lockfile re-resolve, independent of this PR. 0.8.78 is already latest on npm and renames --components-banner-padding to --components-banner-md-padding; Waggle's only consumer of that name is the rule change 2 deletes, so a future re-resolve is clean.

Verification

  • npm ci on 0.8.77, vue-tsc typecheck, eslint (0 errors), vitest 570 passed in 77 files, vite build, Playwright e2e 63 passed / 3 skipped, pre-commit run --all-files.
  • Computed style measured on the built bundle: system-ui, sans-serif / 18px / 27px, matching the 0.8.70 baseline on all three axes.
  • Font faces in the built document: two, both JetBrains Mono. No RijksSans @font-face, and dist/assets contains no RijksSans woff2.
Takes `@nldd/design-system` to `^0.8.77`, with the two code changes that upgrade needs. Replaces #212, which held the bare bump. Rebased on current `main` (which now carries the bundled dependency round from #218). A full risk sweep ran across six axes (tokens, component APIs, shadow DOM, upstream changelog, runtime/a11y, packaging) covering all seven releases; every candidate finding was then adversarially verified by an independent pass. 35 candidates, 10 confirmed, 25 refuted. ## Why the bare bump could not be merged **0.8.75 removed the four `--primitives-font-family-*-fallback` tokens.** `frontend/src/styles/tokens.css:46` pointed the family chain at them deliberately, because we may not use RijksSans (the licensing note is in that file). The `var()` reference goes invalid at computed-value time, which takes out `--primitives-font-family-sans-serif`, `-body` and `-display`, and with them the `font` shorthand on `body`. Measured in Chromium on the built bundle: | | 0.8.70 | 0.8.77 unpatched | 0.8.77 + this PR | |---|---|---|---| | `font-family` | `system-ui, sans-serif` | `Times` | `system-ui, sans-serif` | | `font-size` | 18px | 16px | 18px | | `line-height` | 27px | normal | 27px | Custom properties inherit into shadow roots, so this is not only the document font: 39 NLDD component stylesheets lose their whole `font` shorthand including weight. Measured on the components' own rules, `nldd-tag` goes 16px/18px/475 to 16px/normal/400. The `--primitives-font-size-*` primitives survive, so the unpatched result is an incoherent mix rather than a uniformly smaller page. ## The two changes **1. `frontend/src/styles/tokens.css`** - an explicit `system-ui, sans-serif` stack, replacing the two `-fallback` references. The serif line is deleted outright: `--primitives-font-family-serif-fallback` disappeared back in 0.8.71 and 0.8.77 ships no consumer of `--primitives-font-family-serif` at all. Deleting the override instead was measured and rejected. It restores 18px/27px, but the computed stack then begins with `RijksSans`, which only falls through because `fontTuningPlugin` strips the font. That plugin declares a `generateBundle` hook, which never runs under `vite dev` - so developers would work in the restricted font while production shows system-ui, and a machine with RijksSans installed locally would render it in production too. Switching `main.ts` to `@nldd/design-system/styles/system-font` was also rejected: that stylesheet carries four faces, and the two JetBrains Mono ones would go with it, which `tokens.css:45` explicitly keeps. The explicit stack keeps dev and production identical and leaves `fontTuningPlugin` as a second layer against redistribution rather than the only one. **2. `frontend/src/components/RetentionIntroBanner.vue`** - removes the compensating host-padding rule. It existed because `reset.css`'s `* { padding: 0 }` stripped the banner's `:host` padding. 0.8.75 moved that frame into a shadow wrapper, so the rule stopped compensating and started stacking: +24px height, and the tinted frame inset 12px from the card column below it. With the rule gone, the 0.8.77 rendering is pixel-identical to 0.8.70. Both changes have to be in the same commit as the bump. On 0.8.70 without change 2 the banner text sits against its edge, so splitting them leaves a visibly broken commit. ## Visual changes that come with this, no code involved These are the design system returning spacing that Waggle's own reset removes. No action needed, but they are visible. - Seven error banners in Instellingen gain interior padding (host 32px to 56px). Today the icon is clamped into the rounded corner of the red panel. - Menu dividers regain their rhythm (1px to 9px); the TopNav menu grows ~24px. - Cards lose their resting drop shadow (`--components-card-box-shadow` default went level-1 to `none` in 0.8.71) and the always-present 1px `::after` border becomes visibly grey. Hover, focus-visible and drag overrides are unchanged, measured identical to 0.8.70. - Cards on Welkom and Voorwaarden go from 0px to 10px corner radius; the two files that override the radius (`CardShell.vue`, `Settings.vue`) stay at 8px. - `--semantics-dividers-color` is one palette step lighter in light mode across 51 read sites (`#D9DEE5` to `#E2E6EC`, dEOK 0.025). Dark mode is unchanged. The card shadow and the corner radius are worth a deliberate decision rather than inheriting them by accident; they do not block this PR. ## What no gate catches Every one of these passes typecheck, eslint, vitest, the build and the Playwright e2e suite. There is no `toHaveScreenshot` or `toMatchSnapshot` anywhere in the repo, vitest runs on happy-dom where the Lit components never boot, and no e2e test asserts on computed style or geometry. The app could ship rendering in Times with a fully green pipeline. The cheapest durable net is a static token guard: a vitest test that resolves every `var(--primitives-*/--semantics-*/--components-*)` used in `frontend/src/**` against the installed design system's CSS and fails on a missing name. No browser, no flake. It would have caught this, it catches the `--components-banner-padding` rename in 0.8.78, and it catches the already-dead reference to `--semantics-buttons-primary-tinted-background-color` in `emojiSuggest.module.css:40`. Not included here to keep this PR to the upgrade itself. ## A note on the range `^0.8.70` already resolves to `>=0.8.70 <0.9.0-0`, so it always admitted 0.8.75 and 0.8.77 - only the lockfile held Waggle on 0.8.70. The font-chain break was therefore reachable by any lockfile re-resolve, independent of this PR. 0.8.78 is already `latest` on npm and renames `--components-banner-padding` to `--components-banner-md-padding`; Waggle's only consumer of that name is the rule change 2 deletes, so a future re-resolve is clean. ## Verification - `npm ci` on 0.8.77, `vue-tsc` typecheck, eslint (0 errors), vitest 570 passed in 77 files, `vite build`, Playwright e2e 63 passed / 3 skipped, `pre-commit run --all-files`. - Computed style measured on the built bundle: `system-ui, sans-serif` / 18px / 27px, matching the 0.8.70 baseline on all three axes. - Font faces in the built document: two, both JetBrains Mono. No RijksSans `@font-face`, and `dist/assets` contains no RijksSans woff2.
robbertbos force-pushed deps/nldd-0877 from 5d62f1d268
Some checks failed
CI / release-scripts (pull_request) Successful in 7s
security-scan / SBOM (trivy) (pull_request) Successful in 9s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 14s
security-scan / JS SCA (npm audit) (pull_request) Successful in 18s
security-scan / Python SAST (bandit) (pull_request) Successful in 21s
CI / pre-commit (pull_request) Successful in 30s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 40s
test-build / build (backend) (pull_request) Successful in 59s
CI / backend-test (pull_request) Successful in 55s
test-build / build (frontend) (pull_request) Successful in 1m3s
test-build / build (pull_request) Successful in 0s
CI / frontend-test (pull_request) Successful in 1m11s
CI / backend-test-postgres (pull_request) Has been cancelled
CI / e2e (pull_request) Has been cancelled
to 50c2990ddc
Some checks failed
CI / release-scripts (pull_request) Successful in 9s
security-scan / SBOM (trivy) (pull_request) Successful in 14s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 19s
security-scan / JS SCA (npm audit) (pull_request) Successful in 22s
security-scan / Python SAST (bandit) (pull_request) Successful in 27s
CI / pre-commit (pull_request) Successful in 31s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 45s
CI / backend-test (pull_request) Successful in 55s
test-build / build (backend) (pull_request) Successful in 1m4s
test-build / build (pull_request) Has been cancelled
test-build / build (frontend) (pull_request) Has been cancelled
CI / backend-test-postgres (pull_request) Has been cancelled
CI / frontend-test (pull_request) Has been cancelled
CI / e2e (pull_request) Has been cancelled
2026-08-05 12:19:16 +00:00
Compare
robbertbos force-pushed deps/nldd-0877 from 50c2990ddc
Some checks failed
CI / release-scripts (pull_request) Successful in 9s
security-scan / SBOM (trivy) (pull_request) Successful in 14s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 19s
security-scan / JS SCA (npm audit) (pull_request) Successful in 22s
security-scan / Python SAST (bandit) (pull_request) Successful in 27s
CI / pre-commit (pull_request) Successful in 31s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 45s
CI / backend-test (pull_request) Successful in 55s
test-build / build (backend) (pull_request) Successful in 1m4s
test-build / build (pull_request) Has been cancelled
test-build / build (frontend) (pull_request) Has been cancelled
CI / backend-test-postgres (pull_request) Has been cancelled
CI / frontend-test (pull_request) Has been cancelled
CI / e2e (pull_request) Has been cancelled
to 407a85968b
All checks were successful
CI / release-scripts (pull_request) Successful in 6s
security-scan / SBOM (trivy) (pull_request) Successful in 11s
security-scan / JS SCA (npm audit) (pull_request) Successful in 20s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 13s
security-scan / Python SAST (bandit) (pull_request) Successful in 22s
CI / pre-commit (pull_request) Successful in 29s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 44s
CI / backend-test (pull_request) Successful in 55s
test-build / build (backend) (pull_request) Successful in 1m2s
test-build / build (frontend) (pull_request) Successful in 1m6s
test-build / build (pull_request) Successful in 0s
CI / frontend-test (pull_request) Successful in 1m12s
CI / e2e (pull_request) Successful in 3m41s
CI / backend-test-postgres (pull_request) Successful in 4m37s
CI / release-scripts (push) Successful in 6s
security-scan / SBOM (trivy) (push) Successful in 11s
security-scan / Filesystem scan (trivy fs) (push) Successful in 14s
security-scan / JS SCA (npm audit) (push) Successful in 19s
security-scan / Python SAST (bandit) (push) Successful in 20s
CI / pre-commit (push) Successful in 30s
security-scan / Python SCA (pip-audit) (push) Successful in 40s
CI / backend-test (push) Successful in 54s
publish-main / build (backend) (push) Successful in 1m5s
publish-main / build (frontend) (push) Successful in 1m10s
publish-main / build (push) Successful in 0s
CI / frontend-test (push) Successful in 1m11s
CI / e2e (push) Successful in 3m35s
CI / backend-test-postgres (push) Successful in 4m26s
2026-08-05 12:20:24 +00:00
Compare
robbertbos deleted branch deps/nldd-0877 2026-08-05 12:33:55 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
robbertbos/waggle!219
No description provided.