Search palette: accent border around the dialog; Recent/Navigate rows show icons without labels #1093

Open
opened 2026-10-05 04:39:15 +00:00 by kayg · 17 comments
Owner

Owner report (2026-10-05, production 269b1b51b, desktop dark)

Search palette (Cmd/Ctrl+K):

  1. "wth is this border?" A thick accent-coloured border runs around the whole palette. Remove it; the palette uses the standard glass overlay edge like other overlays (keep keyboard focus rings on the focused control, not around the whole dialog).
  2. Rows in RECENT and NAVIGATE show only an icon with no label: two RECENT rows (a sliders icon = Settings?, a compass icon) and every NAVIGATE row (Calendar, Notes, Files, Photos, Mail, Analytics …) are blank apart from the icon. Every row must show its label (and its shortcut where it has one).

Note: the toast with an accent border on the Tasks Tab is the countdown border the owner asked for earlier (accent countdown ending at the top centre); keep that.

## Owner report (2026-10-05, production 269b1b51b, desktop dark) Search palette (Cmd/Ctrl+K): 1. "wth is this border?" A thick accent-coloured border runs around the whole palette. Remove it; the palette uses the standard glass overlay edge like other overlays (keep keyboard focus rings on the focused control, not around the whole dialog). 2. Rows in RECENT and NAVIGATE show only an icon with no label: two RECENT rows (a sliders icon = Settings?, a compass icon) and every NAVIGATE row (Calendar, Notes, Files, Photos, Mail, Analytics …) are blank apart from the icon. Every row must show its label (and its shortcut where it has one). Note: the toast with an accent border on the Tasks Tab is the countdown border the owner asked for earlier (accent countdown ending at the top centre); keep that.
Author
Owner

Starting work on branch job/palette-1093 at base 269b1b51b. I am tracing the palette row data and shared overlay styles, then I will add the accessible-name regression check and capture the requested production screenshots.

Starting work on branch job/palette-1093 at base 269b1b51b. I am tracing the palette row data and shared overlay styles, then I will add the accessible-name regression check and capture the requested production screenshots.
Author
Owner

Finding: row labels are present in the data ( supplies labels; SearchResultRow renders ), but their wrapper reuses the global class from . That shared selector absolutely positions the wrapper and sets until a row is hovered, hiding labels in Recent and Navigate. Separately, Search opts into OverlaySurface's , which paints the keyboard focus ring on the whole dialog. I will give the row wrapper a Search-specific class and keep the focus ring on the query control while retaining the shared glass edge.

Finding: row labels are present in the data ( supplies labels; SearchResultRow renders ), but their wrapper reuses the global class from . That shared selector absolutely positions the wrapper and sets until a row is hovered, hiding labels in Recent and Navigate. Separately, Search opts into OverlaySurface's , which paints the keyboard focus ring on the whole dialog. I will give the row wrapper a Search-specific class and keep the focus ring on the query control while retaining the shared glass edge.
Author
Owner

Finding update: Search route data is intact. PLUGIN_NAVIGATION supplies labels and SearchResultRow renders them, but its wrapper used the same global .row-copy class as FloatingSidebar's copy-link action. FloatingSidebar.svelte hides that class with opacity zero until hover, so Recent and Navigate labels vanished. Search also set OverlaySurface's surfaceFocusProxy, which draws the keyboard ring around the whole dialog. Search now uses its own row wrapper, names each option from the visible title, and puts the keyboard ring on the query input. I refreshed the existing exact list-scope hashes in contracts/perf/exceptions.json; the performance bounds and owners did not change.

Finding update: Search route data is intact. `PLUGIN_NAVIGATION` supplies labels and `SearchResultRow` renders them, but its wrapper used the same global `.row-copy` class as FloatingSidebar's copy-link action. `FloatingSidebar.svelte` hides that class with opacity zero until hover, so Recent and Navigate labels vanished. Search also set OverlaySurface's `surfaceFocusProxy`, which draws the keyboard ring around the whole dialog. Search now uses its own row wrapper, names each option from the visible title, and puts the keyboard ring on the query input. I refreshed the existing exact list-scope hashes in `contracts/perf/exceptions.json`; the performance bounds and owners did not change.
Author
Owner

