Skip to content

Expose browser UI theme (read-only + change event) #869

@chrmod

Description

@chrmod

Summary
Standardize a minimal, cross-browser way for extensions to read the browser’s current UI theme (effective light/dark + accent/seed color, plus a few optional flags) and get notified when it changes—so extension UIs can match the browser without shipping full themes.

Motivation: this is inspired by Helmut Januschka’s Omarchy work on coherent browser theming: https://www.januschka.com/chromium-omarchy.html


API proposal

declare namespace browser.theme {
  // Enumerations (list of all values)
  type ColorScheme = "light" | "dark" | "system";
  type ThemeVariant = "neutral" | "tonal_spot" | "vibrant" | "expressive" | "none";
  type Source = "system" | "browser" | "extension";

  interface Theme {
    // Effective scheme in use
    colorScheme: ColorScheme;                    // "light" | "dark" | "system"

    // Accent / seed color used by the browser UI
    // Value: sRGB hex "#RRGGBB" (optionally "#RRGGBBAA"); null/undefined if not supported
    accentColor?: string | null;

    // Optional vendor-mapped variant of the theme palette
    variant?: ThemeVariant;                      // "neutral" | "tonal_spot" | "vibrant" | "expressive" | "none"

    // Whether the UI is rendered in grayscale
    grayscale?: boolean;                         // true | false

    // Present if per-window theming exists; omitted otherwise
    windowId?: number;
  }

  // Query once (optionally for a specific window)
  function query(options?: { windowId?: number }): Promise<Theme>;

  // Fire when any property above changes
  const onChanged: browser.Events.Event<(info: Theme) => void>;
}

Example

const apply = async () => {
  const theme = await browser.theme.query();
  document.documentElement.dataset.scheme = theme.colorScheme;
  document.documentElement.style.setProperty("--accent", env.accentColor ?? "#666666");
};
browser.theme.onChanged.addListener(apply);

Why this helps (brief)

  • Consistent theming for popups/side panels/options without hacks.
  • Works in service workers (no DOM/CSS media queries needed).

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triage: chromeChrome needs to assess this issue for the first timeneeds-triage: firefoxFirefox needs to assess this issue for the first timeneeds-triage: safariSafari needs to assess this issue for the first timetopic: themes

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions