Skip to content

feat(plugins): tint currentColor SVG page icons like host icons - #2314

Merged
joahg merged 2 commits into
block:mainfrom
joahg:joah/plugin-page-icon-current-color
Nov 4, 2026
Merged

joahg merged 2 commits into
block:mainfrom
joahg:joah/plugin-page-icon-current-color

Conversation

@joahg

@joahg joahg commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Problem

A plugin page's icon is a data:image/... URL, and PageIcon renders it as an <img>. Inside an <img>, an SVG's currentColor has no text colour to resolve, so a monochrome plugin glyph comes out black. It can't follow the theme, and it can't follow a navigation tab's hover or selected colour the way host icons do. Plugins end up hard-coding a grey that only matches one state.

Change

  • An SVG data URL that paints with currentColor (whether percent-encoded or base64) is drawn as a CSS mask over bg-current. "Paints" means currentColor is a fill, stroke, stop-color, flood-color or lighting-color value, as an attribute or in CSS. Mentions in comments or in <title>, <desc> or <metadata> don't count, so fixed-colour artwork keeps its colours. It takes the surrounding text colour, so it follows the theme and the row's states like the host's Tabler icons.
  • A hidden <img> copy still watches for load failure, so a broken image falls back to the generic icon as before.
  • Any other image (PNG, or an SVG with fixed colours) renders exactly as today.
  • docs/plugin-architecture.md documents the rule.

Tests

  • PageIcon.test.tsx gains three cases: detection (including malformed payloads), mask rendering, and fallback on error. All 8 tests pass.
  • pnpm check and pnpm lint pass.
  • The full vitest run had timeouts in unrelated files (App.profile, navigation, and others) while another suite was running on the machine. The same files fail the same way on clean main under load, and pass on both when rerun.

Draft until a human tries it in the desktop app.

🤖 Generated with Claude Code

A page icon renders as an <img>, where currentColor has no text colour to
resolve, so a monochrome plugin glyph can't follow the theme or a row's
hover and selected states. Draw an SVG that paints with currentColor as a
mask filled with the text colour instead; other images keep their colours.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Joah Gerstenberg <[email protected]>
@joahg
joahg marked this pull request as ready for review November 3, 2026 22:02
@joahg
joahg requested a review from a team as a code owner November 3, 2026 22:02

@kazemek21 kazemek21 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kyle reviewed this PR and the Nexus review-tracker notes, and approved with the non-blocking comment below.

Posted by Codex (gpt-6.1-sol) on behalf of kylez

Comment thread src/app/shell/PageIcon.tsx Outdated
const svg = /;base64$/i.test(match[1] ?? "")
? atob(payload)
: decodeURIComponent(payload);
return /currentcolor/i.test(svg);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Check paint usage before converting the SVG to a mask

This matches currentColor anywhere in the SVG, including a title or comment. For example, a red-and-blue SVG with <title>currentColor example</title> now becomes a single-color silhouette even though neither fill uses currentColor. Should detection distinguish actual paint usage so fixed-color artwork keeps its colors?

Posted by Codex (gpt-6.1-sol) on behalf of kylez

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Good catch, fixed in 3325230. Detection now strips comments and <title>, <desc> and <metadata> text, then requires currentColor as a paint value: fill, stroke, stop-color, flood-color or lighting-color, as an attribute or in CSS. Your red-and-blue example with a currentColor title and comment now keeps its colours, and a <style> rule stroke: currentColor still masks. Both cases are in the test. One limit remains: an SVG that mixes currentColor with fixed colours still draws as one colour, since a mask can't keep the others.

Ignore comments and title, desc and metadata text, and require
currentColor as a fill, stroke or gradient/filter colour, so fixed-colour
artwork that only mentions it keeps its colours.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Joah Gerstenberg <[email protected]>
@joahg
joahg merged commit d3ca053 into block:main Nov 4, 2026
41 checks passed
gilgtm added a commit that referenced this pull request Nov 4, 2026
* origin/main: (52 commits)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)
  feat(search): browse open channels from a Channels tab in search (#2164)
  perf(relay): page combined replay filters after a reconnect (#2308)
  fix(composer): make native Mac text shortcuts work past link chips (#2390)
  perf(relay): read creator proofs for many channels per filter (#2312)
  fix(channels): let published leave and delete confirm through access loss (#2357)
  fix(media): save native context menu media downloads and hide loopback links on macOS (#2131)
  fix(links): say why a message preview is unavailable, and preview unjoined public channels (#2136)
  test(browser): serve emoji artwork in the reaction hit-area journey (#2138)
  test(browser): click a reply link only after its row settles (#2358)
  fix(agents): restore delegated workflow mentions (#2399)
  feat(identity): always back up keys in managed builds (#2398)
  test(threads): render before checking the reader across activity resizes (#2389)
  ...

Signed-off-by: Gil Birman <[email protected]>
Co-authored-by: Claude <[email protected]>

# Conflicts:
#	src/plugins/author.test.mjs
zandt-square added a commit to zandt-square/buzz-app that referenced this pull request Nov 4, 2026
Co-authored-by: Fizz <fbf1920f313ab37ffa4c517e2437e247fe1423378e077eccc4e29f15625b9918@buzz.block.builderlab.xyz>

* origin/main:
  fix(mermaid): cap diagram output size (block#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (block#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (block#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (block#2314)
  feat(notifications): add a soft notification sound (block#1536)
  feat(agents): let agents propose a profile picture (block#2267)
  fix(plugins): default reminders and workflows off for fresh installs (block#2291)

Signed-off-by: Zandt <[email protected]>
wpfleger96 added a commit that referenced this pull request Nov 4, 2026
…w-tab

* origin/main: (41 commits)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)
  feat(search): browse open channels from a Channels tab in search (#2164)
  perf(relay): page combined replay filters after a reconnect (#2308)
  fix(composer): make native Mac text shortcuts work past link chips (#2390)
  perf(relay): read creator proofs for many channels per filter (#2312)
  fix(channels): let published leave and delete confirm through access loss (#2357)
  fix(media): save native context menu media downloads and hide loopback links on macOS (#2131)
  fix(links): say why a message preview is unavailable, and preview unjoined public channels (#2136)
  test(browser): serve emoji artwork in the reaction hit-area journey (#2138)
  test(browser): click a reply link only after its row settles (#2358)
  ...

# Conflicts:
#	src/buzz-mcp/tools.ts
johnmatthewtennant added a commit that referenced this pull request Nov 4, 2026
Records main as a parent; 5560670 brought in its changes without one.

Signed-off-by: John Tennant <[email protected]>
Co-authored-by: Martha <73923046810b68ae182000e74ef7c444383a907df20f81f2ba1008870a6f45a1@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* origin/main:
  feat(solo): let viewers join read-only spaces (#2301)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)

# Conflicts:
#	src/bundled/claude-code/manifest.json
johnmatthewtennant added a commit that referenced this pull request Nov 4, 2026
Co-authored-by: Martha <73923046810b68ae182000e74ef7c444383a907df20f81f2ba1008870a6f45a1@buzz.block.builderlab.xyz>
Co-Authored-By: Claude Opus 5.5 <[email protected]>

* origin/main: (96 commits)
  test(agents): refuse a real relay workflow mention in the harness kit (#2444)
  fix(agents): catch up every event watch on the kinds it watches (#1852)
  Keep local artifact collections current (#1507)
  feat(members): add several people to a chat in one write (#2010)
  feat(solo): let viewers join read-only spaces (#2301)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)
  feat(search): browse open channels from a Channels tab in search (#2164)
  perf(relay): page combined replay filters after a reconnect (#2308)
  fix(composer): make native Mac text shortcuts work past link chips (#2390)
  perf(relay): read creator proofs for many channels per filter (#2312)
  ...

Signed-off-by: John Tennant <[email protected]>
ravarora2 added a commit that referenced this pull request Nov 4, 2026
…-mentions

* origin/main: (57 commits)
  Keep local artifact collections current (#1507)
  feat(members): add several people to a chat in one write (#2010)
  feat(solo): let viewers join read-only spaces (#2301)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
  feat(agents): let agents propose a profile picture (#2267)
  fix(plugins): default reminders and workflows off for fresh installs (#2291)
  Show all reactors in compact, separate emoji capsules (#2179)
  fix(panels): remember page split widths per workspace (#2264)
  feat(search): browse open channels from a Channels tab in search (#2164)
  perf(relay): page combined replay filters after a reconnect (#2308)
  fix(composer): make native Mac text shortcuts work past link chips (#2390)
  perf(relay): read creator proofs for many channels per filter (#2312)
  fix(channels): let published leave and delete confirm through access loss (#2357)
  fix(media): save native context menu media downloads and hide loopback links on macOS (#2131)
  ...

Signed-off-by: Ravneet Arora <[email protected]>
johnmatthewtennant added a commit that referenced this pull request Nov 4, 2026
…est-work-activity

* origin/main:
  test(agents): refuse a real relay workflow mention in the harness kit (#2444)
  fix(agents): catch up every event watch on the kinds it watches (#1852)
  Keep local artifact collections current (#1507)
  feat(members): add several people to a chat in one write (#2010)
  feat(solo): let viewers join read-only spaces (#2301)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  feat(notifications): add a soft notification sound (#1536)
wpfleger96 added a commit that referenced this pull request Nov 4, 2026
…-service

* origin/main: (73 commits)
  fix(bestie): deleting an agent saves no Bestie record where there was none (#2420)
  fix(unread): never treat agents-audience messages as unread (#1552)
  feat(focus): add an optional Focus plugin that quiets everything except Solo chats (#2277)
  [5/5] Add protection to the Goose harness plugin (#839)
  feat(agents): identify plugins in native hook output (#2299)
  [4/5] Add protection to the Codex harness plugin (#1879)
  feat(search): show member counts on channel results (#2333)
  Fix the mute icon flashing when selecting a channel (#2287)
  feat(agents): open a working agent's transcript from its activity (#2276)
  test(agents): refuse a real relay workflow mention in the harness kit (#2444)
  fix(agents): catch up every event watch on the kinds it watches (#1852)
  Keep local artifact collections current (#1507)
  feat(members): add several people to a chat in one write (#2010)
  feat(solo): let viewers join read-only spaces (#2301)
  [3/5] Add protection to the Claude harness plugin (#1878)
  fix(settings): keep the bottom padding on long sections (#2361)
  fix(mermaid): cap diagram output size (#2231)
  feat(agents): give plugin agent types the Buzz side of a turn (#2364)
  feat(plugins): pin buzz://plugin-install links to a path and commit (#2315)
  feat(plugins): tint currentColor SVG page icons like host icons (#2314)
  ...

# Conflicts:
#	src-tauri/src/host_process.rs
#	src-tauri/src/lib.rs
#	src/bundled/claude-code/claude.ts
#	src/bundled/codex/rpc.ts
#	src/bundled/goose/goose.ts
#	src/bundled/goose/runtime.ts
#	src/bundled/goose/sessions.test.ts
#	src/bundled/goose/sessions.ts
#	src/features/agent-harness/acp/process.ts
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.

2 participants