Give the search box its focus ring back, and stop the empty state floating #206

Merged
robbertbos merged 1 commit from search-focus-and-empty-state into main 2026-07-26 20:17:30 +00:00
Owner

Two regressions from the NLDD work, both reported from the running app.

The search box had a halo but no ring

SearchRow shows focus on the .field wrapper and deliberately sets outline: none on the inner input. That beats the global :focus-visible rule on source order at equal specificity - but only for the outline. Its box-shadow survived, and --semantics-focus-ring-box-shadow is a 6px halo in the page background colour.

So the focused search box drew background onto background with no ring: the same failure #198 fixed globally, reintroduced locally by a legitimate override.

The ring now sits on .field, which is what a user perceives as the search box, and the input clears both halves of the global rule.

Eight other places suppress the outline for the same good reason (the editors, the link bar, the emoji picker, the preview dialogs, the card modal). All of them had the same stray halo. They now clear the shadow too, and a sweep over src finds no outline suppression left without it.

The empty state floated in the middle of the page

nldd-inline-dialog sets flex-grow: 1 on its host and centres its content in whatever height it gets - that is its design ("fills the container"). In the reading list its wrapper is a page-tall flex column, so it stretched to 912px around 107px of content and parked the message halfway down.

flex-grow: 0 holds it to its content height: 203px, sitting under the header. Full width is preserved.

Worth recording: align-self: start does not work here. The column's cross axis is horizontal, so it only narrowed the box while leaving the height untouched.

The Focus empty state was already correct - its wrapper is a row, so flex-grow lands on the width there. Verified rather than assumed.

Verified

Measured in a running preview before and after; vue-tsc clean, 541 tests green, build green, eslint 0 errors.

Two regressions from the NLDD work, both reported from the running app. ## The search box had a halo but no ring `SearchRow` shows focus on the `.field` wrapper and deliberately sets `outline: none` on the inner input. That beats the global `:focus-visible` rule on source order at equal specificity - but only for the outline. Its `box-shadow` survived, and `--semantics-focus-ring-box-shadow` is a 6px halo in the page background colour. So the focused search box drew background onto background with no ring: the same failure #198 fixed globally, reintroduced locally by a legitimate override. The ring now sits on `.field`, which is what a user perceives as the search box, and the input clears both halves of the global rule. **Eight other places** suppress the outline for the same good reason (the editors, the link bar, the emoji picker, the preview dialogs, the card modal). All of them had the same stray halo. They now clear the shadow too, and a sweep over `src` finds no outline suppression left without it. ## The empty state floated in the middle of the page `nldd-inline-dialog` sets `flex-grow: 1` on its host and centres its content in whatever height it gets - that is its design ("fills the container"). In the reading list its wrapper is a page-tall flex column, so it stretched to **912px around 107px of content** and parked the message halfway down. `flex-grow: 0` holds it to its content height: 203px, sitting under the header. Full width is preserved. Worth recording: `align-self: start` does **not** work here. The column's cross axis is horizontal, so it only narrowed the box while leaving the height untouched. The Focus empty state was already correct - its wrapper is a row, so `flex-grow` lands on the width there. Verified rather than assumed. ## Verified Measured in a running preview before and after; `vue-tsc` clean, 541 tests green, build green, eslint 0 errors.
Give the search box its focus ring back, and stop the empty state floating
All checks were successful
CI / release-scripts (pull_request) Successful in 8s
security-scan / JS SCA (npm audit) (pull_request) Successful in 38s
security-scan / Filesystem scan (trivy fs) (pull_request) Successful in 26s
security-scan / SBOM (trivy) (pull_request) Successful in 16s
security-scan / Python SAST (bandit) (pull_request) Successful in 43s
CI / pre-commit (pull_request) Successful in 1m22s
security-scan / Python SCA (pip-audit) (pull_request) Successful in 1m6s
CI / backend-test (pull_request) Successful in 1m42s
CI / frontend-test (pull_request) Successful in 1m50s
test-build / build (backend) (pull_request) Successful in 1m7s
test-build / build (frontend) (pull_request) Successful in 1m12s
test-build / build (pull_request) Successful in 0s
CI / e2e (pull_request) Successful in 3m28s
CI / backend-test-postgres (pull_request) Successful in 4m30s
CI / release-scripts (push) Successful in 6s
security-scan / SBOM (trivy) (push) Successful in 10s
security-scan / Filesystem scan (trivy fs) (push) Successful in 14s
security-scan / JS SCA (npm audit) (push) Successful in 23s
security-scan / Python SAST (bandit) (push) Successful in 24s
CI / pre-commit (push) Successful in 35s
security-scan / Python SCA (pip-audit) (push) Successful in 44s
CI / backend-test (push) Successful in 1m27s
publish-main / build (backend) (push) Successful in 1m32s
publish-main / build (frontend) (push) Successful in 1m32s
publish-main / build (push) Successful in 0s
CI / frontend-test (push) Successful in 1m40s
CI / e2e (push) Successful in 3m19s
CI / backend-test-postgres (push) Successful in 4m12s
e4467eb45f
Two regressions from the NLDD work, both visible.

The search box lost its focus indicator. SearchRow draws focus on the .field
wrapper and deliberately sets outline: none on the inner input; that beats the
global :focus-visible rule on source order at equal specificity, but its
box-shadow survives. The result was the halo without the ring - the same
background-on-background failure #198 fixed, reintroduced locally. The ring now
sits on .field, where the user perceives the box, and the input clears both
halves.

Eight other places suppress the outline for the same legitimate reason and had
the same stray halo. All of them now clear the shadow too; a check over src
finds no outline suppression left without it.

The reading-list empty state sat halfway down the page. nldd-inline-dialog sets
flex-grow: 1 on its host and centres its content in whatever height it gets, so
in a page-tall flex column it stretched to 912px around 107px of content.
flex-grow: 0 holds it to its content height; it is 203px now and sits under the
header. align-self does not work here - the column's cross axis is horizontal,
so it only narrowed the box.

The Focus empty state was already correct: its wrapper is a row, so flex-grow
lands on the width there.
robbertbos deleted branch search-focus-and-empty-state 2026-07-26 20:17:30 +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!206
No description provided.