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

omartelo merged 1 commit into
mainfrom
feat/theme-aware-app-icon

Conversation

@omartelo

@omartelo omartelo commented Jul 30, 2026 •

Copy link
Copy Markdown
Collaborator

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
3 of 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.
omartelo added a commit that referenced this pull request Sep 5, 2026
The New worktree dialog's name field took a branch name or the task in
plain words. It takes an issue too now — "#128", or the URL copied out of
the browser — looked up through gh on the project's own account.

What that buys is the other half: the session opened on that worktree
finds the issue at its prompt. Number, title, link and body, as one
bracketed paste so the body's newlines are text rather than a run of
Enters, and unsent — the Enter stays the user's, as with the pull request
handoff. Typing the context in by hand was the only way an agent learned
what its worktree was for.

Everything the flow needs already existed: toBranchName slugs the title
and prints the exact branch under the field before anything is created
(#413), CreateWorktree makes an ordinary branch off the chosen base,
writeAtPrompt waits out the setup script and the provider's boot (#447),
and bracketedPaste is why the paste is one block. What is new is one gh
call, one pure module, and a row in the gh message table.

Two refusals, both because the field is a branch name first:

- A bare number stays a branch name. "#" is the marker, so there is one
  field with one meaning rather than a mode to be in.
- A pull request's number is refused, naming the screen that does open
  pull requests. GitHub counts issues and pull requests in one sequence
  and `gh issue view` answers for either; taking it would branch off the
  base under its title instead of checking its head out. The URL is the
  only field in the answer that tells the two apart.

And the reference itself never names the branch, resolved or not: git
accepts "#381" as a branch name, and most shells read the "#" as the
start of a comment, so `git checkout #381` is `git checkout`.

Claude-Session: https://claude.ai/code/session_01GSu6sRs6pBuZHmWaJmuZ3o
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