Skip to content

feat: give the app icon a mark that inverts with the colour scheme - #128

Merged
omartelo merged 1 commit into
mainfrom
feat/theme-aware-app-icon
Jul 30, 2026
Merged

feat: give the app icon a mark that inverts with the colour scheme#128
omartelo merged 1 commit into
mainfrom
feat/theme-aware-app-icon

Conversation

@omartelo

@omartelo omartelo commented Jul 30, 2026

Copy link
Copy Markdown
Owner

The purple flame is replaced by a monochrome one that reads on either background: white on dark, black on light.

What changed

Asset Was Now
frontend/public/appicon.svg new; traced vector of the mark, carrying its own prefers-color-scheme rule
frontend/public/appicon.png, build/appicon.png purple flame, 216 KB white flame, transparent, 1024×1024, 52 KB
frontend/public/appicon-light.png new; black flame, same mask
build/windows/lich.ico purple white, regenerated at 256 · 128 · 64 · 48 · 32 · 16
frontend/index.html PNG icon link SVG icon link
README.md <img> <picture> with a prefers-color-scheme source

Why an SVG for the favicon

Chrome ignores the media attribute on <link rel="icon">, so a pair of PNGs would not flip in the shell we
actually run in. An SVG carrying the media query in its own stylesheet does, and it is 3 KB.

The mark was traced from the source bitmap rather than thresholded — the alpha comes from the luminance
channel, so the antialiasing survives. The flame is normalised to 80% of the canvas height, matching the 78%
the old icon sat at.

Known ceiling

The launcher, dock and taskbar icon is a single image: neither the hicolor icon spec nor .ico carries a
theme variant. Those ship the white flame, which is right for the dark panels most desktops default to and
wrong for a light one. Giving that icon a background or a solid colour is the escape hatch if it bites.

Test plan

  • biome check clean (12 warnings — the standing a11y backlog)
  • tsc --noEmit + vite build green; appicon.svg, appicon.png, appicon-light.png land in dist/
  • The media query fires: headless Chromium driven over CDP with prefers-color-scheme emulated renders
    appicon.svg as a black flame under light and a white one under dark.
  • README survives GitHub's sanitiser: gh api /markdown keeps the <picture> / <source media> pair and
    wraps it in GitHub's own <themed-picture>. Both PNGs return 200 at their raw URL on this branch.

Not verified, and out of reach of a headless screenshot: whether the --app window and taskbar icon
re-renders when the system scheme flips while the app is running, as opposed to picking the right variant at
load. Worth a look in a real window before merge.

The purple flame is replaced by a monochrome one that reads on either
background: white on dark, black on light.

The window and tab icon is now an SVG carrying its own
prefers-color-scheme rule, so the browser draws the variant that matches
the scheme — Chrome ignores `media` on a PNG icon link, and that is the
shell we run in. README picks its variant the same way.

The launcher, dock and taskbar icon has no such lever: neither the
hicolor spec nor .ico carries a theme variant, so those ship the white
one.
@omartelo
omartelo force-pushed the feat/theme-aware-app-icon branch from a628966 to 3c86901 Compare July 30, 2026 14:53
@omartelo
omartelo merged commit 6c3e94c into main Jul 30, 2026
3 checks passed
@omartelo
omartelo deleted the feat/theme-aware-app-icon branch July 30, 2026 15:00
@omartelo omartelo mentioned this pull request Jul 30, 2026
4 tasks
omartelo added a commit that referenced this pull request Aug 6, 2026
The .syso the Windows binary links still carried the purple meteor mark
retired in #128, which updated build/windows/lich.ico and the PNGs but
not the resource generated from them. Nothing in the repo said how that
resource is produced, so there was nothing to remind the reskin.

The executable's icon is what Windows draws in the two places the
Chromium window never covers: the Start Menu shortcut, which the
installer points at lich.exe with no IconFilename of its own, and the
taskbar button of the file picker — ncruces/zenity runs an in-process
IFileOpenDialog there, so the dialog is a window of lich's own.

Regenerate the resource from lich.ico and add `task icons:windows`, so
the next icon change has a recipe to run instead of a binary to
remember.
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