Skip to content

feat(ui): streamline icon imports and enhance dynamic icon mapping#152

Merged
kylengn merged 4 commits intomainfrom
feat/add-icon-components
Nov 19, 2025
Merged

feat(ui): streamline icon imports and enhance dynamic icon mapping#152
kylengn merged 4 commits intomainfrom
feat/add-icon-components

Conversation

@kylengn
Copy link
Contributor

@kylengn kylengn commented Nov 18, 2025

Summary by CodeRabbit

  • Refactor
    • Reorganized icon component to dynamically support an expanded range of icons
    • Enhanced type safety for icon properties while maintaining backward compatibility
    • Improved internal architecture for managing icon libraries

@kylengn kylengn self-assigned this Nov 18, 2025
Copilot AI review requested due to automatic review settings November 18, 2025 10:52
@vercel
Copy link

vercel bot commented Nov 18, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
react-ui Ready Ready Preview Comment Nov 19, 2025 4:04am

@coderabbitai
Copy link

coderabbitai bot commented Nov 18, 2025

Important

Review skipped

Auto incremental 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.

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

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

The icon component's import strategy is refactored from direct named imports to a namespace-based approach. A dynamic icon discovery layer is introduced that converts Remix icon names to camelCase keys, merges custom icons with runtime-scanned Remix icons into a unified mapping, and updates the BaseIconProps type signature to reflect this new architecture.

Changes

Cohort / File(s) Change Summary
Icon Component Refactoring
libs/react/ui/src/components/icon/icon.tsx
Replaced direct named RemixIcon imports with namespace import; added utility functions (RI_PREFIX_REGEX, NUMERIC_START_REGEX, toCamelCase); created customIcons mapping for google/microsoft icons; implemented dynamic runtime scanning of RemixIcons namespace to populate dynamicIconsMap; merged custom and dynamic icons into unified iconsMap; updated BaseIconProps type signature from ComponentProps<typeof RiGoogleFill> to ComponentProps<typeof RemixIcons.RiGoogleFill>.

Sequence Diagram

sequenceDiagram
    participant Init as Module Init
    participant Utils as Utility Functions
    participant CustomIcons as Custom Icons Map
    participant RemixNS as RemixIcons Namespace
    participant Dynamic as Dynamic Discovery
    participant Final as Unified iconsMap

    Init->>Utils: Define regex & toCamelCase
    Init->>CustomIcons: Build custom icons (google, microsoft)
    Init->>RemixNS: Access RemixIcons namespace
    RemixNS->>Dynamic: Scan for Ri* prefixed icons
    Dynamic->>Dynamic: Convert to camelCase keys
    Dynamic->>Dynamic: Filter out already-mapped customs
    Dynamic->>Final: Merge customIcons + dynamicIconsMap
    Final->>Init: Export unified iconsMap & IconName
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • The dynamic runtime scanning logic requires careful verification to ensure all Remix icons are correctly discovered and converted to camelCase keys
  • Type signature changes and their consistency across the codebase should be validated
  • Edge cases in the regex helpers (NUMERIC_START_REGEX) and toCamelCase conversion logic warrant thorough testing
  • The merging strategy for custom vs. dynamically discovered icons needs verification to prevent conflicts or duplicates

Possibly related PRs

Suggested reviewers

  • dvxam
  • noe-charmet
  • EnzalRad

Poem

🐰 Hops through icon cascades
With RemixIcons unified,
Dynamic discovery prances,
CamelCase conversions dance,
Where custom and Remix combine!
🎨✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: streamlining icon imports (replacing direct named imports with broad imports) and enhancing dynamic icon mapping (adding runtime discovery and type-safe mapping logic).
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@argos-ci
Copy link

argos-ci bot commented Nov 18, 2025

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) 👍 Changes approved 2 changed, 2 added Nov 19, 2025, 4:06 AM

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR refactors the icon component to use dynamic icon mapping instead of individual imports, enabling automatic access to all Remix icons through a wildcard import and camelCase name conversion.

  • Replaced individual icon imports with import * as RemixIcons to access all icons
  • Added dynamic icon mapping that converts PascalCase Remix icon names to camelCase (e.g., RiGoogleFillgoogle)
  • Implemented automatic icon registration by filtering and mapping all Remix icons that don't conflict with custom icons

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
libs/react/ui/src/components/icon/icon.tsx (2)

