Skip to content

feat(ui): refactor Icon component to use remixicon registry#172

Merged
kylengn merged 3 commits intomainfrom
feat/enhance-icon-component
Nov 25, 2025
Merged

feat(ui): refactor Icon component to use remixicon registry#172
kylengn merged 3 commits intomainfrom
feat/enhance-icon-component

Conversation

@kylengn
Copy link
Contributor

@kylengn kylengn commented Nov 24, 2025

Summary by CodeRabbit

  • New Features

    • Added new custom icon entries (badge, checkCircleSolid, circleDottedLine, componentFill, componentLine, ellipseMiniSolid, infoTooltipFill, resize) expanding the available icon library.
  • Refactor

    • Reorganized icon registry structure with centralized management for improved maintainability and extensibility. Icon component API remains unchanged with no impact to existing usage.

✏️ Tip: You can customize this high-level summary in your review settings.

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

vercel bot commented Nov 24, 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 25, 2025 3:59am

@coderabbitai
Copy link

coderabbitai bot commented Nov 24, 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 pull request refactors icon management by centralizing Remix icon imports into a dynamic registry file, merging custom icons with Remix icons into a unified map, and broadening the BaseIconProps type to use a generic Remixicon component type instead of a specific icon type.

Changes

Cohort / File(s) Summary
Icon Registry Creation
libs/react/ui/src/components/icon/remixicon-registry.ts
New file that dynamically imports all Remix icons, filters and normalizes icon names by stripping "Ri" prefix and lowercasing first letter, then exports remixiconMap, RemixIconName type, and remixiconNames array.
Icon Component Refactoring
libs/react/ui/src/components/icon/icon.tsx
Replaces explicit individual Remix icon imports with centralized remixiconMap import; introduces customIconsMap with new entries (badge, checkCircleSolid, circleDottedLine, componentFill, componentLine, ellipseMiniSolid, infoTooltipFill, resize); merges both maps into unified iconsMap; generalizes BaseIconProps from ComponentProps<typeof RiGoogleFill> to ComponentProps<RemixiconComponentType>.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Type generalization: Verify that broadening BaseIconProps to ComponentProps<RemixiconComponentType> maintains type safety and doesn't inadvertently accept invalid props
  • Icon name normalization: Carefully review the name normalization logic in remixicon-registry.ts to ensure all Remix icons are correctly mapped and no collisions occur
  • Custom icons integration: Ensure custom icon entries are properly typed and the merge between remixiconMap and customIconsMap preserves expected behavior
  • Dynamic import side effects: Confirm the dynamic registry approach doesn't introduce unexpected runtime behavior or build issues

Possibly related PRs

Suggested reviewers

  • dvxam
  • noe-charmet
  • EnzalRad

Poem

🐰 Hops through the icon garden with glee,
Remixing and merging for all to see,
Custom and classic in harmony blend,
One map to rule them, no imports to mend!
Registry centralized, types set free,
What a wonderful refactor it be! 🎨✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: refactoring the Icon component to use a new remixicon registry, which aligns with the core modifications across both files.

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 24, 2025

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

Build Status Details Updated (UTC)
default (Inspect) 👍 Changes approved 2 changed Nov 25, 2025, 4:01 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 dynamically load all Remix icons from a registry instead of using hardcoded imports. This change makes all Remix icons available through the Icon component rather than just a curated subset of 14 icons.

Key Changes:

  • Introduced remixicon-registry.ts that builds a dynamic map of all Remix icons by filtering exports and transforming icon names
  • Modified icon.tsx to merge the full Remix icon registry with custom icons, replacing explicit icon imports
  • Changed icon naming convention from custom short names (e.g., google, check, close) to systematic names derived from Remix component names (e.g., googleFill, checkLine, closeLine)

Reviewed changes

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

File Description
libs/react/ui/src/components/icon/remixicon-registry.ts Creates a registry of all Remix icons by filtering and transforming icon component names, enabling dynamic access to the full icon library
libs/react/ui/src/components/icon/icon.tsx Replaces hardcoded icon imports with the dynamic registry, merging all Remix icons with custom icons while changing the icon naming convention

💡 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: 0

🧹 Nitpick comments (4)
libs/react/ui/src/components/icon/remixicon-registry.ts (3)

4-7: Double‑check the typeof value === 'function' filter against your installed @remixicon/react

The prefix + typeof guard is a nice way to exclude non‑icon exports, but it assumes every icon export from @remixicon/react has typeof === 'function'. If a future (or current) version ever exposes icons as exotic components where typeof is 'object', they’ll be silently dropped and remixiconMap will end up incomplete.

Consider either:

  • Relaxing the guard (e.g. also allowing 'object') while still excluding obvious non‑icon exports, or
  • Asserting this behaviour in a small test that fails loudly if icons stop being functions.

9-12: Optionally tighten iconNameToKey typing

The normalization logic is straightforward, but you could make the intent clearer and catch misuse by constraining the input type, e.g.:

function iconNameToKey(iconName: `Ri${string}`): string { ... }

This is purely a type‑level improvement; runtime behaviour stays the same.


19-25: RemixIconName is effectively just string due to the Record<string, …> cast

Because remixiconMap is asserted as Record<string, RemixiconComponentType>, keyof typeof remixiconMap (and thus RemixIconName) collapses to string instead of a finite union of normalized icon keys. That’s fine if you only need a generic string index, but if the goal is stronger typing/autocomplete on allowed Remix icon names, this cast prevents it.

If you want a narrower RemixIconName, you’ll likely need either:

  • A generated type/registry (build‑time codegen), or
  • A manually maintained type RemixIconName = 'alertFill' | 'addLine' | ... that you use to type the map, e.g. Record<RemixIconName, RemixiconComponentType>.
libs/react/ui/src/components/icon/icon.tsx (1)

38-44: IconName is now effectively string; consider whether that loss of narrowing is acceptable

With:

const iconsMap = {
  ...remixiconMap,
  ...customIconsMap,
} as Record<string, RemixiconComponentType> & typeof customIconsMap;

export type IconName = keyof typeof iconsMap;

keyof typeof iconsMap widens to string because of the Record<string, …> part, so IconName no longer encodes the concrete set of icon keys (Remix + custom). That means Icon will happily accept any string at the type level, even though iconsMap[name] may be undefined at runtime.

If you want to preserve stricter typing, possible directions:

  • Drop the Record<string, …> from the cast and let TS infer, or
  • Shape the type explicitly, e.g.:
type IconName = RemixIconName | keyof typeof customIconsMap;

const iconsMap: Record<IconName, RemixiconComponentType> = {
  ...remixiconMap,
  ...customIconsMap,
};

If you’re okay with IconName being just string, this is fine as‑is.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6a87c0 and bacc605.

📒 Files selected for processing (2)
  • libs/react/ui/src/components/icon/icon.tsx (2 hunks)
  • libs/react/ui/src/components/icon/remixicon-registry.ts (1 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/remixicon-registry.ts
  • libs/react/ui/src/components/icon/icon.tsx
🧬 Code graph analysis (1)
libs/react/ui/src/components/icon/icon.tsx (1)
libs/react/ui/src/components/icon/remixicon-registry.ts (1)
  • remixiconMap (19-22)
⏰ 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 (3)
libs/react/ui/src/components/icon/icon.tsx (2)

21-36: Good use of satisfies to keep custom icons aligned with Remix props

Typing customIconsMap with as const satisfies Record<string, RemixiconComponentType> is a solid pattern: it preserves literal keys while enforcing that each custom icon matches the Remix icon component contract.


46-47: Base icon props generalization looks good; verify compatibility with your TS/React versions

Switching to:

type BaseIconProps = ComponentProps<RemixiconComponentType>;
type IconProps = {name: IconName} & Omit<BaseIconProps, 'name'>;

nicely aligns the Icon API with whatever props @remixicon/react exposes (e.g. size, color, className) and keeps name under your control.

Just ensure your installed versions of React/TypeScript and @remixicon/react agree on RemixiconComponentType being a valid argument to ComponentProps; if not, you may need to switch to ComponentPropsWithoutRef or a custom props alias.

libs/react/ui/src/components/icon/remixicon-registry.ts (1)

1-2: No issues found—dependency is properly declared

The verification confirms that @remixicon/react is already listed in libs/react/ui/package.json as a dependency with version ^4.6.0. The imports in this file are properly supported and will not rely on transitive installs.

noe-charmet
noe-charmet previously approved these changes Nov 25, 2025
@kylengn kylengn merged commit 43f0699 into main Nov 25, 2025
5 checks passed
@kylengn kylengn deleted the feat/enhance-icon-component branch November 25, 2025 05:08
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