Fix PWA WCO sidebar tab icon visibility and complete dock safe-area insets #141

Closed
opened 2026-05-29 15:16:58 +00:00 by steve · 0 comments
Owner

Installed Chromium desktop PWAs can hide the native title bar via Window Controls Overlay (WCO) and draw app chrome edge-to-edge. A series of fixes landed for theme color, unified chrome background, platform safe areas, collapsed title-bar geometry, and top-tab layout — but sidebar dock tab icons (left and right) are still not visible in WCO mode, and the chrome bottom border is missing while the overlay is active. This issue tracks the remaining fix and documents what already shipped.

Problem

After enabling WCO in the installed PWA:

  • Sidebar dock tab icons are not visible — the toggle-group icons in the left (and right) sidebar tab header row (tabs-sidebar.svelte.sidebar-workspace-tab-header-container) do not render in a usable way. Center top tabs were fixed for collapsed/expanded title-bar geometry, but the sidebar dock headers were not fully corrected.
  • Title-bar bottom border is missing in WCO mode — the 1px chrome separator only applies when data-pwa-titlebar-hidden is absent, but WCO always sets data-pwa-titlebar-hidden="true".
  • Right dock lacks a split-scoped right safe-area inset — Windows/Linux caption-button clearance exists as a blanket rule on outer header bars; the right sidebar inner tab row does not mirror Electron-style split-scoped insets.

Users on macOS Chrome PWAs (and Windows/Linux where WCO is supported) see broken top chrome in the sidebar docks even though center tabs may look correct.

Background — fixes already applied

The following PWA header / title-bar work is already merged (2026-05-29, @lapis-notes/web + shared workspace shell CSS):