64-79: Dynamic spread into iconsMap likely widens IconName to string, weakening type safety

Because dynamicIconsMap is typed as Record<string, RemixiconComponentType> and then spread into iconsMap, the inferred type of iconsMap becomes something like:

{ /* literal keys from customIcons */ } & Record<string, RemixiconComponentType>

For such an intersection, keyof typeof iconsMap effectively collapses to string. That means:

  • IconName = keyof typeof iconsMap is now just string, not the literal union of known keys.
  • <Icon name="totallyWrong" /> will type‑check, even though iconsMap["totallyWrong"] will be undefined, leading to an invalid React element (IconComponent is undefined) at runtime.

If you want to preserve a strongly‑typed public surface while still benefiting from dynamic discovery, consider splitting the concerns:

  • Keep a curated map for the public API, e.g.:

    const staticIconsMap = customIcons;
    export type IconName = keyof typeof staticIconsMap;
  • Use iconsMap (with dynamic spread) internally where you really need “all Remix icons”, or expose a separate allIconNames: string[] / allIconsMap for tooling like icon pickers.

This keeps the runtime behavior you added but restores compile‑time checking for consumer‑facing IconProps.name.

Please confirm in your editor what IconName currently resolves to; if it’s string, I’d strongly consider tightening it as above.

Also applies to: 81-87


89-90: BaseIconProps update is consistent with the new namespace import; optional decoupling from a specific icon

Switching from ComponentProps<typeof RiGoogleFill> to ComponentProps<typeof RemixIcons.RiGoogleFill> is a mechanical, correct change that keeps the Icon props aligned with a representative Remix icon while matching the new import style.

If you ever want to avoid tying BaseIconProps to a single concrete icon, you could instead extract props from RemixiconComponentType via a conditional type (e.g., type BaseIconProps = RemixiconComponentType extends React.ComponentType<infer P> ? P : never;), but that’s purely optional and what you have now is consistent with the previous design.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 56ec27f and 5ff887c.

📒 Files selected for processing (1)
  • libs/react/ui/src/components/icon/icon.tsx (3 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*

⚙️ CodeRabbit configuration file

We handle errors at the edge of our applications in most cases. Do not recommend to add error handling around every single function. We prefer them to bubble up and be handled at upper layers.

Files:

  • libs/react/ui/src/components/icon/icon.tsx
🧬 Code graph analysis (1)
libs/react/ui/src/components/icon/icon.tsx (3)
libs/react/ui/src/components/icon/custom/shipfox-logo.tsx (1)
  • ShipfoxLogo (8-20)
libs/react/ui/src/components/icon/custom/slack-logo.tsx (1)
  • SlackLogo (6-35)
libs/react/ui/src/components/icon/custom/stripe-logo.tsx (1)
  • StripeLogo (8-27)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Agent
  • GitHub Check: Continuous integration
🔇 Additional comments (2)
libs/react/ui/src/components/icon/icon.tsx (2)

21-23: Camel‑case helper and numeric prefix handling look correct

RI_PREFIX_REGEX / NUMERIC_START_REGEX plus toCamelCase produce the expected keys (e.g., RiHomeSmileFillhomeSmileFill, Ri2KLinei2KLine). The logic is straightforward and matches the new dynamic mapping needs.

Also applies to: 55-62


24-53: customIcons map additions are consistent and readable

The expanded customIcons object cleanly mixes custom SVG logos with explicit Remix aliases (google, microsoft, imageAdd, etc.), and the keys follow the existing camelCase naming convention. Marking it as const keeps key names precise for typing. No issues from a correctness or clarity standpoint.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 6 out of 6 changed files in this pull request and generated no new comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@kylengn
Copy link
Contributor Author

kylengn commented Nov 19, 2025

@noe-charmet can you help review and approve this PR please?

@kylengn kylengn merged commit 82e623d into main Nov 19, 2025
5 checks passed
@kylengn kylengn deleted the feat/add-icon-components branch November 19, 2025 05:18
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