Skip to content

Draw the icons from the phosphor package that was already installed - #397

Merged
sivert-io merged 1 commit into
mainfrom
claude/client-drop-react-icons
Sep 4, 2026
Merged

Draw the icons from the phosphor package that was already installed#397
sivert-io merged 1 commit into
mainfrom
claude/client-drop-react-icons

Conversation

@sivert-io

Copy link
Copy Markdown
Member

react-icons was 82 MB in node_modules to supply 129 icons, and 126 of them
came from react-icons/pi — which is @phosphor-icons/react's artwork,
repackaged. @gryt/ui already depends on the real one, so both were installed
and only one of them was used.

How

src/lib/icons.tsx exports the same 129 names over the package that was already
there. The names are unchanged on purpose. react-icons puts the weight in the
name (PiGearSixFill) and phosphor puts it in a prop (<GearSix weight="fill">),
so renaming would have meant editing 291 call sites and getting the weight right
at every one. Here it is written once per icon, derived mechanically from the
name it already had.

It also keeps working where an icon is passed as a value rather than rendered —
the settings tabs hold one per row, and a weight prop at the call site is not
available there.

GitHub and Ko-fi have no phosphor equivalent, so their paths live in
src/lib/brandIcons.tsx. Two paths, about 2 KB, lifted from what react-icons
drew before it went.

The trade, which is not free

This costs about 0.4 MB in dist/assets. A phosphor icon carries all six
weights inside one component, so the bundle now contains duotone and thin
variants nothing draws — I counted 120 duotone blocks in the built output.
react-icons had a separate component per weight, so it only ever shipped the one.

Against 82 MB off every checkout and every CI run, I think that is worth it, but
it is a trade and not the free win I described earlier. Roughly 100 KB in a
compressed installer, against 92 MB.

If you would rather not pay it, the alternative is vendoring the 129 single-weight
paths the way brandIcons.tsx does — smallest bundle and smallest install, at
the cost of a generated 129-path file that no longer follows the package. Say the
word and I will swap it.

Verified

Lint, typecheck and an Electron build all pass. No react-icons import remains
anywhere in src. All 129 names mapped with none missing — 100 fill, 18 bold,
11 regular.

Not verified: how they look. This is 79 files of icons and I have not put eyes on
a screen. The weight for each is derived from its old name, so a wrong one would
be a systematic mistake rather than a scattered one, but it is worth a look
around settings and the voice controls.

🤖 Generated with Claude Code

react-icons was 82MB in node_modules to supply 129 icons, all but three of them
from react-icons/pi — which is @phosphor-icons/react's artwork, repackaged.
@gryt/ui already depends on the real one, so both were installed and only one
was used.

src/lib/icons.tsx exports the same 129 names over the package that was already
there. The names are unchanged deliberately: react-icons puts the weight in the
name and phosphor puts it in a prop, so renaming would have meant editing 291
call sites and getting the weight right at each. Here it is written once per
icon, derived from the name it already had. It also keeps working where an icon
is passed as a value rather than rendered, which the settings tabs do.

GitHub and Ko-fi have no phosphor equivalent, so their paths are in
src/lib/brandIcons.tsx — about 2KB, lifted from what react-icons drew.

This costs about 0.4MB in dist/assets, which is real and worth saying: a
phosphor icon carries all six weights in one component, so the bundle now
contains duotone and thin variants nothing draws, where react-icons had a
separate component per weight. Against 82MB off every checkout and every CI run
it is a trade worth making, but it is a trade rather than a free win.

Lint, typecheck and an Electron build all pass, and no react-icons import
remains.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@sivert-io
sivert-io merged commit a6f3e37 into main Sep 4, 2026
3 checks passed
sivert-io added a commit that referenced this pull request Sep 4, 2026
…ed (#398)

generate-tray-icon.mjs imports three icons to render the tray glyphs, and it
imported them from react-icons, which #397 deleted. The release died on
"Generate app icons" before it built anything.

I checked src/ for react-icons imports when removing it and did not check
scripts/. Nothing else would have: lint and tsc do not cover scripts/*.mjs, and
no local build runs icons:generate — it is a release step.

Phosphor puts the weight in a prop rather than the name, and its components are
forwardRef objects, so calling one the way react-icons' could be called throws.
createElement instead.

The rendered PNGs come out byte-identical, which is the check that matters: it
is the same artwork either way.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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