Owner update (2026-10-05, screenshot owner-palette-preview.png in the job worktree): the Recent/Navigate row labels are NOT missing. They render dark text on the dark glass (black on black), so they are invisible. Root cause is a colour token: the row label uses a text token that is not theme-aware (or inherits a light-theme ink) in dark themes. Also in the preview pane: the action row (Attach File, Edit, Delete, …) is clipped at the right edge, and an accent vertical line runs along the right border. Fix contrast with the right role token (check every theme meets WCAG AA 4.5:1 for labels), stop the clipping (wrap or overflow menu), and remove the accent line. Add a contrast check for palette rows in all themes.

Owner update (2026-10-05, screenshot owner-palette-preview.png in the job worktree): the Recent/Navigate row labels are NOT missing. They render dark text on the dark glass (black on black), so they are invisible. Root cause is a colour token: the row label uses a text token that is not theme-aware (or inherits a light-theme ink) in dark themes. Also in the preview pane: the action row (Attach File, Edit, Delete, …) is clipped at the right edge, and an accent vertical line runs along the right border. Fix contrast with the right role token (check every theme meets WCAG AA 4.5:1 for labels), stop the clipping (wrap or overflow menu), and remove the accent line. Add a contrast check for palette rows in all themes.
Author
Owner

Continuing #1093 on branch job/palette-1093 at base 269b1b51b5. I reviewed the 2026-10-05 owner screenshot and comment. The existing row-wrapper fix is useful, but the screenshot confirms a separate contrast-token failure on dark glass; it also shows the preview action row clipped at the pane edge and an accent divider. I am tracing the shared theme roles and preview layout, then will add palette contrast coverage and production E2E checks for the requested themes and widths.

Continuing #1093 on branch job/palette-1093 at base 269b1b51b5774d79de08bfb31d058b3d248a7e7b. I reviewed the 2026-10-05 owner screenshot and comment. The existing row-wrapper fix is useful, but the screenshot confirms a separate contrast-token failure on dark glass; it also shows the preview action row clipped at the pane edge and an accent divider. I am tracing the shared theme roles and preview layout, then will add palette contrast coverage and production E2E checks for the requested themes and widths.
Author
Owner

Finding: bun run check from apps/web reached perf-lint and rejected the existing SearchPreview render.bound ledger entry because the source hash changed with the width/wrapping fix. The recorded finite-row bound and owner are unchanged. I am refreshing only the matching source-hash entries before rerunning the gate.

Finding: `bun run check` from `apps/web` reached perf-lint and rejected the existing SearchPreview `render.bound` ledger entry because the source hash changed with the width/wrapping fix. The recorded finite-row bound and owner are unchanged. I am refreshing only the matching source-hash entries before rerunning the gate.
Author
Owner

E2E setup finding: /mnt/hdd/targets/shared-server/CURRENT is absent, and the provided shared-server build script fails because its source checkout has no apps/web/build for the embedded frontend. I am building the worktree production assets and server locally for the requested search E2E.

E2E setup finding: /mnt/hdd/targets/shared-server/CURRENT is absent, and the provided shared-server build script fails because its source checkout has no apps/web/build for the embedded frontend. I am building the worktree production assets and server locally for the requested search E2E.
Author
Owner

Search E2E finding: the production run timed out at apps/web/e2e/search.mjs:970 while captureIndexingPalette opened Search; the dialog did not become visible within 30 seconds. CSP reports were 0 across 1 page. No screenshot was captured. I am inspecting the setup and will use one focused rerun after resolving the cause.

Search E2E finding: the production run timed out at apps/web/e2e/search.mjs:970 while captureIndexingPalette opened Search; the dialog did not become visible within 30 seconds. CSP reports were 0 across 1 page. No screenshot was captured. I am inspecting the setup and will use one focused rerun after resolving the cause.
Author
Owner