Host theme and manifest

  • host-theme-color.ts — dynamic <meta name="theme-color"> synced to --workspace-chrome-background (not static brand blue).
  • index.html — light/dark bootstrap theme-color metas.
  • vite.config.ts — manifest theme_color / background_color aligned to shell tokens (#f6f6f6 light baseline); display_override: ["window-controls-overlay", "standalone"].

PWA host document and runtime markers

  • pwa-host-document.ts — early data-pwa-host="true", data-runtime="web-pwa", data-os, installed-PWA detection before workspace mount.

Window Controls Overlay geometry

  • pwa-window-controls.ts — tracks display mode, sets data-pwa-titlebar-hidden="true" in WCO, listens to geometrychange, mirrors overlay rect into CSS custom properties.
  • pwa-window-controls-core.ts — pure inset helpers:
    • macOS defaults: top 38px, left 78px (traffic lights)
    • Windows/Linux defaults: top 32px, right 138px (caption buttons)
    • Collapsed title bar: when getTitlebarAreaRect().height === 0 with known width, top inset clears to 0 so negative-margin tab headers are not clipped off-screen (initial all-zero rect still uses platform default).
  • Vitestpackages/web/src/pwa-window-controls.test.ts (7 cases).

Unified chrome background

  • workspace-shell.css--workspace-chrome-background: var(--sidebar) wired to --tab-container-background, --titlebar-background, --ribbon-background.
  • Top-tab header bar, sidebar tab header bar, sidebar toggle wrapper, and related chrome surfaces share the same background token.
  • host-theme-color.ts and popout theme mirroring resolve --workspace-chrome-background first.

WCO layout CSS (shared workspace shell)

Under @media (display-mode: window-controls-overlay) and html[data-pwa-host="true"]:

  • CSS env / JS-driven vars: --workspace-safe-area-top, --workspace-safe-area-left, --workspace-safe-area-right.
  • Fixed ::before on :root fills the top safe-area strip with chrome background (z-index: 1000).
  • Top and sidebar tab header bars extend into the overlay via negative margin-top + padding-top on --workspace-safe-area-top, with z-index: 1001.
  • macOS left insets on center tabs (mod-top-left-space, mod-popout-left-safe-area) and chrome header row first child.
  • Windows/Linux right padding on top-tab and sidebar outer header bars.
  • Ribbon column chrome fill via ::before; macOS ribbon padding-left (likely incorrect — pushes icons out of the ~48px column; cleanup planned).
  • Vault chooser top padding when title bar hidden.

Visible title-bar border (partial)

  • Bottom border on top/sidebar chrome header rows when native title bar is visible (:not([data-pwa-titlebar-hidden="true")]).
  • Does not apply in WCO mode — the mode users actually run in.

Collapsed title bar regression fix + tests

  • Fixed center top tabs disappearing when Chrome collapses the native title bar.
  • Playwrightpackages/workspace/e2e/pwa-title-bar.spec.ts (collapsed 0px vs expanded 38px top-tab layout).

Spec updates

Relevant commits (jj, 2026-05-29)

  • Unify PWA title bar, sidebar header, and top-tab chrome background
  • Derive PWA WCO safe areas per platform from overlay geometry
  • Add sidebar-colored bottom border to visible PWA title chrome
  • Fix collapsed PWA title bar clipping and add regression tests

Goal

Make installed PWA WCO chrome fully usable for both sidebar docks:

  1. Sidebar dock tab icons visible in expanded and collapsed title-bar states.
  2. Split-scoped safe-area insets: left dock (macOS traffic lights), right dock (Windows/Linux caption buttons).
  3. 1px bottom border on chrome header rows in WCO mode, using --workspace-sidebar-header-border.
  4. Regression tests covering left/right sidebar icon visibility, right inset, and border.

Scope

A. Sidebar tab header flex / height under WCO (left and right docks)

Both docks use tabs-sidebar.svelte. The header bar has inline flex: 0 0 var(--header-height) and fixed h-[var(--header-height)], which conflicts with WCO padding-top: var(--workspace-safe-area-top).

In workspace-shell.css WCO block:

  • Override .workspace-shell__tabs--sidebar > .workspace-shell__tab-header-bar flex basis to calc(var(--header-height) + var(--workspace-safe-area-top)).
  • Relax .sidebar-workspace-tab-header-container height under WCO: height: auto; min-height: var(--header-height); align-items: center.

B. Split-scoped safe-area insets

  • Left dock (macOS): .workspace-shell__split--left .sidebar-workspace-tab-header-containerpadding-left: calc(var(--size-4-2) + var(--desktop-titlebar-left-split-gap)) (mirror Electron rule; uses traffic-light gap minus ribbon width).
  • Right dock (Windows/Linux): .workspace-shell__split--right .sidebar-workspace-tab-header-containerpadding-right: calc(var(--size-4-2) + var(--workspace-safe-area-right)).
  • Refine existing blanket Windows/Linux padding-right on sidebar outer header bars — keep center top tabs on outer bar; move sidebar dock insets to inner container via split-scoped rules to avoid double padding on the left dock.

C. WCO chrome bottom border

Add border rule for data-pwa-titlebar-hidden="true" on top-tab, sidebar-tab, and chrome-header-row surfaces inside the WCO media block.

D. Cleanup

Remove incorrect macOS full --workspace-safe-area-left padding on the narrow ribbon column (~48px wide).

Non-goals

  • Changing Electron desktop title-bar behavior.
  • Revisiting center top-tab layout beyond what collapsed/expanded tests already cover.
  • Ribbon icon column changes unless required by shared chrome alignment (ribbon was not the reported regression).
  • Forcing WCO on browsers that only support standalone display mode.

Acceptance Criteria

  • In an installed Chromium PWA with WCO active, left sidebar dock tab icons ([role='radio'] in .workspace-shell__split--left .sidebar-workspace-tab-header-container) have non-zero visible size in both collapsed (0px top inset) and expanded (~38px top inset) title-bar states.
  • With the right sidebar dock open, right dock tab icons are similarly visible under WCO.
  • On Windows/Linux PWA hosts, right-split .sidebar-workspace-tab-header-container receives padding-right that includes --workspace-safe-area-right.
  • On macOS PWA hosts, left-split .sidebar-workspace-tab-header-container receives left-split-gap padding (not full traffic-light width on the ribbon).
  • Chrome header rows show a 1px bottom border (--workspace-sidebar-header-border) in WCO mode.
  • Playwright coverage extended in packages/workspace/e2e/pwa-title-bar.spec.ts for sidebar icons, right inset, and border.
  • pnpm --filter @lapis-notes/web check and workspace Playwright spec pass.
  • Spec pages updated if behavior changes; make spec-lint passes when spec is touched.

Root-cause notes (investigation)

WCO adds padding-top to sidebar tab header bar
  + inline flex: 0 0 40px on the same element
  + fixed height: 40px on inner .workspace-tab-header-container
→ content box can collapse to ~2px when padding-top is 38px
→ toggle-group icons hidden (left and right docks share tabs-sidebar.svelte)

Border rule at workspace-shell.css lines ~202–210 excludes data-pwa-titlebar-hidden="true", which WCO always sets.

Suggested Files or Specs To Inspect

Validation Commands

pnpm --filter @lapis-notes/web check
pnpm --filter @lapis-notes/workspace exec playwright test e2e/pwa-title-bar.spec.ts --project chromium
make spec-lint   # when spec pages change

Manual verification requires reinstalling/relaunching the PWA after manifest changes for WCO to activate.

Follow-up Tasks

  • Consider adding a visual regression snapshot for PWA WCO chrome (left/right docks + center tabs) once icons are fixed.
  • Audit ribbon padding-left interaction with macOS traffic lights separately from dock tab icons.

Implementation Summary

Explicitly colored WCO sidebar tab icons and tightened the PWA regression to assert painted icon contrast.

Reopen Reason

Sidebar dock icons still respond but are not visibly painted in PWA WCO mode; investigate rendering/color and tighten regression coverage.

Installed Chromium desktop PWAs can hide the native title bar via Window Controls Overlay (WCO) and draw app chrome edge-to-edge. A series of fixes landed for theme color, unified chrome background, platform safe areas, collapsed title-bar geometry, and top-tab layout — but **sidebar dock tab icons (left and right) are still not visible in WCO mode**, and the chrome bottom border is missing while the overlay is active. This issue tracks the remaining fix and documents what already shipped. ## Problem After enabling WCO in the installed PWA: - **Sidebar dock tab icons are not visible** — the toggle-group icons in the left (and right) sidebar tab header row (`tabs-sidebar.svelte` → `.sidebar-workspace-tab-header-container`) do not render in a usable way. Center top tabs were fixed for collapsed/expanded title-bar geometry, but the sidebar dock headers were not fully corrected. - **Title-bar bottom border is missing in WCO mode** — the 1px chrome separator only applies when `data-pwa-titlebar-hidden` is absent, but WCO always sets `data-pwa-titlebar-hidden="true"`. - **Right dock lacks a split-scoped right safe-area inset** — Windows/Linux caption-button clearance exists as a blanket rule on outer header bars; the right sidebar inner tab row does not mirror Electron-style split-scoped insets. Users on macOS Chrome PWAs (and Windows/Linux where WCO is supported) see broken top chrome in the sidebar docks even though center tabs may look correct. ## Background — fixes already applied The following PWA header / title-bar work is **already merged** (2026-05-29, `@lapis-notes/web` + shared workspace shell CSS): ### Host theme and manifest - **`host-theme-color.ts`** — dynamic `<meta name="theme-color">` synced to `--workspace-chrome-background` (not static brand blue). - **`index.html`** — light/dark bootstrap theme-color metas. - **`vite.config.ts`** — manifest `theme_color` / `background_color` aligned to shell tokens (`#f6f6f6` light baseline); `display_override: ["window-controls-overlay", "standalone"]`. ### PWA host document and runtime markers - **`pwa-host-document.ts`** — early `data-pwa-host="true"`, `data-runtime="web-pwa"`, `data-os`, installed-PWA detection before workspace mount. ### Window Controls Overlay geometry - **`pwa-window-controls.ts`** — tracks display mode, sets `data-pwa-titlebar-hidden="true"` in WCO, listens to `geometrychange`, mirrors overlay rect into CSS custom properties. - **`pwa-window-controls-core.ts`** — pure inset helpers: - macOS defaults: top 38px, left 78px (traffic lights) - Windows/Linux defaults: top 32px, right 138px (caption buttons) - **Collapsed title bar:** when `getTitlebarAreaRect().height === 0` with known width, top inset clears to **0** so negative-margin tab headers are not clipped off-screen (initial all-zero rect still uses platform default). - **Vitest** — `packages/web/src/pwa-window-controls.test.ts` (7 cases). ### Unified chrome background - **`workspace-shell.css`** — `--workspace-chrome-background: var(--sidebar)` wired to `--tab-container-background`, `--titlebar-background`, `--ribbon-background`. - Top-tab header bar, sidebar tab header bar, sidebar toggle wrapper, and related chrome surfaces share the same background token. - **`host-theme-color.ts`** and popout theme mirroring resolve `--workspace-chrome-background` first. ### WCO layout CSS (shared workspace shell) Under `@media (display-mode: window-controls-overlay)` and `html[data-pwa-host="true"]`: - CSS env / JS-driven vars: `--workspace-safe-area-top`, `--workspace-safe-area-left`, `--workspace-safe-area-right`. - Fixed `::before` on `:root` fills the top safe-area strip with chrome background (`z-index: 1000`). - Top and sidebar **tab header bars** extend into the overlay via negative `margin-top` + `padding-top` on `--workspace-safe-area-top`, with `z-index: 1001`. - macOS left insets on center tabs (`mod-top-left-space`, `mod-popout-left-safe-area`) and chrome header row first child. - Windows/Linux right padding on top-tab and sidebar **outer** header bars. - Ribbon column chrome fill via `::before`; macOS ribbon `padding-left` (likely incorrect — pushes icons out of the ~48px column; cleanup planned). - Vault chooser top padding when title bar hidden. ### Visible title-bar border (partial) - Bottom border on top/sidebar chrome header rows when native title bar is **visible** (`:not([data-pwa-titlebar-hidden="true")]`). - **Does not apply in WCO mode** — the mode users actually run in. ### Collapsed title bar regression fix + tests - Fixed center top tabs disappearing when Chrome collapses the native title bar. - **Playwright** — `packages/workspace/e2e/pwa-title-bar.spec.ts` (collapsed 0px vs expanded 38px top-tab layout). ### Spec updates - [`packages/web/spec.md`](../../packages/web/spec.md) - [`spec/src/20-packages/web/index.md`](../../spec/src/20-packages/web/index.md) ### Relevant commits (jj, 2026-05-29) - Unify PWA title bar, sidebar header, and top-tab chrome background - Derive PWA WCO safe areas per platform from overlay geometry - Add sidebar-colored bottom border to visible PWA title chrome - Fix collapsed PWA title bar clipping and add regression tests ## Goal Make installed PWA WCO chrome fully usable for **both sidebar docks**: 1. Sidebar dock tab icons visible in expanded and collapsed title-bar states. 2. Split-scoped safe-area insets: left dock (macOS traffic lights), right dock (Windows/Linux caption buttons). 3. 1px bottom border on chrome header rows in WCO mode, using `--workspace-sidebar-header-border`. 4. Regression tests covering left/right sidebar icon visibility, right inset, and border. ## Scope ### A. Sidebar tab header flex / height under WCO (left and right docks) Both docks use [`tabs-sidebar.svelte`](../../packages/workspace/src/lib/components/tabs/tabs-sidebar.svelte). The header bar has inline `flex: 0 0 var(--header-height)` and fixed `h-[var(--header-height)]`, which conflicts with WCO `padding-top: var(--workspace-safe-area-top)`. In [`workspace-shell.css`](../../packages/workspace/src/lib/styles/workspace-shell.css) WCO block: - Override `.workspace-shell__tabs--sidebar > .workspace-shell__tab-header-bar` flex basis to `calc(var(--header-height) + var(--workspace-safe-area-top))`. - Relax `.sidebar-workspace-tab-header-container` height under WCO: `height: auto; min-height: var(--header-height); align-items: center`. ### B. Split-scoped safe-area insets - **Left dock (macOS):** `.workspace-shell__split--left .sidebar-workspace-tab-header-container` → `padding-left: calc(var(--size-4-2) + var(--desktop-titlebar-left-split-gap))` (mirror Electron rule; uses traffic-light gap minus ribbon width). - **Right dock (Windows/Linux):** `.workspace-shell__split--right .sidebar-workspace-tab-header-container` → `padding-right: calc(var(--size-4-2) + var(--workspace-safe-area-right))`. - **Refine** existing blanket Windows/Linux `padding-right` on sidebar outer header bars — keep center top tabs on outer bar; move sidebar dock insets to inner container via split-scoped rules to avoid double padding on the left dock. ### C. WCO chrome bottom border Add border rule for `data-pwa-titlebar-hidden="true"` on top-tab, sidebar-tab, and chrome-header-row surfaces inside the WCO media block. ### D. Cleanup Remove incorrect macOS full `--workspace-safe-area-left` padding on the narrow ribbon column (~48px wide). ## Non-goals - Changing Electron desktop title-bar behavior. - Revisiting center top-tab layout beyond what collapsed/expanded tests already cover. - Ribbon icon column changes unless required by shared chrome alignment (ribbon was not the reported regression). - Forcing WCO on browsers that only support standalone display mode. ## Acceptance Criteria - [ ] In an installed Chromium PWA with WCO active, **left sidebar dock tab icons** (`[role='radio']` in `.workspace-shell__split--left .sidebar-workspace-tab-header-container`) have non-zero visible size in both collapsed (0px top inset) and expanded (~38px top inset) title-bar states. - [ ] With the **right sidebar dock** open, **right dock tab icons** are similarly visible under WCO. - [ ] On Windows/Linux PWA hosts, right-split `.sidebar-workspace-tab-header-container` receives `padding-right` that includes `--workspace-safe-area-right`. - [ ] On macOS PWA hosts, left-split `.sidebar-workspace-tab-header-container` receives left-split-gap padding (not full traffic-light width on the ribbon). - [ ] Chrome header rows show a **1px bottom border** (`--workspace-sidebar-header-border`) in WCO mode. - [ ] Playwright coverage extended in `packages/workspace/e2e/pwa-title-bar.spec.ts` for sidebar icons, right inset, and border. - [ ] `pnpm --filter @lapis-notes/web check` and workspace Playwright spec pass. - [ ] Spec pages updated if behavior changes; `make spec-lint` passes when spec is touched. ## Root-cause notes (investigation) ```text WCO adds padding-top to sidebar tab header bar + inline flex: 0 0 40px on the same element + fixed height: 40px on inner .workspace-tab-header-container → content box can collapse to ~2px when padding-top is 38px → toggle-group icons hidden (left and right docks share tabs-sidebar.svelte) ``` Border rule at `workspace-shell.css` lines ~202–210 excludes `data-pwa-titlebar-hidden="true"`, which WCO always sets. ## Suggested Files or Specs To Inspect - [`packages/workspace/src/lib/styles/workspace-shell.css`](../../packages/workspace/src/lib/styles/workspace-shell.css) — WCO block (~lines 190–340) - [`packages/workspace/src/lib/components/tabs/tabs-sidebar.svelte`](../../packages/workspace/src/lib/components/tabs/tabs-sidebar.svelte) — sidebar tab header markup - [`packages/workspace/src/lib/components/sidebar/sidebar-left.svelte`](../../packages/workspace/src/lib/components/sidebar/sidebar-left.svelte) - [`packages/workspace/src/lib/components/sidebar/sidebar-right.svelte`](../../packages/workspace/src/lib/components/sidebar/sidebar-right.svelte) - [`packages/web/src/pwa-window-controls.ts`](../../packages/web/src/pwa-window-controls.ts) - [`packages/web/src/pwa-window-controls-core.ts`](../../packages/web/src/pwa-window-controls-core.ts) - [`packages/workspace/e2e/pwa-title-bar.spec.ts`](../../packages/workspace/e2e/pwa-title-bar.spec.ts) - [`packages/web/spec.md`](../../packages/web/spec.md) - [`spec/src/20-packages/web/index.md`](../../spec/src/20-packages/web/index.md) ## Validation Commands ```bash pnpm --filter @lapis-notes/web check pnpm --filter @lapis-notes/workspace exec playwright test e2e/pwa-title-bar.spec.ts --project chromium make spec-lint # when spec pages change ``` Manual verification requires **reinstalling/relaunching the PWA** after manifest changes for WCO to activate. ## Follow-up Tasks - Consider adding a visual regression snapshot for PWA WCO chrome (left/right docks + center tabs) once icons are fixed. - Audit ribbon `padding-left` interaction with macOS traffic lights separately from dock tab icons. ## Implementation Summary Explicitly colored WCO sidebar tab icons and tightened the PWA regression to assert painted icon contrast. ## Reopen Reason Sidebar dock icons still respond but are not visibly painted in PWA WCO mode; investigate rendering/color and tighten regression coverage. <!-- backlog:task_id=TASK-WEB-001 source_spec=spec/src/20-packages/web/index.md -->
Sign in to join this conversation.
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
lapis-notes/lapis#141
No description provided.