docs: describe the shell-driven light/dark theming

This commit is contained in:
Eduard Tolosa 2026-07-02 15:38:22 -05:00
parent d75ba7fff6
commit b406970b93
2 changed files with 18 additions and 32 deletions

View file

@ -295,38 +295,24 @@ image.
## Theming
St's CSS engine has no custom properties (`var()`) and no reliable
`!important`, so the light theme is not a runtime-generated stylesheet.
Instead `stylesheet.css` is the dark theme (default, auto-loaded by GNOME),
and `light.css` carries light overrides with every rule scoped under a
`.strata-theme-light` ancestor class -- e.g. dark `.strata-panel { ... }` is
overridden by `.strata-panel.strata-theme-light { ... }`. That scoping makes
each light rule strictly more specific than its dark counterpart, so it wins
deterministically regardless of stylesheet load order.
Light and dark are handled by GNOME Shell's built-in per-variant stylesheet
loading, not by any code in the extension. When it enables an extension the
Shell loads `stylesheet-<variant>.css`, where the variant comes from
`Main.getStyleVariant()` (the shell's own light/dark), and falls back to
`stylesheet.css`; it reloads that sheet when the color scheme changes.
The switch between themes is a single class. `extension.js` loads `light.css`
into the St theme context once at `enable()` (and unloads it on `disable()`),
but loading it changes nothing on screen: its rules are present in the engine
yet match no actors, because nothing carries `.strata-theme-light` yet. The
panel resolves the effective theme from the `theme` setting (`auto` consults
`org.gnome.desktop.interface color-scheme`) and adds or removes that one class
on its root box. With the class present the more-specific light rules win and
the panel is light; with it absent only the base dark rules apply. So
switching is one class toggle on an existing subtree -- instant, off the
ingest/render hot paths, and needing no reload.
Strata ships two sheets and no `stylesheet.css`:
`light.css` is loaded exactly once and the theme context's `changed` signal is
deliberately not used: `load_stylesheet` itself emits `changed`, so reloading
on it feeds back into itself and hits "too much recursion" (it fired on screen
unlock, which restyles widgets). The one caveat of loading once is a full
GNOME Shell *theme* switch (the User Themes extension swapping the whole Shell
theme), which replaces the theme object and drops every dynamically loaded
sheet, including `light.css`. After that, light mode falls back to the dark
base rules until the extension is re-enabled; dark mode is unaffected because
GNOME re-loads `stylesheet.css` itself. This is rare and recoverable, and far
preferable to re-subscribing to `changed`. The ordinary light/dark switch
(including the system Settings light/dark that `auto` follows) is just the
class toggle and is unaffected.
- `stylesheet-dark.css` is the full dark theme (the base).
- `stylesheet-light.css` does `@import url("stylesheet-dark.css")` and then
overrides the colors for a light panel. Its rules follow the import, so they
win by load order.
This is the structure the built-in `window-list` extension uses. Because the
variant tracks the *shell* style, the panel matches the shell chrome: a normal
session prefers dark, so the panel is dark, and it turns light only when the
shell itself is light (a `prefer-light` color scheme, the Classic session, or
high contrast). There is no theme setting and no manual stylesheet loading.
## Wayland clipboard monitor

View file

@ -34,8 +34,8 @@ Unknown MIME types are ignored (a strict allowlist).
**Appearance.**
- Automatic light/dark theme: `Auto` follows the system color scheme; `Light`
and `Dark` force one.
- Light and dark styling follows the GNOME Shell automatically, matching the
rest of the shell UI.
- Configurable panel position (top/center/bottom by left/center/right), width,
and maximum height.
- Optional "move an item to the top" when you paste it.