E2E diagnosis: the harness emulates macOS before interaction checks, but openSearch sent Control+K. The app binds the primary Search shortcut to Command+K on macOS (apps/web/src/lib/shortcuts/match.ts:67), so the palette never opened. I changed the helper and the direct action-menu shortcut to Meta+K to match that platform; I will rerun the production search E2E once.

E2E diagnosis: the harness emulates macOS before interaction checks, but openSearch sent Control+K. The app binds the primary Search shortcut to Command+K on macOS (apps/web/src/lib/shortcuts/match.ts:67), so the palette never opened. I changed the helper and the direct action-menu shortcut to Meta+K to match that platform; I will rerun the production search E2E once.
Author
Owner

Merge finding: origin/dev carries an exact #1058 adoption checkpoint for SearchDialog's template scope. A local SearchDialog edit invalidated that accepted checkpoint. I kept the upstream SearchDialog intact and moved the focus-ring ownership adjustment to SearchField CSS: the query input retains the shared focus token and the overlay retains its standard glass edge.

Merge finding: origin/dev carries an exact #1058 adoption checkpoint for SearchDialog's template scope. A local SearchDialog edit invalidated that accepted checkpoint. I kept the upstream SearchDialog intact and moved the focus-ring ownership adjustment to SearchField CSS: the query input retains the shared focus token and the overlay retains its standard glass edge.
Author
Owner

Performance-lint finding after merging origin/dev: apps/web/src/lib/search/SearchField.svelte#each:285e5ba945fef3df:1:adapter was stale after the field style change. The parser emits the current base list hash; I am aligning its related derived pins to that parsed source while preserving their upstream owners and reasons.

Performance-lint finding after merging origin/dev: apps/web/src/lib/search/SearchField.svelte#each:285e5ba945fef3df:1:adapter was stale after the field style change. The parser emits the current base list hash; I am aligning its related derived pins to that parsed source while preserving their upstream owners and reasons.
Author
Owner

Merged-tree check finding: passed perf-lint and shared token checks, then svelte-check reported 46 errors in 7 files. The diagnostics include in newly merged Canvas files, with dependent implicit-any errors. I am installing the frozen lockfile dependencies and will rerun once.

Merged-tree check finding: passed perf-lint and shared token checks, then svelte-check reported 46 errors in 7 files. The diagnostics include in newly merged Canvas files, with dependent implicit-any errors. I am installing the frozen lockfile dependencies and will rerun once.
Author
Owner

Merged-tree check finding: bun run check passed perf-lint and shared token checks, then svelte-check reported 46 errors in 7 files. The diagnostics include Cannot find module @excalidraw/excalidraw in newly merged Canvas files, with dependent implicit-any errors. I am installing the frozen lockfile dependencies and will rerun once.

Merged-tree check finding: bun run check passed perf-lint and shared token checks, then svelte-check reported 46 errors in 7 files. The diagnostics include Cannot find module @excalidraw/excalidraw in newly merged Canvas files, with dependent implicit-any errors. I am installing the frozen lockfile dependencies and will rerun once.
Author
Owner

The screenshot-enabled search E2E found a harness ReferenceError: its final touch context used screenshotDpr without defining it. The main contexts already use the review scale (2x when SEARCH_E2E_REVIEW_2X=1, otherwise 1x). I added the same explicit scale for the touch context and am rerunning the full Search E2E.

The screenshot-enabled search E2E found a harness `ReferenceError`: its final touch context used `screenshotDpr` without defining it. The main contexts already use the review scale (2x when `SEARCH_E2E_REVIEW_2X=1`, otherwise 1x). I added the same explicit scale for the touch context and am rerunning the full Search E2E.
Author
Owner

The real-server E2E reached Search and failed its existing shared-glass action assertion: .pill.btn had higher CSS specificity than .glass-chrome, so the Attach/Open actions used the opaque --paper-2 fallback instead of the shared chrome tint. This was a production styling defect, not a stale test. I set the action controls' fill and hover fill to the shared glass-chrome roles; the existing assertion remains unchanged.

The real-server E2E reached Search and failed its existing shared-glass action assertion: `.pill.btn` had higher CSS specificity than `.glass-chrome`, so the Attach/Open actions used the opaque `--paper-2` fallback instead of the shared chrome tint. This was a production styling defect, not a stale test. I set the action controls' fill and hover fill to the shared glass-chrome roles; the existing assertion remains unchanged.
Author
Owner

The full Search E2E now passes the action fill check, then fails its existing each action uses the shared glass hairline assertion. The shared Pill contract in DESIGN §34 / #1029 says action-button borders stay transparent, and the rendered Search actions follow that rule. I left the old assertion unchanged. I am adding a focused #1093 production-build E2E path to run the requested palette contrast, focus edge, preview bounds and screenshot checks without rewriting this unrelated expectation.

The full Search E2E now passes the action fill check, then fails its existing `each action uses the shared glass hairline` assertion. The shared Pill contract in DESIGN §34 / #1029 says action-button borders stay transparent, and the rendered Search actions follow that rule. I left the old assertion unchanged. I am adding a focused #1093 production-build E2E path to run the requested palette contrast, focus edge, preview bounds and screenshot checks without rewriting this unrelated expectation.
Author
Owner

Finished — palette #1093

Branch: job/palette-1093
Head: 1f29a5eed7e68fe25d98ee1f729b4117e86fee61 (fix(search): keep palette labels readable across themes)

Built

  • Palette result titles use the theme-aware glass text role. Every row now exposes its visible title as its accessible name, with “Untitled” for a blank title. Search rows use their own text wrapper so the FloatingSidebar .row-copy rule cannot hide them.
  • Added a WCAG AA contrast check over every theme mesh point and the selected-row fill.
  • Calendar preview actions wrap inside the preview width on desktop and phone. Search action fills use the shared chrome tokens.
  • The query input owns the focus ring; the palette retains the standard shared edge without an outer accent ring.
  • Refreshed the exact #1058 performance adoption hashes for the SearchDialog source change.

Files

  • apps/web/src/lib/search/SearchResultRow.svelte and its focused test
  • apps/web/src/lib/themes.test.ts
  • apps/web/src/lib/search/SearchPreview.svelte
  • apps/web/src/lib/components/search-dialog.svelte
  • apps/web/src/lib/search/SearchField.svelte
  • apps/web/e2e/search.mjs
  • contracts/perf/adoption-1058.json
  • contracts/perf/exceptions.json

UX gaps closed

  • Recent, Navigate, Actions and content rows keep a visible, screen-reader-named title, including blank-title results.
  • Preview actions remain within the available pane or phone sheet width.
  • Keyboard focus stays on the rounded query control and does not paint an accent perimeter on the dialog.

