Skip to content

refactor(web): route all icon imports through one barrel - #7963

Open
saphid wants to merge 8 commits into
pingdotgg:mainfrom
saphid:agent/web-icon-barrel-extracted
Open

refactor(web): route all icon imports through one barrel#7963
saphid wants to merge 8 commits into
pingdotgg:mainfrom
saphid:agent/web-icon-barrel-extracted

Conversation

@saphid

@saphid saphid commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Web icon imports now go through one generated static module, while project-selected icons use a separate dynamic lookup. This gives the web app one checked import surface and catches direct or misspelled Lucide imports before they drift into the codebase.

The generator uses the workspace TypeScript parser, validates names against lucide-react, and verifies that the checked-in module is current. The integration also preserves the latest environment-filter and model-price controls while routing their icons through the same module.

Verification

Current head ce70ae4f6c5afe13ca4295d6a3e300e852783414 includes upstream main 82c2b7ffb4d450572f5baf9a70693f1e25cfdfed. The merge keeps upstream's menu radio indicator and obsolete composer-test deletion.

  • vp test run apps/web/src/icons/icon-imports.test.ts apps/web/src/icons/index.test.ts: 6 tests passed.
  • vp test run apps/web/src/components/ProjectFavicon.test.tsx apps/web/src/components/ThreadStatusIndicators.test.ts apps/web/src/components/pullRequest/PullRequestListFilters.test.tsx: 53 tests passed across 4 files.
  • Web icons:generate, icons:check, and typecheck passed; all 226 generated exports are current.
  • Scoped web Knip file/dependency check and production web build passed. The build retained chunk-size warnings.

A fresh read-only review of the merge resolution found no actionable issues. Current integrated Settings navigation shows the same icons and labels before and after the import refactor.

Before After
Before: Settings navigation icons After: the same Settings navigation icons

Annotated before · Annotated after.

Capture conditions: baseline main 39802c061, candidate integration 0d60fe9be45bec12356ab116796008d44c3d2a7b containing exact PR head ce70ae4f6c5afe13ca4295d6a3e300e852783414; same dark Settings General navigation. Matching crops x0,y60,width256,height740 omit the header and settings content changed by other integrated PRs. This is representative icon-rendering evidence, not a standalone build or a performance measurement. Reference-identity tests cover all generated icon exports. Images were inspected and all uploaded bytes were retrieved and hash-verified. No new interaction is introduced by changing icon imports.

Implemented and reviewed with GPT-6 and GPT-5.6 Sol in the Codex harness. A direct Claude Opus 5 high review availability attempt exited 1 because OAuth had expired; no Opus review occurred.

Note

Route all web Lucide icon imports through single ~/icons barrel

  • Adds a generator script generate-icon-barrel.ts that scans web source and test files for named Lucide icon imports, validates them against lucide-react exports, and writes or checks the generated barrel at index.ts
  • Adds a dynamic icon seam at dynamic.ts re-exporting DynamicIcon, IconName, and iconNames from lucide-react/dynamic
  • Updates 100+ component, route, and UI files to import icons from ~/icons instead of lucide-react directly
  • Adds an ESLint no-restricted-imports rule in vite.config.ts that flags direct lucide-react imports and directs developers to ~/icons
  • Adds icons:check and icons:generate scripts to package.json, plus identity and parser tests under apps/web/src/icons/
  • Risk: any new direct lucide-react import will fail lint; the barrel must be regenerated via icons:generate when new icons are used or CI's icons:check will fail

Macroscope summarized ce70ae4.

@coderabbitai

coderabbitai Bot commented Aug 23, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: a65da9d1-092d-46f8-a3ab-8b7b5b7bf790

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Aug 23, 2026
Comment thread apps/web/scripts/generate-icon-barrel.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

UI consistency: one web file still bypasses the new ~/icons seam

apps/web/src/components/chat/ChatComposer.tsx (import block ending at line 237) still imports directly from lucide-react:

import {
  BotIcon,
  CircleAlertIcon,
  PencilRulerIcon,
  type LucideIcon,
  LockIcon,
  LockOpenIcon,
  PenLineIcon,
  SparklesIcon,
  XIcon,
} from "lucide-react";

Two consequences that come from lines changed in this PR:

  1. The new eslint/no-restricted-imports entry added in vite.config.ts is "error" and applies repo-wide, so lint now fails on this file. It carries no eslint-disable, and the PR's verification only ran vp lint apps/web/src/icons, which would not surface it.
  2. The composer is the most icon-dense surface in the app, so leaving it outside the barrel contradicts the invariant this PR and docs/internals/icons.md state ("Every interface glyph in apps/web flows through one module") and would be missed by a future icon-pack swap — the exact seam this change exists to create.

Smallest fix: change that one specifier to ~/icons. Every name in the block, including type LucideIcon, is already exported by apps/web/src/icons/index.ts, so the barrel does not need regenerating:

} from "~/icons";

(Posted as a conversation comment rather than inline because the file is not part of this diff.)

Posted via Macroscope — UI Consistency

@macroscopeapp

macroscopeapp Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This is a broad web import-graph refactor that introduces a generated icon abstraction and changes imports across the production UI, including authentication-related components. It also adds explicit lint and diagnostic suppressions, so the change warrants human review despite the intended reference-preserving behavior.

You can add or adjust custom eligibility rules. Learn more.

@saphid

saphid commented Aug 23, 2026

Copy link
Copy Markdown
Contributor Author

Good catch — fixed in c67ca0c50. The codemod's grep had skipped ChatComposer.tsx because the file contains literal NUL bytes in a template string (grep binary detection); the sweep now reads file bytes instead, and a re-scan confirms zero direct lucide-react imports remain outside the barrel. Macroscope's UI Consistency check passes on the latest commit.

@saphid

saphid commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Factual check on the Macroscope UI-consistency comment against current head c67ca0c5: apps/web/src/components/chat/ChatComposer.tsx imports the icon block from ~/icons at line 237. The file contains a NUL byte, which explains why text-oriented scans can misclassify it as binary. No code change is needed for that finding.

The separate unresolved generator finding is still valid: declaration-level import type { LucideIcon } from "~/icons" is matched as a runtime export by IMPORT_PATTERN. That needs a code fix and focused test before the PR is ready.

@saphid
saphid force-pushed the agent/web-icon-barrel-extracted branch 2 times, most recently from 4e958a7 to 7e8c6c1 Compare August 27, 2026 02:32
Comment thread apps/web/src/icons/icon-import-parser.ts Outdated
@saphid
saphid force-pushed the agent/web-icon-barrel-extracted branch 4 times, most recently from c0fb01a to d0a4c9c Compare August 29, 2026 05:21
Comment thread apps/web/src/icons/icon-import-parser.ts Outdated
Comment thread apps/web/src/icons/icon-import-parser.ts Outdated
Comment thread apps/web/src/icons/icon-import-parser.ts Outdated
Comment thread apps/web/src/icons/icon-import-parser.ts Outdated
Comment thread apps/web/src/icons/icon-import-parser.ts Outdated
Comment thread apps/web/src/icons/icon-import-parser.ts Outdated

@cursor cursor Bot 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 6b9f440097c0b914454b0ad74679020408d85e52. Configure here.

Comment thread apps/web/src/icons/icon-import-parser.ts Outdated
@saphid
saphid force-pushed the agent/web-icon-barrel-extracted branch from 6b9f440 to 7fae5ca Compare August 30, 2026 01:01
Comment thread apps/web/src/icons/icon-import-parser.ts Outdated
@saphid
saphid force-pushed the agent/web-icon-barrel-extracted branch from 7fae5ca to 3978288 Compare September 5, 2026 00:28
@juliusmarminge

Copy link
Copy Markdown
Member

can we not fix this with a vite plugin or smth??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL 500-999 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants