Repository navigation
UI Consistency: 1 issue (4 call sites)
apps/web/src/components/Sidebar.tsx — the new projectFaviconSource === null branches render raw lucide icons instead of ProjectFavicon's fallback, dropping the primitive's text-icon-muted (themed --icon-muted / --app-theme-icon-muted) tone, and shrink-0 in the slim-row case.
Before this PR these rows always rendered ProjectFavicon (with cwd={projectCwd ?? ""}), so the no-favicon state was drawn by ProjectFaviconFallback as cn("size-3.5 shrink-0 text-icon-muted", className). The bare icons now inherit the row's text color, so the placeholder renders at full row-text strength and no longer follows the runtime theme's icon tone.
Affected lines (inline comments posted with suggested fixes):
- L532 — draft row
FolderIcon, missingtext-icon-muted - L1225 — slim thread row
MessageSquareIcon, missingtext-icon-mutedandshrink-0 - L1369 — thread row
FolderIcon, missingtext-icon-muted - L1671 — search result
MessageSquareIcon, missingtext-icon-muted
The tooltip fallback (L303) sets stroke-muted-foreground explicitly, so it is visually equivalent and was not flagged.
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 examined
apps/web/src/components/ProjectFavicon.tsx(compared against merge base324ddda)apps/web/src/components/Sidebar.tsxapps/web/src/components/CommandPalette.tsxapps/web/src/components/LegacySidebar.tsxapps/web/src/components/settings/ProjectSettingsPanel.tsxapps/web/src/components/ProjectFavicon.test.tsx- Context only (out of scope):
apps/mobile/**,docs/user/project-settings.md
No findings on
projectKeyplumbing throughLegacySidebar,ProjectSettingsPanel, andCommandPalette'sProjectWithFaviconSource— these preserve the existing class contracts (ITEM_ICON_CLASS,size-4 shrink-0) and do not reconstruct any core primitive.- Spreading
ProjectFaviconSourceintoProjectFaviconkeepsclassName/fallbackIconat the call site, so geometry and contextual color remain call-site owned. key={projectKey}instead ofkey={cacheKey}keeps the image mounted across URL churn; the hidden preload image plusdisplayedSrcswap preserves the previous no-flicker behavior, and load-error handling still clears the shared map.- No CSS/Tailwind ownership, theme-variant, scroll/virtualization, or emitted-selector changes are introduced by this PR.
Verification suggested for the author
A focused render test (or existing ProjectFavicon.test.tsx extension) covering the null-source branch would lock in the fallback tone, since the change is behavioral prop-defaulting rather than a purely visual class migration.
🔍 Agent activity — 1 tool call
💭 I'm checking the web app changes, focusing on files like ProjectFavicon, Sidebar, CommandPalette, LegacySidebar, and ProjectSettingsPanel to see what's actually been modified. I'm examining how ProjectFavicon's key changed from cacheKey to projectKey, which means the component now stays mounted across URL changes instead of remounting—so I need to check whether the displayedSrc state still updates correctly when the favicon src changes without a remount. Looking at Sidebar.tsx, I notice the fallback rendering changed from always using ProjectFavicon with a fallbackIcon prop to a conditional inline fallback. The original fallback applied consistent classes like size-3.5, shrink-0, and text-icon-muted, but the new inline MessageSquareIcon fallback seems to lose some of those styling classes, which could be a visual regression worth flagging. I'm finding the same pattern repeated elsewhere — FolderIcon and MessageSquareIcon instances in SidebarDraftRow and SidebarSearchResultRow also dropping the
text-icon-mutedclass, so these icons could lose their intended muted tone unless surrounding context supplies it. I should check the actual file to confirm whether nearby color classes compensate for this before flagging it as a real regression. I'm comparing the old fallback styling in ProjectFavicon against the new raw icon usage — the new version seems to drop theshrink-0andtext-icon-mutedclasses that the old SidebarThreadRow fallback had, so I need to check whether that old code path was even being hit. Looking at the existing FolderIcon pattern at line 3488, it already uses a bare fallback withouttext-icon-muted, so this might just match an established repo convention rather than being a real regression. I should check the parent span's classes too, since the SidebarThreadRow icon sits inside a span that already hasshrink-0, which could make the missing class on the icon itself a non-issue. The real question is the color tone: if the fallback icon now inheritscurrentColorinstead of a muted tone, that's a visible shift wheneverprojectFaviconSourceis null, which happens when a thread's project isn't found in the project groups map. I need to weigh whether this edge case occurs often enough to flag as a genuine inconsistency. I'm tracing the four affected sites — the draft row FolderIcon, the two MessageSquareIcon instances, and the other FolderIcon — to see how severe the muted-tone loss actually is in each surrounding context, starting with the SidebarSearchResultRow. Since--icon-mutedis a runtime theme token, removingtext-icon-mutedfrom these fallback icons means custom themes lose that intended tone — this is a real violation introduced by the changed lines, since the new else branches render raw icons without the color indirection that contextual icons need to retain. The fix is simple: reuse ProjectFavicon's fallback styling by addingtext-icon-muted shrink-0to the raw icons, or just keep rendering the shared fallback component. I note the pre-existing bare FolderIcon pattern elsewhere isn't a new finding, and the tooltip fallback is fine since it sets stroke explicitly which overrides visually the same way. Checking the other changed files — CommandPalette, LegacySidebar, ProjectSettingsPanel — they just pass projectKey through, so those are fine. In ProjectFavicon.tsx itself, the key changed from cacheKey to projectKey, which could matter: since the component stays mounted across src changes for the same project now, I need to check whether the useState initializer that reads loadedProjectFavicons at mount still behaves correctly when src updates without remounting. The displayed src should stay on the old value until the new one loads, which gives a smooth transition — that's fine. But I notice a subtler issue: there's a render-phase mutation deleting an entry from the module-level favicon cache when the favicon is missing, which is a side effect happening during render rather than in an effect. The test comments suggest this is intentional, to make cache invalidation not depend on the component staying mounted, but mutating shared state during render is risky under StrictMode or concurrent rendering. I'm weighing whether this counts as a UI-consistency finding versus a general React correctness concern — it leans more toward the latter, so I probably won't flag it as a failure, especially since the cache write itself happens safely inside the onLoad handler. Multiple ProjectFavicon instances sharing the same projectKey but different cwd intentionally share the loaded src for group sharing, which seems fine, and per-instance className/size differences aren't a problem either. I'm now checking whether a missingshrink-0class on a parent span around line 1225 could cause a layout issue, so I want to look at the surrounding lines to confirm. I'm noticing that when the icon falls back to no source, it now picks up the current text color instead of the muted icon token, which is a visible regression. I'm checking whether this null-source state is actually reachable — tracing whether a thread's projectId could reference a project missing from the current project groups, like a filtered-out project. This does seem reachable, for instance while projects are still loading, and I'm finding the same muted-tone loss across four call sites including the SidebarDraftRow fallback icon. It's a modest but legitimate consistency regression rather than just an aesthetic nitpick, so I'm leaning toward flagging it with inline comments rather than letting it pass silently. Now I want to double check the CommandPalette changes, particularly howProjectWithFaviconSourceandfaviconSourceare being passed through in OpenCommandPaletteDialog, to make sure that wiring is correct before finalizing my findings. Checking LegacySidebar and ProjectSettingsPanel, I see they just pass projectKey through. I'm wondering if there's a mismatch where projectKey comes from one member but cwd/environmentId comes from another, causing the asset URL to reflect a different environment than what's displayed — that seems to be the intent. I also notice SidebarThreadRow's projectFaviconSource now uses the group representative's environmentId rather than thread.environmentId, which changes how the favicon was previously sourced. For a thread on environment B whose group representative is environment A, the favicon would now come from A — but that's intentional per the PR, meant to give every checkout in the group the same icon source, not a consistency bug. I'm also confirming the ProjectFavicon key change using projectKey causes a clean remount when switching projects, and that two instances rendering the same project with different sizes won't conflict since keys are scoped per parent. I check that a stale cached src with an expired asset token would just trigger the image's onError handler to clean it up properly, and there's no Tailwind or CSS ownership issue here. My real finding is the fallback icon styling divergence — in SidebarDraftRow, the FolderIcon fallback loses thetext-icon-mutedtoken and instead inherits the row's text color, making it more visually prominent than intended across themes. This is a legitimate but low-severity issue, not severe enough to warrant a hard failure, so I'm leaning toward flagging it with an inline comment rather than failing the check outright. I want to double-check whether this is actually a regression though, since there are pre-existing bare icons elsewhere in the codebase (like the project-scope menu trigger) that also skiptext-icon-muted. That weakens the consistency argument somewhat, but since these specific rows previously rendered with the muted styling, this still reads as a behavior change introduced on the changed lines rather than an existing pattern being followed. I should verify against the merge-base version to confirm the fallback really did applytext-icon-mutedbefore. I'm confirming the old fallback styling matched, and checking whether the null-source case previously still rendered ProjectFavicon with an empty cwd that would fail and fall back anyway. Now I want to check if there's a bigger regression in how SidebarSearchResultRow and SidebarThreadRow handle the source value. The new code pulls favicon source fromprojectFaviconSourceByKeyderived fromprojectGroups, while the old code usedprojectFaviconPathByKeyand cwd fromprojectCwdByKey, both derived fromprojectsdirectly. I need to verify whetherprojectGroupsactually covers every project inprojects, or if it's filtered by scope and could be missing some. The project display name mapping reuses the existing projectGroups data, so coverage matches. I'm now cataloging the specific fallback-icon regressions where styling like text-icon-muted and shrink-0 get dropped at each site, starting with the FolderIcon and MessageSquareIcon instances. Now I'm weighing whether to post four separate inline comments for each regression site or consolidate into fewer comments since they're all the same pattern — leaning toward posting on the two most impactful lines to avoid noise while still flagging the issue clearly. I'm checking the exact indentation levels at each of these line numbers to make sure the edits align properly with the surrounding code structure. Now I'm confirming the class ordering matches the existing convention used elsewhere in the file, then preparing to submit a single review with four inline comments, with the overall check defaulting to failure since there are findings to report.
1. modify_pr — Reviewed the web-side favicon changes for shared-component and styling consistency. One issue: the new projectFaviconSource === null branches in Sidebar.tsx render raw lucide icons instead of going through ProjectFavicon's fallback, which applies cn("size-3.5 shrink-0 text-icon-muted", className). Before this PR these rows always rendered ProjectFavicon (with cwd={projectCwd ?? ""}), so the no-favicon state was drawn with the themed --icon-muted token (--app-theme-icon-muted under custom themes). The new bare icons inherit the row's current text color, so the placeholder now renders at full row-text strength and stops following the theme's icon tone; the slim-row case also drops shrink-0. Adding text-icon-muted (and shrink-0 where it was dropped) restores the previous rendering. Everything else — the projectKey plumbing, ProjectFaviconSource spreading, and the CommandPalette/LegacySidebar/ProjectSettingsPanel call sites — keeps the existing class contracts intact.
Agent Credits: 101 credits