UX gaps left

  • The full Search E2E stops at an existing action-button hairline assertion. It conflicts with the shared Pill contract, which keeps action-button borders transparent (DESIGN §34, #1029). I did not change that expectation. This leaves the full Search E2E gate unresolved and makes this not ready for merge pending orchestrator review.
  • The full suite stopped before its later largest-palette measurement. The local server sample below is not a replacement for that worst-case profile.

Decisions

  • Use --glass-text-primary for labels and retain the accent-soft selection fill and icon. The automated contrast test checks light and dark themes.
  • Wrap the calendar action groups instead of hiding actions in an overflow menu.
  • Give the query control the shared focus ring and keep the overlay edge on its standard glass role.
  • Keep Search action borders transparent per DESIGN §34 / #1029, despite the conflicting older E2E expectation.

Verification

bun run check passed. Verbatim summary output:

perf-lint: PASS; 0 violations; 21977 scoped exceptions
User browser caches use userStorage; only documented device/public-link exceptions remain.
Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css.
Text sizes and UI shape values use shared role tokens.
Keyboard focus rings use the shared focus tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
svelte-check found 0 errors and 4 warnings in 3 files

Focused Vitest passed:

 Test Files  2 passed (2)
      Tests  87 passed (87)
   Duration  46.06s (transform 75%, tests 16%, import 5%, environment 4%, setup 1%)

The production web build exited 0:

✓ built in 1m 58s
Compressed 877 static variants; saved 20840812 bytes.

Focused production-build Search E2E passed with macOS platform emulation:

PASS #1093 row labels, focus edge and preview action bounds across the four review themes
CSP REPORTS search: 0 across 2 pages

The full Search E2E reached this existing failure, with the expectation left unchanged:

AssertionError [ERR_ASSERTION]: each action uses the shared glass hairline
+ actual - expected
+ 'rgba(0, 0, 0, 0)'
- 'color(srgb 0.890196 0.890196 0.882353 / 0.82)'

Local Search server sample from that run: p50 97.0ms, p95 242.3ms, mean CPU 71.55%, mean RSS 563.8 MiB, peak RSS 565.7 MiB. The #499 local reference in docs/perf/baseline.json is p50 52.6ms, p95 248.3ms, mean CPU 56.07%, mean RSS 518978163 bytes. The host load was not recorded, so these local samples are not directly comparable. No search algorithm changed.

Rust files were unchanged. cargo clean removed 8.2 GiB. Web build output was deleted after the captures.

macOS review screenshots attached

The empty palette is attached at 390, 820 and 1440 px. The selected Calendar preview is attached at 390 and 1440 px for every theme.

Theme Empty palette Selected preview
mono 390 · 820 · 1440 390 · 1440
noir 390 · 820 · 1440 390 · 1440
tokyo-night 390 · 820 · 1440 390 · 1440
paper 390 · 820 · 1440 390 · 1440

READY FOR MERGE: no — the focused #1093 review passes, but the full Search E2E remains red on the conflicting shared-Pill border assertion.

## Finished — palette #1093 Branch: `job/palette-1093` Head: `1f29a5eed7e68fe25d98ee1f729b4117e86fee61` (`fix(search): keep palette labels readable across themes`) ### Built - Palette result titles use the theme-aware glass text role. Every row now exposes its visible title as its accessible name, with “Untitled” for a blank title. Search rows use their own text wrapper so the FloatingSidebar `.row-copy` rule cannot hide them. - Added a WCAG AA contrast check over every theme mesh point and the selected-row fill. - Calendar preview actions wrap inside the preview width on desktop and phone. Search action fills use the shared chrome tokens. - The query input owns the focus ring; the palette retains the standard shared edge without an outer accent ring. - Refreshed the exact #1058 performance adoption hashes for the SearchDialog source change. ### Files - `apps/web/src/lib/search/SearchResultRow.svelte` and its focused test - `apps/web/src/lib/themes.test.ts` - `apps/web/src/lib/search/SearchPreview.svelte` - `apps/web/src/lib/components/search-dialog.svelte` - `apps/web/src/lib/search/SearchField.svelte` - `apps/web/e2e/search.mjs` - `contracts/perf/adoption-1058.json` - `contracts/perf/exceptions.json` ### UX gaps closed - Recent, Navigate, Actions and content rows keep a visible, screen-reader-named title, including blank-title results. - Preview actions remain within the available pane or phone sheet width. - Keyboard focus stays on the rounded query control and does not paint an accent perimeter on the dialog. ### UX gaps left - The full Search E2E stops at an existing action-button hairline assertion. It conflicts with the shared Pill contract, which keeps action-button borders transparent (DESIGN §34, #1029). I did not change that expectation. This leaves the full Search E2E gate unresolved and makes this **not ready for merge** pending orchestrator review. - The full suite stopped before its later largest-palette measurement. The local server sample below is not a replacement for that worst-case profile. ### Decisions - Use `--glass-text-primary` for labels and retain the accent-soft selection fill and icon. The automated contrast test checks light and dark themes. - Wrap the calendar action groups instead of hiding actions in an overflow menu. - Give the query control the shared focus ring and keep the overlay edge on its standard glass role. - Keep Search action borders transparent per DESIGN §34 / #1029, despite the conflicting older E2E expectation. ### Verification `bun run check` passed. Verbatim summary output: ```text perf-lint: PASS; 0 violations; 21977 scoped exceptions User browser caches use userStorage; only documented device/public-link exceptions remain. Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css. Text sizes and UI shape values use shared role tokens. Keyboard focus rings use the shared focus tokens. UI transitions and animation options use shared motion tokens or documented exceptions. svelte-check found 0 errors and 4 warnings in 3 files ``` Focused Vitest passed: ```text Test Files 2 passed (2) Tests 87 passed (87) Duration 46.06s (transform 75%, tests 16%, import 5%, environment 4%, setup 1%) ``` The production web build exited 0: ```text ✓ built in 1m 58s Compressed 877 static variants; saved 20840812 bytes. ``` Focused production-build Search E2E passed with macOS platform emulation: ```text PASS #1093 row labels, focus edge and preview action bounds across the four review themes CSP REPORTS search: 0 across 2 pages ``` The full Search E2E reached this existing failure, with the expectation left unchanged: ```text AssertionError [ERR_ASSERTION]: each action uses the shared glass hairline + actual - expected + 'rgba(0, 0, 0, 0)' - 'color(srgb 0.890196 0.890196 0.882353 / 0.82)' ``` Local Search server sample from that run: p50 `97.0ms`, p95 `242.3ms`, mean CPU `71.55%`, mean RSS `563.8 MiB`, peak RSS `565.7 MiB`. The #499 local reference in `docs/perf/baseline.json` is p50 `52.6ms`, p95 `248.3ms`, mean CPU `56.07%`, mean RSS `518978163` bytes. The host load was not recorded, so these local samples are not directly comparable. No search algorithm changed. Rust files were unchanged. `cargo clean` removed 8.2 GiB. Web build output was deleted after the captures. ### macOS review screenshots attached The empty palette is attached at 390, 820 and 1440 px. The selected Calendar preview is attached at 390 and 1440 px for every theme. | Theme | Empty palette | Selected preview | |---|---|---| | mono | [390](https://git.kayg.org/attachments/f1e54160-a44b-4248-8fae-63f316535a09) · [820](https://git.kayg.org/attachments/8d40119c-d20b-4362-9949-568e1e7e3613) · [1440](https://git.kayg.org/attachments/3d3a1789-9bb4-40ba-b980-8bd90e57e951) | [390](https://git.kayg.org/attachments/1a430390-2d35-4d71-ae46-551173745a33) · [1440](https://git.kayg.org/attachments/51d9be91-9678-4672-b7ce-0c90e9209fa9) | | noir | [390](https://git.kayg.org/attachments/23e848f1-a26b-47d3-9004-f087604d884d) · [820](https://git.kayg.org/attachments/bb3c072a-3a4f-49fe-a32d-0d540602aacc) · [1440](https://git.kayg.org/attachments/edf225bb-60b1-4062-97c9-7c42a4ebf503) | [390](https://git.kayg.org/attachments/6ae7a5e2-848f-47dc-b44c-ecf9f4022a9f) · [1440](https://git.kayg.org/attachments/86b04269-1c5c-4f41-a2ed-bf3b83d54653) | | tokyo-night | [390](https://git.kayg.org/attachments/cc1633ee-c082-4d60-b071-4337788a38f5) · [820](https://git.kayg.org/attachments/470bf78b-737e-4751-985c-1dfefb56321f) · [1440](https://git.kayg.org/attachments/aa55024a-d304-4b5e-8d42-1395a72fc84d) | [390](https://git.kayg.org/attachments/6a9363a1-087c-418e-b464-cdf0d51f393b) · [1440](https://git.kayg.org/attachments/5141642c-816f-4d2d-8c14-88165a220919) | | paper | [390](https://git.kayg.org/attachments/f6264995-61f2-4f16-bdc9-a28ea5832b7f) · [820](https://git.kayg.org/attachments/4d98b41b-6976-4c63-9dc4-9b232125ee3c) · [1440](https://git.kayg.org/attachments/8d92ec64-906e-44e3-8cc3-e132057e456f) | [390](https://git.kayg.org/attachments/5be842c6-e7a7-4f43-af1b-c298c3b679b9) · [1440](https://git.kayg.org/attachments/436baad3-11a7-4141-a79a-25136f5ed291) | **READY FOR MERGE: no** — the focused #1093 review passes, but the full Search E2E remains red on the conflicting shared-Pill border assertion.
Sign in to join this conversation.
No labels
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
kayg/calternal#1093
No description provided.