Skip to content

feat(composer): show skill source icons

MacroscopeApp / Macroscope - UI Consistency failed Aug 19, 2026 in 5m 29s

UI Consistency: 1 issue found

1 finding (new work in 60b3758, "feat(composer): show skill source icons").

  • apps/web/src/components/chat/ComposerCommandMenu.tsx (lines 187-190) — the skill source moved from a visible text label (formatProviderSkillInstallSource) to an aria-hidden Lucide glyph with no text alternative, tooltip, or title. Nothing else in the row carries the scope (label is the display name; description falls back to the provider description), so the App/Repo/Project/Personal/System distinction is dropped from the accessibility tree and reduced to six unlabeled glyphs visually. Suggested fix: give the icon role="img" plus an aria-label from a kind→label map, matching the icon + text-alternative pattern already used elsewhere (AgentsPanel.tsx:188).

An inline review comment with a suggested fix has been posted.

Details

Note

Your check run agent prompt is: .macroscope/check-run-agents/ui-consistency.md
More information about how Check Run Agents work can be found in our Help Center.

Scope reviewed

Merge base a850895 → head 60b3758, limited to apps/web/src/**/*.{ts,tsx,css}. Findings from earlier commits in this PR were already posted in prior runs and are not repeated here; this run focused on the newest commit, whose in-scope web changes are:

  • components/chat/ComposerCommandMenu.tsx (+ new test) — skill source label replaced by icon.
  • components/chat/ChatComposer.tsx, components/ComposerPromptEditor.tsx, components/chat/SkillInlineText.tsx, providerSkillSearch.ts — import-path-only moves to @t3tools/client-runtime/providerSkills.

Checks performed

  • Verified formatProviderSkillInstallSource / providerSkillPresentation have no remaining consumers anywhere in the repo after the move (grep returned nothing), so the rename is safe.
  • Confirmed skill lists are homogeneous (ChatComposer.tsx:1056-1128): the skill trigger only yields skill items and the slash-command trigger only yields command items, so the icon-vs-no-icon split does not misalign rows inside a single list.
  • Confirmed the icon color survives the primitive's color indirection: AutocompleteItem applies [&_svg:not([class*='text-'])]:text-muted-foreground, and the new icon carries text-icon-muted, so it keeps its intended tone; size (size-4) matches PierreEntryIcon.
  • apps/mobile/** changes in the same commit (AppSymbol, ComposerCommandPopover) are outside this check's include patterns and were used as context only.

🔍 Agent activity — 1 tool call

💭 I need to check the diff against head commit 60b3758, reviewing prior flagged issues to see if they're still present and looking for anything new across the changed files. The newest commit since the prior run is "feat(composer): show skill source icons" (60b3758) — I want to check what that change actually did. I should focus my review on the most recent commit's web changes, since earlier commits already have findings posted. Looking at the ComposerCommandMenu.tsx changes for skill source icons, I want to check whether the icon sizing and alignment fit properly within the CommandItem's layout given the baseline-aligned label text. I'm also checking whether slash commands now render without icons while skills render one, which could create visual inconsistency if they ever appear in the same list — though since skills and slash commands are triggered separately ($use vs /), this likely isn't an issue in practice. I confirm titleCaseWords is still used by formatProviderSkillDisplayName, so no dead code there. I also notice a discrepancy between mobile and web icon mappings for repo/project skill sources, but mobile is outside the scope of this review since only apps/web files are included. Now I want to verify whether CommandItem's flex row uses items-center, since that affects whether the icon aligns properly with the baseline-aligned label text. I also want to confirm text-icon-muted is a valid class already used elsewhere in the codebase, then look at the full current state of ComposerCommandMenu.tsx and CommandItem to settle these alignment questions. I'm now looking at the skill icon's muted text color, wondering if AutocompleteItem routes icon color through a shared CSS variable primitive. I want to check the AutocompleteItem base class to see how it handles icon tone across pressed and disabled states before migrating. I'm checking that the icon's muted text color is excluded from the base selector since it already contains "text-", so it keeps its muted styling even in the active state, consistent with how the previous SkillGlyph wrapper behaved—no new issue there. Looking further, the icon alignment and kind-mapping (like "other" → PackageIcon) seem fine, and the web/mobile icon constant naming difference is expected given cross-platform code. But I notice a real accessibility concern: the source label used to be visible text conveying things like "App" or "Personal," and now it's just an icon marked aria-hidden="true" with no tooltip or accessible name—so that information is now invisible to screen readers and unlabeled visually, which is a genuine regression. The fix would be to give the icon a proper accessible label, like swapping aria-hidden="true" for role="img" with an aria-label set to the source text, though I need to be careful since the existing test explicitly checks that "App" doesn't appear in the output—so I need to make sure any accessible label doesn't conflict with that test's intent, which seems to be about the visible label being removed, not about accessibility entirely. I want to check how other icon-only indicators in this codebase handle accessibility, like PierreEntryIcon, to see if there's an established convention using tooltips or screen-reader-only text I should follow instead of inventing a new pattern. I should also scan for other clear-cut findings in the recent commits that haven't been flagged yet, including a change in ComposerPromptEditor.tsx where a class name constant was renamed. I'm also verifying whether titleCaseWords and normalizePathSeparators are still actually used after the refactor in providerSkills.ts, and confirming they're both still referenced elsewhere so they aren't dead code. Since prior findings have already been posted, I want to avoid repeating them and focus on what's new. Since the last run, the only meaningful change is commit 60b3758, and most files touched there are just import path updates — the real substantive change is in ComposerCommandMenu.tsx with its icon handling. I'm considering two potential issues there: an icon-only source indicator that's aria-hidden with no accessible name or tooltip, which could be an accessibility regression compared to the previous text label, and an inconsistency where slash-command items render no icon while skill items render a 16px icon, creating visual misalignment when both appear together. I'm checking whether skill and slash-command items actually mix in the same list — tracing through the trigger logic, $ triggers skills only and / triggers slash-commands (built-in and provider), so they shouldn't mix within a single list, meaning the icon inconsistency is consistent within each list type rather than a cross-list problem. I still want to verify whether the skill trigger list could somehow include provider-slash-commands by checking the composer logic further. Skill lists check out as homogeneous. On accessibility, the source labels used to be visible text but now appear as decorative, aria-hidden icons with no tooltip or screen-reader text — that's a real violation of preserving accessibility semantics during migration, since a meaningful label got replaced by an unlabeled icon. I want to make sure this isn't just flagging a design preference, though — the commit's whole point is to swap labels for icons, and I shouldn't penalize aesthetic choices. But icon-only meaning without an accessible name is genuinely an a11y gap, not aesthetics, so I think this finding holds, even if it's a softer one. I should check whether other meaning-carrying icons in the codebase follow a similar pattern without sr-only text, and whether the skill source is still shown as a text label elsewhere, like in settings, to see if there's now an inconsistency between surfaces. I'm checking size consistency between the skill source icon and label text, noting the icon went from size-3.5 to size-4, and want to compare this against the PierreEntryIcon sizing. The skill source icon is meaning-bearing but unlabeled, which is an accessibility gap. I also notice FolderIcon is reused for both "project" skill source and directory path entries within the same menu, so the same glyph carries different meanings depending on context. I'm also checking whether the active/highlighted state affects icon color — it stays text-icon-muted, but that's pre-existing behavior, not a new issue. I want to see if the repo has a convention for icon-only status indicators, like using sr-only spans elsewhere, so I'll search for that pattern. I found a good precedent in the codebase — AgentsPanel pairs an icon with a screen-reader-only label span, which confirms there's an established convention for this pattern and gives me a concrete fix to cite. Let me check that file around lines 180-190 to reference it properly. This seems like a reasonable precedent for icon-conveyed status paired with screen-reader text. Checking the item's description fallback logic, I confirm that for most skills the source isn't otherwise conveyed, so it really is icon-only information—this likely falls under preserving accessibility and interaction semantics during migration. I'll plan to post one inline comment on ComposerCommandMenu.tsx near the SkillSourceIcon function. Scanning for other issues, I notice the icon sizing changed from a smaller glyph to a raw size-4 box, but the row height and padding still look fine, and a few icon import overlaps between components seem harmless. I also note that mobile and web diverge slightly in how they map scope to folder icons, but since I can only comment on web files, I'll just mention this discrepancy in the summary rather than as an inline comment. I should double-check that the LucideIcon type import is valid from lucide-react, and search the repo for any other consumers of the removed formatProviderSkillInstallSource function before finalizing. Doing a final sweep of the PR for anything still unflagged, checking files like composerInlineChip.ts and ComposerPendingApprovalPanel which already have findings noted. I'm also verifying the new test file's assertions don't conflict with existing expectations. For the sr-only label fix, I'll propose keeping the icon aria-hidden and adding a sibling sr-only span with the source label derived from a small map, while flagging that the test's assertion needs to scope to visible text rather than the whole markup. I'm now figuring out exactly which diff line to attach this comment to — settling on the SkillSourceIcon function around lines 187-189 since those are within the added hunk and valid for a review comment. Drafting the suggestion block to add a label map and render the sr-only span alongside the icon... but I should double check the existing test doesn't assert against the literal string "App" appearing in the markup, since the sr-only label text would include it. Writing the suggestion diff... I need to figure out exactly which lines to replace, since the label map needs to be declared before the function. I'll target lines 187-190 for the replacement, then decide whether to mark this review as a failure given it's a real finding, and post the comment.

1. modify_pr — UI consistency — 1 finding apps/web/src/components/chat/ComposerCommandMenu.tsx: the skill source moved from a text label to an aria-hidden icon with no text alternative, so the source is no longer exposed to assistive tech and has no visible name either.


Agent Credits: 173 credits