Skip to content

fix(ext): decouple URN-bar theme from the app theme (#459)#129

Merged
MichaelTaylor3d merged 1 commit into
mainfrom
fix/urnbar-theme-decouple
Jul 12, 2026
Merged

fix(ext): decouple URN-bar theme from the app theme (#459)#129
MichaelTaylor3d merged 1 commit into
mainfrom
fix/urnbar-theme-decouple

Conversation

@MichaelTaylor3d

Copy link
Copy Markdown
Contributor

Summary

Closes DIG-Network/dig_ecosystem#459 (builds on #429).

The URN-bar light/dark theme switcher (#429) painted from — and its toggle wrote directly to — the
main app theme state (uiSlice.theme / persisted wallet.settings.theme, #111). Toggling the bar's
paint therefore also flipped the whole extension's product theme, and vice versa: an unintended
coupling between two conceptually separate preferences.

This gives the URN bar its OWN independent, persisted theme preference, fully decoupled in both
directions:

  • TOOLBAR_THEME_KEY = 'toolbar.theme' (src/lib/toolbar.ts) — a FLAT chrome.storage.local
    key, same idiom as the existing TOOLBAR_ENABLED_KEY ('toolbar.enabled') — never a field inside
    the wallet.settings blob the app theme lives in. Modes: light / dark / system
    (TOOLBAR_THEME_MODES), default system (TOOLBAR_THEME_DEFAULT) — before this fix the toolbar
    ALWAYS followed prefers-color-scheme with no persisted pref at all, so defaulting to system
    reproduces that exact first-run look (no jarring migration).
  • New pure resolvers in the shared core: resolveToolbarTheme(mode, prefersDark) (system → OS signal,
    light/dark pass through) and nextToolbarTheme(effective) (toggle to the explicit opposite).
  • DigToolbar.tsx (built-in fullscreen bar) now reads/writes this key via useStorageValue
    instead of useAppSelector(s => s.ui.theme) / dispatch(setTheme(...)) +
    updateWalletSettings({theme}). The toggle button, its data-testids, aria-label, and visual
    behavior are unchanged — only the underlying state it drives has moved.
  • dig-toolbar.ts (injected content-script bar) previously had NO persisted theme state at all —
    it just read prefers-color-scheme at mount time. It now reads the SAME toolbar.theme key
    (default system) alongside the existing toolbar.enabled read, resolves it the same way, paints
    the same shared TOOLBAR_PALETTES, and live-repaints on a chrome.storage.onChanged event for
    EITHER key — so it stays in lockstep with the fullscreen bar's switcher without gaining a Redux
    store. Also added a data-theme attribute on its root (mirroring the built-in bar) for testability.

Verified

  • Gitnexus blast radius: impact() on toolbarTheme/DigToolbar returned stale-index misses (the
    theme feature postdates the last index build), so blast radius was confirmed by manual grep across
    the repo: DigToolbar is mounted only in App.tsx; @/lib/toolbar is imported only by
    HeaderToolbarToggle.tsx, DigToolbar.tsx, dig-toolbar.ts, and background/index.ts (which only
    uses the unrelated TOOLBAR_ENABLED_*/TOOLBAR_TOGGLE_COMMAND exports); uiSlice.theme/setTheme
    is touched only by uiSlice.ts, AppFooter.tsx (app-theme control, untouched), useAppliedTheme.ts
    (untouched), and DigToolbar.tsx (the coupling fixed here). gitnexus detect_changes on the staged
    diff reports risk_level: low, 0 affected processes. tsc --noEmit clean; eslint src 0 errors.
  • Unit (Vitest, TDD red→green): 29 new/updated assertions in src/lib/toolbar.test.ts for the new
    primitives (TOOLBAR_THEME_KEY/_DEFAULT/_MODES, isToolbarThemeMode, resolveToolbarTheme,
    nextToolbarTheme). DigToolbar.test.tsx rewrites the #429 describe block to prove the
    decoupling: clicking flips the bar to dark and persists under the toolbar's OWN key — NOT wallet.settings.theme and toggling the MAIN app theme (uiSlice.theme) does NOT move the URN-bar theme (reverse-direction proof), plus a keyboard-operability test
    (is keyboard-operable: focusing + pressing Enter flips the theme). Full suite: 239/239 test
    files, 2474/2474 tests green
    ; coverage 96.12% statements / 87.55% branches (repo floor is 80%).
  • Playwright (built extension, real headless Chromium, playwright.sw.config.ts): all
    25/25 tests green in e2e/sw/node-serve-omnibox-toolbar.spec.ts, including:
    • #459 — the URN-bar theme is independent of the app theme, proven in BOTH directions — drives the
      REAL AppFooter theme-select control and the REAL URN-bar toggle button, diverges them
      (app=light, toolbar=dark) and confirms neither moves the other.
    • #459 — the INJECTED content-script toolbar reads the SAME independent theme key, live, and never touches the app theme — flips toolbar.theme from the SW, confirms the injected bar (on an
      ordinary web page) repaints live with no reload, and that wallet.settings was never written.
      Screenshots: toolbar-injected-theme-{dark,light}.png (visually inspected — bar dark/light
      against the unaffected fixture page).
    • #429/#459 — the URN-bar theme toggle flips light↔dark, persists under its OWN key, and survives reload — WITHOUT touching the app theme (rewritten from the old, now-incorrect assertion that a
      toolbar toggle click flips document.documentElement.dataset.digTheme).
    • #429/#459 — screenshot the URN-bar theme toggle in both light + dark (desktop/mobile) (rewritten
      to drive the toolbar's own key, not the app theme) — screenshots visually inspected, no layout
      regressions.
    • One pre-existing, unrelated flake (#289 — local node reachable...) reproduced on first run and
      passed in isolation and on re-run — confirmed unrelated to this change (timing flake in the fixture
      harness, not a regression).
  • A11y (§6.6): the toggle is a real <button> with a stable localized aria-label
    (toolbar.theme.toggle, unchanged, all 14 locales), aria-pressed state, and is keyboard-operable
    (Enter/Space) — covered by both the unit keyboard test and (implicitly, via .click()) e2e.

Cross-repo

SPEC.md §5.5 rewritten: the "two mounts choose WHICH palette differently, by design" section (which
described the OLD entangled behavior) is replaced with a description of the independent
toolbar.theme key, its default, and the explicit no-cross-write guarantee; the theme-toggle bullet
now states it writes ONLY toolbar.theme. Checked docs.dig.net for existing content describing this
toggle (none — #429 never documented the URN-bar theme switcher there) — no staleness introduced, no
other-repo changes needed (matches the issue's own cross-repo scope).

Bump

Patch 1.95.01.95.1 — a fix: restoring the intended isolation between two existing
preferences; no new public API/behavior surface (the toggle button, its test ids, and its visual
behavior are all unchanged from the user's perspective — only the state plumbing underneath moved to
its own key).

Co-Authored-By: Claude noreply@anthropic.com

The URN-bar light/dark switcher (#429) wrote uiSlice.theme /
wallet.settings.theme directly, so toggling the bar's paint also
flipped the whole extension's product theme. Give the bar its OWN
independent, persisted preference (TOOLBAR_THEME_KEY = 'toolbar.theme',
a flat storage key like TOOLBAR_ENABLED_KEY; modes light/dark/system,
default system so first-run look is unchanged) resolved by
resolveToolbarTheme/nextToolbarTheme in the shared toolbar.ts core.

Both mounts now read/write ONLY this key: DigToolbar.tsx via
useStorageValue, and the injected dig-toolbar.ts content script via
chrome.storage.local + a new storage.onChanged branch (it previously
only followed prefers-color-scheme with no persisted pref at all) —
so the two stay in lockstep without ever touching the app theme.

Patch bump (1.95.0 -> 1.95.1): a fix restoring intended isolation
between two prefs, no new public surface.

Co-Authored-By: Claude <noreply@anthropic.com>
@MichaelTaylor3d MichaelTaylor3d merged commit 96baa90 into main Jul 12, 2026
8 checks passed
@MichaelTaylor3d MichaelTaylor3d deleted the fix/urnbar-theme-decouple branch July 12, 2026 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant