ui: render extension-contributed detail-rail tab icons - #5
Draft
alextomas955 wants to merge 3 commits into
Draft
Conversation
alextomas955
force-pushed
the
ext-tab-icon-resolution
branch
3 times, most recently
from
July 19, 2026 02:08
e4ec9d5 to
e8a7163
Compare
A detail-rail tab contributed by an extension can now render an icon, set via its manifest `icon` string as a bare name (no prefix). The name resolves in order: a host built-in named icon (resolveIcon), then a component the extension registered under that name (e.g. its own brand logo); an unresolved name falls back to the default glyph and warns in dev. Built-in-first, so a shared icon name can never be shadowed by an extension's content component. The extension component is sandboxed in an error boundary and hard-clamped to icon size, so a crashing or oversized icon can neither break the rail nor blow out its layout. Previously an extension tab's icon was dropped, so every extension tab showed the default puzzle glyph. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
alextomas955
force-pushed
the
ext-tab-icon-resolution
branch
from
July 19, 2026 14:36
e8a7163 to
68853bd
Compare
…installed-extensions list Extends the renderExtensionTabIcon resolution (built-in name → extension-registered component → default) introduced for the detail-rail tab to three more host surfaces, so an extension's icon renders everywhere it is represented, not only on its detail-rail tab: - Settings-nav: resolveExtensionSettingsTabIcon returns a registered extension component when the tab's icon name matches one (else the built-in, else the default Plug glyph). - Bulk-action button: ExtensionSelectionActions renders renderExtensionTabIcon(action.icon, …) instead of a hardcoded Puzzle glyph. - Installed-Extensions list: renders the extension's iconUrl next to its name. All backward-compatible (unknown/absent icon → the existing default glyph). Live-verified on a dev instance with an extension registering its own logo component + iconUrl. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
alextomas955
force-pushed
the
ext-tab-icon-resolution
branch
from
July 21, 2026 07:03
6cf3d74 to
21db9a5
Compare
…ss all surfaces
Fold the previously-split icon paths — a registered component for the tab/nav/bulk-action, but a raw
<img iconUrl> for the installed-extensions list — into ONE resolver with a single precedence: host
built-in name → extension-registered component → an <img> for a URL / data-URI / path asset → the
caller's fallback. Every ReactNode surface (detail-rail tab, bulk-action bar, installed-extensions
list) now resolves icons the same way; the settings-nav shares the same precedence (its render site
takes a component, so it keeps resolveExtensionSettingsTabIcon).
- Generalizes renderExtensionTabIcon → renderExtensionIcon with {sizeClass, fallback} options and an
image-source branch.
- The installed-extensions list routes its iconUrl through the resolver instead of a bare <img>.
Co-Authored-By: Claude Opus 4.8 <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.
Summary
Extension-contributed detail-rail tabs can now render their own icon. The tab's
iconvalue resolves in three forms:component:<Name>— the extension's own registered component (e.g. a brand logo), rendered inline so it inherits the tab'scurrentColorlike a native icon;Previously the extension tab's icon was dropped when the rail was assembled, so every extension tab showed the default puzzle glyph.
Safe against a misbehaving or hostile extension: the lucide set is an explicit allowlist (no dynamic
lucide-reactbarrel import, and no way to render an arbitrary component by name); acomponent:icon is sandboxed in an error boundary and hard-clamped to icon size, so a crashing or oversized icon component falls back to the default and cannot break the rail.Linked issue
Closes #
Type of change
AI usage
Testing done & evidence
tsc -bclean;vite buildsucceeds.ui/src/test/extensionTabIcon.test.tsx(5 cases): acomponent:icon renders the resolved component; an allowlisted lucide name renders that glyph; an unknown component, unknown name, and missing name each resolve toundefinedso the default applies.uivitest suite — no new failures.Checklist