Skip to content

Render plugin nav icons supplied as a file path - #19794

Merged
brandonkelly merged 5 commits into
6.xfrom
bugfix/plugin-nav-icons
Oct 2, 2026
Merged

brandonkelly merged 5 commits into
6.xfrom
bugfix/plugin-nav-icons

Conversation

@brianjhanson

Copy link
Copy Markdown
Contributor

A plugin's control panel nav item never showed its icon.

Cause

A plugin's icon arrives as an absolute filesystem path — cpNavIconPath() returns the path to its own icon-mask.svg — and getCpNavItem() puts that in the nav item's icon field.

But icon is handed to craft-nav-item as an icon name (ActionList.vue, navAttrs()), so the path gets looked up as though it were a system icon and resolves to nothing. The nav's only other route for an icon is iconSvg, which it renders as inline markup — and nothing converted one to the other.

This isn't specific to any one plugin, or to the Yii adapter: InteractsWithCp::getCpNavItem() does the same thing for plugins written for Craft 6, so no plugin's nav icon could render. Craft's own nav entries pass real names ('plug', 'custom-icons/graphql'), which is why only plugins looked broken.

Fix

Navigation::normalize() — which already walks every item and recurses into subnavs, and runs inside buildTree() so the result lands in the cached tree rather than re-rendering per request — now renders a path-shaped icon through Icons::svg() and moves the result to iconSvg.

Icons::svg() already handled both shapes, so this is only wiring the two together.

Deliberately narrow in two ways:

  • Only values ending .svg are touched, so the named icons the rest of the nav uses stay names. Inlining every icon would weigh down a tree that's cached and shared across every control panel page.
  • An unreadable file leaves the item alone. Icons::svg() logs and returns an empty string for anything it can't read, so a missing path keeps whatever was there rather than substituting a blank icon.

No plugin has to change, whether it was written for Craft 6 or comes through the Yii adapter — both arrive as a path in the same field.

Verification

path icon    -> icon: NULL, iconSvg: rendered 284 bytes, starts <svg
named icon   -> icon: 'plug', iconSvg: NULL
missing file -> icon kept: '/nope/missing.svg', iconSvg: NULL

361 tests across tests/Unit/Cp (including NavigationTest) and tests/Feature/Integration pass, along with Pint and PHPStan. Those suites were run against this change in a full checkout; this branch's working copy has no vendor/, so only php -l and Pint were run here directly — the applied hunk is byte-identical.

Worth noting for anyone testing by hand: getTree() is cached with a one-hour TTL, so an icon may not appear until the nav cache turns over. Navigation::flushCache() forces it.

@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown

📚 Storybook previews

@craftcms/ui — open Storybook

No changed components detected in this Storybook.

resources/js — open Storybook

No changed components detected in this Storybook.

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown

This PR had conflicts with 6.x. Claude attempted an automatic resolution and pushed a merge commit. Please review the merge commit carefully before approving/merging.

Claude's response

I resolved the one conflict, in CHANGELOG.md's "Unreleased" section, and committed the merge as 45f638e. It has not been pushed.

Both sides had edited the same list. 6.x reordered the existing entries and added two new ones: "Improved consistency of control panel breadcrumbs" (#19786) and the craft:up migrations-table fix (#19796). This branch's version held the same shared entries in the old order, plus one new entry for the plugin nav icon fix (#19794).

I used 6.x's ordering and wording for the whole list. Its version also capitalizes "Axios" in the Craft.sendActionRequest() entry. I then added this branch's #19794 entry with the other "Fixed a bug…" entries, right after the users' breadcrumb chips fix. No entry from either side was lost and nothing is duplicated.

There was nothing ambiguous, so I didn't add any CONFLICT-REVIEW comments. No code files had conflicts.

@brandonkelly
brandonkelly merged commit 0af5701 into 6.x Oct 2, 2026
20 checks passed
@brandonkelly
brandonkelly deleted the bugfix/plugin-nav-icons branch October 2, 2026 22:48
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