Skip to content

Add dark mode, bookmarks bar mirror, local favicon loading and overall polishing#30

Open
el16z3c wants to merge 4 commits into
zarazhangrui:mainfrom
el16z3c:main
Open

Add dark mode, bookmarks bar mirror, local favicon loading and overall polishing#30
el16z3c wants to merge 4 commits into
zarazhangrui:mainfrom
el16z3c:main

Conversation

@el16z3c

@el16z3c el16z3c commented Apr 20, 2026

Copy link
Copy Markdown

Summary

This PR polishes Tab Out’s new-tab experience with three user-facing improvements:

  • Adds a dark mode with system preference support and a manual toggle
  • Restores quick bookmark access by mirroring Chrome’s Bookmarks Bar inside Tab Out
  • Replaces third-party favicon loading with Chrome’s local extension favicon endpoint

It also removes a few sources of visual friction: the duplicate Tab Out warning banner, the footer branding strip, heavy re-render animations during live updates, and CSP warnings from inline handlers.

Why

Tab Out is already strong as a focused tab dashboard, but replacing Chrome’s new tab page removes some conveniences users expect from the native page. The biggest one is immediate access to bookmarks. Since Chrome does not expose a way for an extension new-tab override to force the native bookmarks bar to appear, this PR mirrors the user’s actual Bookmarks Bar folder via chrome.bookmarks.

Dark mode also matters for a new-tab replacement because users see it constantly, often at night or between tasks. The implementation keeps the existing warm editorial look rather than introducing a separate visual language.

Finally, the previous favicon approach used Google’s favicon service. This PR switches to Chrome’s built-in _favicon endpoint so favicon rendering stays local to the browser cache.

Changes

Dark mode

  • Adds extension/theme.js to apply the saved or system theme before CSS paints
  • Adds a header theme toggle
  • Persists preference in chrome.storage.local
  • Mirrors the theme to localStorage to avoid a flash on new-tab load
  • Adds dark color tokens while preserving the current design language

Bookmarks Bar mirror

  • Adds a compact Bookmarks Bar section under the header
  • Reads the real Bookmarks Bar via chrome.bookmarks
  • Supports bookmark folders as dropdown menus
  • Shows two bookmark rows by default
  • Adds a More / Less control when bookmarks overflow
  • Closes folder dropdowns when clicking outside
  • Ensures only one folder dropdown is open at a time
  • Aligns dropdowns left when near the right edge of the viewport
  • Hides dropdown scrollbars while preserving scroll behavior

Local favicon loading

  • Replaces https://www.google.com/s2/favicons with Chrome’s extension favicon endpoint
  • Adds the favicon permission
  • Uses local browser favicon cache instead of a third-party service

Live refresh and visual polish

  • Adds live refresh listeners for tab changes:
    • create
    • close
    • update
    • move
    • attach/detach
    • replace
    • window focus
  • Adds live refresh listeners for bookmark changes:
    • create
    • remove
    • change
    • move
    • reorder
    • import end
  • Suppresses intro animations after the first dashboard render so repeated tab changes do not cause flicker
  • Removes the duplicate Tab Out cleanup banner
  • Groups multiple Tab Out pages as a normal Tab Out domain card
  • Removes the in-page footer branding strip for a cleaner visual finish

CSP cleanup

  • Removes inline onerror handlers from generated images
  • Removes inline onerror from optional config.local.js
  • Loads optional local config dynamically from app.js
  • Adds a CSP-safe captured image error listener
  • Moves remaining generated inline styles into CSS classes

New permissions

This PR adds:

  • bookmarks: required to read the user’s Bookmarks Bar folder
  • favicon: required for Chrome’s local _favicon endpoint

No server, account, or external API is introduced.

Validation

Manually verified:

  • New tab renders with the existing light theme
  • Dark mode toggle switches theme and persists
  • System dark preference is used when no manual preference is saved
  • Bookmarks Bar renders from Chrome bookmarks
  • Folder dropdowns open, close on outside click, and do not stack
  • Overflowing bookmarks collapse to two rows with a More button
  • Tab groups update when tabs are closed outside Tab Out
  • Bookmark mirror updates after bookmark changes
  • Duplicate Tab Out tabs now appear as a normal Tab Out card
  • No CSP warning from inline handlers

Local checks run:

node --check extension\app.js
node --check extension\theme.js
node -e "JSON.parse(require('fs').readFileSync('extension/manifest.json','utf8')); console.log('manifest ok')"
git diff --check

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