Automic dark mode#346
Merged
maurerle merged 7 commits intofreifunk:mainfrom May 10, 2026
Merged
Conversation
maurerle
reviewed
Apr 19, 2026
3 tasks
Member
|
I merged main into this to use the svg icons folder as well: Can you pleas update this PR to this? |
Add button.theme.{light,dark,auto} across en/de/fr/cz/ru/tr.
Each label names the current theme and the next click's target
("Light (next: dark)"), so sighted and screen-reader users get
the same state-plus-action signal.
Polyglot is configured with allowMissing: true, so missing keys
would render as raw dotted strings to non-English users -- all
locales need them.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Theme is currently implied by the selected tile layer (the baselayerchange handler in map.ts adds theme_<mode> on <html>). Make theme an explicit user preference so dark mode is reachable without switching the basemap and persists across sessions. The implicit coupling is removed in the next commit. The new module lib/theme.ts owns theme state, storage, DOM class mutation, and matchMedia subscription. Exposes initTheme, getTheme, cycleTheme, and themeIconSVG. Persist the user's choice in localStorage under meshviewer.theme. All access is wrapped in try/catch so sandboxed iframes, Safari private mode, and file:// contexts fall back to in-memory state. On apply, toggle the theme_night class on <html> and dispatch a "themechange" CustomEvent on document.documentElement so the map's label canvas can re-render without a direct dependency on this module. Auto mode subscribes to prefers-color-scheme so the UI flips live without a reload. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Remove the theme_* class manipulation from the baselayerchange handler. Theme is now a user preference owned by lib/theme.ts and no longer implicitly tied to tile-layer config. The label canvas derives colors from getComputedStyle on body, so it still needs to refresh on theme change. LabelLayer subscribes to the themechange CustomEvent in its onAdd / onRemove hooks, tying listener lifetime to the layer; map.ts keeps no theme-related code. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add a button that cycles light -> dark -> auto. The icon shows
the current theme; the aria-label carries "Light (next: dark)"
from the locale file, giving screen-reader users the same
state-plus-action signal as the icon.
The aria-label also feeds the styled tooltip via the existing
::after { content: attr(aria-label) } rule on .content button.
No title attribute is set, which would stack a native browser
tooltip on top of the styled one.
Call initTheme() before rendering so the matchMedia listener
and storage state are live before the first click.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Read the stored theme preference synchronously in <head> and set theme_night on <html> before any CSS resolves, so dark-mode users don't see a light flash while Vite loads the main bundle. Read-only and wrapped in try/catch; the theme module still owns writes and listeners. If localStorage throws (sandboxed iframes, storage disabled, some file:// contexts), a nested try/catch falls back to prefers-color-scheme alone, so OS-dark users still get the correct first paint. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move sun/moon/auto SVGs from theme.ts string constants into assets/icons/svg/ and register them in icon.scss. The toggle button now swaps ion-<state> via classList instead of injecting innerHTML, dropping themeIconSVG() and the svg-sizing rule in _button.scss — the shared ion-* ::before pipeline handles loading and sizing already. Co-Authored-By: Grische <github@grische.xyz> Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Align the CSS class name with the public-facing terminology introduced earlier in this branch (light / dark / auto). The DARK_CLASS constant in lib/theme.ts and the inline pre-paint script in index.html now use "dark"; scss/night.scss is renamed to scss/dark.scss for symmetry. No behavior change. The class is set only by lib/theme.ts and the pre-paint script; nothing else consumed the old name. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This changes the current behaviour and decouples dark mode from the map layer.
The user can now select either dark, light or automatic by using the button on the top right.
The automatic theme switches depending on the system theme (without a reload).
Motivation and Context
As the map layer is not saved, it bothered my how my browser switched between dark and bright mode somewhat random.
This mode behaves similar to other apps (e.g. Github) and should be a lot more intuitive.
How Has This Been Tested?
Tested locally in Chrome with all variants of Themes.
Screenshots/links:
See it live here: https://map.ffmuc.net/
Checklist: