Skip to content

feat: add 9 new icons and payment checkout example#63

Closed
forever-ivy wants to merge 26 commits intoitshover:masterfrom
forever-ivy:feat/add-new-brand-icons
Closed

feat: add 9 new icons and payment checkout example#63
forever-ivy wants to merge 26 commits intoitshover:masterfrom
forever-ivy:feat/add-new-brand-icons

Conversation

@forever-ivy
Copy link
Copy Markdown

@forever-ivy forever-ivy commented Jan 8, 2026

Description

Add 9 new brand icons (alipay, appstore, openai, react, tiktok, visa, wechat,paypal,mastercard)
Added new example payment checkout

Type of Change

New icons
New example

Checklist

  • Code follows project style guidelines
  • npm run check passes
  • npm run registry:build passes (for new icons)
  • Icons work on all screen sizes
  • Self-review completed

Release Notes

  • New Features
    • Introduced 8 new animated icon components: Alipay, App Store, Netflix, OpenAI, React, TikTok, Visa, and WeChat.
    • Icons feature smooth animations triggered on hover with customizable animation controls.
    • Start and stop animation capabilities available for programmatic control.
    • All new icons are registered and ready for application-wide use.

Summary by CodeRabbit

  • New Features
    • Added many animated brand icons (Alipay, WeChat, TikTok, Visa, Mastercard, App Store, Netflix, OpenAI, React, PayPal and variants) with hover-triggered animations and start/stop controls, and registry entries to discover them.
    • Added a Payment Checkout component with expandable order summary, animated payment-method selection, responsive layout, and a pay action callback.

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

@vercel
Copy link
Copy Markdown
Contributor

vercel bot commented Jan 8, 2026

@forever-ivy is attempting to deploy a commit to the itshover's projects Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jan 8, 2026

📝 Walkthrough

Walkthrough

Adds many new animated icon components and registry entries, plus a new PaymentCheckout example component and its registration entry.

Changes

Cohort / File(s) Summary
Animated Icon Components
icons/alipay-icon.tsx, icons/wechat-icon.tsx, icons/brand-appstore-icon.tsx, icons/brand-mastercard-icon.tsx, icons/brand-tiktok-icon.tsx, icons/brand-visa-icon.tsx, icons/tiktok-icon.tsx, icons/netflix-icon.tsx, icons/openai-icon.tsx, icons/react.tsx, icons/paypal-icon.tsx, icons/mastercard-icon.tsx, icons/visa-icon.tsx, icons/appstore-icon.tsx, icons/...
New React forwardRef components exporting default animated SVG icons. Each uses Motion (useAnimate), exposes an imperative handle (startAnimation, stopAnimation), wires hover start/stop, and accepts size, color, strokeWidth, className.
Shared Type Definitions
icons/types.ts
New exported interfaces AnimatedIconProps and AnimatedIconHandle consumed by icon components.
Icon Registry & Exports
icons/index.ts, lib/icons.ts, registry.json, public/r/registry.json
Imports/exports and ICON_LIST/ICONS updated to include added icons (alipay, wechat, brand-* etc.); some ICON_LIST entries duplicated in places; hotel icon path adjusted. New registry entries reference motion.
Individual Registry Manifests
public/r/*.json
(e.g. public/r/alipay-icon.json, public/r/appstore-icon.json, public/r/mastercard-icon.json, public/r/tiktok-icon.json, public/r/visa-icon.json, public/r/wechat-icon.json, public/r/netflix-icon.json, public/r/openai-icon.json, public/r/react-icon.json, public/r/paypal-icon.json, public/r/brand-*.json)
New registry:ui JSON entries for each icon pairing the icon TSX and icons/types.ts, declaring dependencies on motion.
Payment Checkout Example
components/examples/payment-checkout.tsx
New example component (PaymentCheckout + PaymentCheckoutExample) with types (PaymentMethod, CheckoutItem, PaymentCheckoutProps), subtotal/total logic, animated payment method selection, pay action callback, controlled/uncontrolled selection and summary toggles.
Examples Registry Update
lib/examples.ts
Adds import and EXAMPLE_REGISTRY entry for the PaymentCheckout example (payment-checkout) with metadata and tags.

Sequence Diagram(s)

sequenceDiagram
  participant User as "User"
  participant Checkout as "PaymentCheckout"
  participant Method as "PaymentMethodOption"
  participant Host as "onPay handler"

  User->>Checkout: Open checkout
  Checkout->>Method: Render payment methods (animated)
  User->>Method: Click/select method
  Method-->>Checkout: selectedMethodId
  User->>Checkout: Toggle summary / view items
  User->>Checkout: Click "Pay"
  Checkout->>Host: onPay(paymentPayload)
  Host-->>Checkout: confirmation / result
  Checkout-->>User: Show confirmation UI
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐰 Hop-hop, new icons come to play,
Alipay twinkles, WeChat bubbles sway,
Checkout counts coins with a merry beat,
Paths draw and spin on tiny feet,
I nibble code-carrots — delights are complete! 🥕✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ 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%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ 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 'feat: add 9 new icons and payment checkout example' directly and clearly summarizes the main changes in the pull request, specifying both the number of icons and the new example component.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

Copy link
Copy Markdown
Contributor

@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: 13

🤖 Fix all issues with AI agents
In @icons/index.ts:
- Line 135: The import for ReactIcon in icons/index.ts uses "./react" which is
inconsistent with the "-icon" naming convention; rename the module file from
react.tsx to react-icon.tsx and update the import in icons/index.ts to
"./react-icon" (and any other places importing ReactIcon) so the symbol
ReactIcon resolves to the newly named module and matches the pattern used
throughout the icon set.

In @icons/netflix-icon.tsx:
- Around line 54-56: NetflixIcon currently auto-triggers its animation on mount
via the useEffect that calls start, but OpenAIIcon and Visa lack this behavior
causing inconsistent UX; either remove the mount useEffect from NetflixIcon or
add the same mount-trigger to the other icons. Locate the NetflixIcon useEffect
that calls start and then either (a) delete that useEffect to require hover for
all icons, or (b) add the equivalent useEffect(() => { start(); }, [start]) into
the OpenAIIcon and Visa components (and any other icon components) so all icons
consistently animate on mount; update related prop names or animation hooks if
necessary to ensure start is available and stable across those components.
- Line 8: The import in netflix-icon.tsx uses the legacy path "framer-motion";
update the import to use "motion/react" (e.g., change import { motion,
useAnimate, stagger } from "framer-motion" to import { motion, useAnimate,
stagger } from "motion/react") and apply the same change in the other icon
components openai-icon.tsx, react.tsx, wechat-icon.tsx, and tiktok-icon.tsx so
all icons consistently import motion utilities from "motion/react".

In @icons/openai-icon.tsx:
- Around line 1-71: Add a mount animation by importing and using useEffect in
the OpenAIIcon component: call the existing start callback inside useEffect when
the component mounts and optionally call stop on cleanup; reference the start
and stop functions (and the OpenAIIcon forwardRef) so the initial path-draw
animation runs on mount just like NetflixIcon. Ensure you import useEffect from
React, add useEffect(() => { start(); return () => stop(); }, [start, stop]); to
the component body.

In @icons/react.tsx:
- Line 3: The import line currently pulls motion utilities from "framer-motion";
change it to import from "motion/react" instead (update the import that
currently reads import { motion, useAnimate, stagger } from "framer-motion" to
use "motion/react") so the module matches package.json and the rest of the icon
files; ensure the same named imports (motion, useAnimate, stagger) are
preserved.

In @icons/tiktok-icon.tsx:
- Around line 1-3: The import for the animation library is wrong: replace the
import source that currently imports { motion, useAnimate } from "framer-motion"
with the project's actual library "motion" so that the named symbols motion and
useAnimate used in icons/tiktok-icon.tsx (and any references in the file such as
forwardRef usage that relies on motion) resolve at runtime; update that single
import statement to import the same named exports from "motion".

In @icons/visa-icon.tsx:
- Around line 1-84: Add a mount animation by calling the existing start callback
inside a useEffect when the Visa component mounts: import/use React's useEffect
and invoke start() in useEffect(() => { start(); }, [start]) so the icon
animates on initial render; keep the existing hover handlers and imperative
handle (start/stop) intact and do not change the animate/selectors
(scope/animate/useAnimate).

In @lib/icons.ts:
- Around line 500-503: The icon entry with name "react icon" has an inconsistent
path value of "/icons/react"; update its path to follow the established pattern
(e.g., "/icons/react-icon") and rename the component file from react.tsx to
react-icon.tsx, then update the corresponding import/export in icons/index.ts so
the module name matches the new path and keeps naming consistent with other
icons.
- Line 1: The file imports the Node "path" module but never uses it; remove the
unused import statement (the line importing "path") from lib/icons.ts to
eliminate the unused symbol "path" and then run the repo linter/TypeScript build
to ensure no other references remain.

In @public/r/netflix-icon.json:
- Line 4: Update the dependency declaration so it matches the actual import:
change the dependencies array entry from "motion" to "framer-motion" (used by
the embedded component import `import { motion, useAnimate, stagger } from
"framer-motion"`), ensuring the registry/dependency list and runtime imports
align.

In @public/r/openai-icon.json:
- Around line 4-10: The component OpenAIIcon imports animation primitives from
"framer-motion" but the package declared is "motion", causing resolution errors;
update the import statement in the embedded icon component (the line importing
motion, useAnimate, stagger) to import from "motion/react" instead of
"framer-motion" so the symbols motion, useAnimate, and stagger resolve
correctly.

In @public/r/react.json:
- Line 10: The import for the motion library is wrong: update the import
statement at the top of the ReactIcon module so that the ReactIcon component
uses the same package as other icons (importing motion, useAnimate, stagger from
"motion/react" instead of "framer-motion"); locate the import line that declares
motion, useAnimate, stagger and change its source to "motion/react" so the
ReactIcon component (forwardRef ReactIcon, start/stop callbacks, and the
motion.svg usage) resolves at runtime.

In @public/r/tiktok-icon.json:
- Around line 4-10: The component TiktokIcon imports motion and useAnimate from
"framer-motion" while the declared dependency is "motion"; update the import
statement in the embedded icons/tiktok-icon.tsx content to import { motion,
useAnimate } from "motion/react" (leave the rest of the component, including
TiktokIcon, start/stop callbacks and exports, unchanged) so the runtime import
matches the registry dependency.
🧹 Nitpick comments (10)
public/r/visa-icon.json (1)

10-10: Add dependency array to useImperativeHandle.

The useImperativeHandle hook call on line 44 (within the embedded component code) is missing a dependency array. While the code will work, React 19 best practices recommend including all dependencies for consistency and to avoid potential stale closure issues.

♻️ Proposed fix

Update the useImperativeHandle call to include the dependency array:

-    useImperativeHandle(ref, () => ({
+    useImperativeHandle(ref, () => ({
       startAnimation: start,
       stopAnimation: stop,
-    }));
+    }), [start, stop]);
public/r/react.json (1)

10-10: Add dependency array to useImperativeHandle.

The useImperativeHandle hook call on line 51 (within the embedded component code) is missing a dependency array. React 19 best practices recommend including [start, stop] to avoid potential stale closure issues.

♻️ Proposed fix
-    useImperativeHandle(ref, () => ({
+    useImperativeHandle(ref, () => ({
       startAnimation: start,
       stopAnimation: stop,
-    }));
+    }), [start, stop]);
icons/tiktok-icon.tsx (1)

51-54: Add dependency array to useImperativeHandle.

The useImperativeHandle call is missing a dependency array. React 19 best practices recommend including [start, stop] to ensure the imperative handle updates correctly if the callbacks change.

♻️ Proposed fix
-    useImperativeHandle(ref, () => ({
+    useImperativeHandle(ref, () => ({
       startAnimation: start,
       stopAnimation: stop,
-    }));
+    }), [start, stop]);
icons/alipay-icon.tsx (1)

50-86: Inconsistent component structure with other icons.

This icon wraps the motion.svg in a <div className="inline-flex items-center justify-center">, while icons/react.tsx renders the motion.svg directly. Additionally, the overflow style is applied inline here (style={{ overflow: "visible" }}), whereas react.tsx includes it in the className (overflow-visible).

For consistency and maintainability, all icon components should follow the same structural pattern.

♻️ Align with the pattern used in react.tsx
     return (
-      <div className={`inline-flex items-center justify-center ${className}`}>
-        <motion.svg
-          ref={scope}
-          onHoverStart={start}
-          onHoverEnd={stop}
-          xmlns="http://www.w3.org/2000/svg"
-          width={size}
-          height={size}
-          viewBox="0 0 24 24"
-          fill="none"
-          stroke={color}
-          strokeWidth={strokeWidth}
-          strokeLinecap="round"
-          strokeLinejoin="round"
-          className="cursor-pointer"
-          style={{ overflow: "visible" }}
-        >
+      <motion.svg
+        ref={scope}
+        onHoverStart={start}
+        onHoverEnd={stop}
+        xmlns="http://www.w3.org/2000/svg"
+        width={size}
+        height={size}
+        viewBox="0 0 24 24"
+        fill="none"
+        stroke={color}
+        strokeWidth={strokeWidth}
+        strokeLinecap="round"
+        strokeLinejoin="round"
+        className={`cursor-pointer overflow-visible ${className}`}
+      >
           <path
             d="M0 0h24v24H0z"
             stroke="none"
             className="bg-none"
             fill="none"
           />

           {/* 外框容器 */}
           <path d="M19 3h-14a2 2 0 0 0 -2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2 -2v-14a2 2 0 0 0 -2 -2" />

           {/* 顶部横笔画 */}
           <path d="M7 7h10" />

           {/* 中间竖笔画 */}
           <path d="M12 3v7" />

           {/* 支付宝核心 Swoosh/支字变形路径 */}
           <path d="M21 17.314c-2.971 -1.923 -15 -8.779 -15 -1.864c0 1.716 1.52 2.55 2.985 2.55c3.512 0 6.814 -5.425 6.814 -8h-6.604" />
-        </motion.svg>
-      </div>
+      </motion.svg>
     );
icons/netflix-icon.tsx (1)

77-84: Use English for code comments to maintain consistency.

The SVG path comments are in Chinese. If the project convention is English-language comments, consider translating these to maintain consistency with the rest of the codebase.

📝 Suggested translation
-        {/* 左侧垂直线条 */}
+        {/* Left vertical line */}
         <path d="M5 3v18h4v-10.5" />
 
-        {/* 右侧垂直线条 */}
+        {/* Right vertical line */}
         <path d="M19 21v-18h-4v10.5" />
 
-        {/* 中间连接斜杠 */}
+        {/* Center connecting slash */}
         <path d="M9 3l10 18h-4l-10 -18l4 0" />
icons/visa-icon.tsx (1)

82-82: Inconsistent displayName convention.

The displayName is set to "Visa" while other icons in this PR use the "Icon" suffix (e.g., "NetflixIcon", "OpenAIIcon"). Consider using "VisaIcon" for consistency.

-Visa.displayName = "Visa";
+Visa.displayName = "VisaIcon";
icons/wechat-icon.tsx (2)

8-8: Import path inconsistent with other icons.

This file imports from "framer-motion" while other icons in the PR (alipay-icon, appstore-icon) use "motion/react". For consistency and to match the declared motion dependency, use the same import path.

Proposed fix
-import { motion, useAnimate, stagger } from "framer-motion";
+import { motion, useAnimate, stagger } from "motion/react";

70-84: Missing onHoverEnd handler.

Other icons in the PR (e.g., OpenAI, AppStore) use both onHoverStart and onHoverEnd to manage animation state. This component only has onHoverStart={playSingleJitter} without a corresponding onHoverEnd. While the jitter is brief, adding onHoverEnd would maintain consistency with the imperative API and other icon patterns.

public/r/alipay-icon.json (1)

8-11: Component naming inconsistent with other icons.

The component is named Alipay with displayName = "Alipay", while other icons in the PR use the Icon suffix (e.g., AppStoreIcon, OpenAIIcon, TiktokIcon, WechatIcon). For consistency, consider renaming to AlipayIcon.

Proposed changes in the embedded content
-const Alipay = forwardRef<AnimatedIconHandle, AnimatedIconProps>(
+const AlipayIcon = forwardRef<AnimatedIconHandle, AnimatedIconProps>(
...
-Alipay.displayName = "Alipay";
-export default Alipay;
+AlipayIcon.displayName = "AlipayIcon";
+export default AlipayIcon;
icons/appstore-icon.tsx (1)

8-9: Split imports from motion packages.

The imports are split between "motion/react" and "motion". Other icons in the PR import stagger from the same module as useAnimate. Consider consolidating:

Proposed fix
-import { motion, useAnimate } from "motion/react";
-import { stagger } from "motion";
+import { motion, useAnimate, stagger } from "motion/react";
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e1abc69 and 4a7659d.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (22)
  • icons/alipay-icon.tsx
  • icons/appstore-icon.tsx
  • icons/index.ts
  • icons/netflix-icon.tsx
  • icons/openai-icon.tsx
  • icons/react.tsx
  • icons/tiktok-icon.tsx
  • icons/visa-icon.tsx
  • icons/wechat-icon.tsx
  • lib/icons.ts
  • public/r/alipay-icon.json
  • public/r/appstore-icon.json
  • public/r/hotel-icon.json
  • public/r/netflix-icon.json
  • public/r/openai-icon.json
  • public/r/react.json
  • public/r/registry.json
  • public/r/tiktok-icon.json
  • public/r/travel-bag.json
  • public/r/visa-icon.json
  • public/r/wechat-icon.json
  • registry.json
🔇 Additional comments (19)
public/r/travel-bag.json (1)

10-10: LGTM! Minor visual adjustment to SVG path.

The SVG path data change appears to be a minor visual refinement to the travel bag icon. The component structure and animation logic remain unchanged and follow best practices.

public/r/hotel-icon.json (1)

10-10: LGTM! Line ending normalization.

This change only normalizes line endings (CRLF → LF) with no behavioral modifications to the hotel icon component.

icons/tiktok-icon.tsx (1)

56-92: Nice glitch effect implementation!

The glitch-style animation using offset cyan and red paths with the main path creates an authentic TikTok brand effect. Extracting pathData as a constant for reuse across the three paths is clean and maintainable.

icons/react.tsx (1)

15-41: Animation logic looks good.

The staggered path animation with center-dot sequence creates a nice visual effect. The implementation correctly initializes, animates, and resets the SVG elements.

lib/icons.ts (3)

104-111: New icon entries look good.

The alipay and appstore icon entries follow the established pattern with appropriate names, paths, and keywords.


374-374: Good fix for hotel icon path.

Correcting the path from /icons/hostel-icon to /icons/hotel-icon resolves the mismatch.


608-611: New icon entries are properly structured.

The tiktok, visa, and wechat entries follow the correct pattern and include appropriate keywords.

Also applies to: 692-699

icons/alipay-icon.tsx (1)

15-42: Animation implementation is solid.

The staggered path animation with appropriate timing creates a smooth drawing effect.

icons/index.ts (2)

32-33: Import statements are well-organized.

The new icon imports follow the established pattern and maintain alphabetical ordering within their sections.

Also applies to: 117-118, 158-158, 191-191, 198-198


383-392: Icon catalog entries are properly structured.

All new icon entries include appropriate names, icon references, and relevant keywords that will help with discoverability.

Also applies to: 1085-1089, 1243-1262, 1288-1292, 1343-1347, 1409-1413

public/r/netflix-icon.json (1)

7-18: Registry structure is correct.

The registry entry properly includes both the component file and the shared types file, with appropriate type declarations.

icons/netflix-icon.tsx (1)

13-92: Core implementation looks solid.

The component follows the established pattern with forwardRef, proper imperative API exposure, and clean animation logic using staggered path drawing. The SVG structure and prop handling are well-implemented.

icons/openai-icon.tsx (1)

9-71: Clean implementation of OpenAI icon animation.

The component structure, animation logic, and imperative API are well-implemented. The staggered path drawing effect with appropriate timing creates a nice visual experience.

public/r/wechat-icon.json (1)

1-20: Registry JSON structure is correct.

The registry item follows the expected schema with proper dependencies, file references, and embedded content. The structure aligns with other icon registry entries.

public/r/registry.json (1)

92-108: Registry entries are well-structured and consistent.

All eight new brand icon entries (alipay-icon, appstore-icon, netflix-icon, openai-icon, react, tiktok-icon, visa-icon, wechat-icon) follow the established registry pattern with correct file paths, dependencies, and metadata.

Also applies to: 194-210, 2115-2131, 2149-2165, 2404-2420, 2880-2896, 3169-3185, 3237-3253

icons/visa-icon.tsx (1)

3-3: Change netflix-icon.tsx and openai-icon.tsx to use "motion/react" for consistency.

The vast majority of icon files in the codebase use import { motion, useAnimate, stagger } from "motion/react". Netflix-icon.tsx, openai-icon.tsx, and a few others import from "framer-motion" instead. Standardize all icon components to use "motion/react".

Likely an incorrect or invalid review comment.

registry.json (1)

92-108: LGTM!

New icon registry entries are properly structured, alphabetically ordered, and consistent with existing entries. Dependencies and file references are correct.

Also applies to: 194-210, 2115-2131, 2149-2165, 2404-2420, 2880-2896, 3169-3185, 3237-3253

icons/appstore-icon.tsx (1)

63-65: Animation restarts when color prop changes.

The start callback depends on color, and useEffect depends on start. This means changing the color prop will trigger a re-animation. This may be intentional, but verify this is the desired behavior.

public/r/appstore-icon.json (1)

1-20: LGTM!

Registry item structure is correct. The embedded content matches the source file. Note: the split import pattern was flagged in the icons/appstore-icon.tsx review.

Comment thread icons/index.ts Outdated
Comment thread icons/netflix-icon.tsx Outdated
Comment thread icons/netflix-icon.tsx Outdated
Comment thread icons/openai-icon.tsx Outdated
Comment thread icons/react.tsx Outdated
Comment thread lib/icons.ts
Comment thread public/r/netflix-icon.json
Comment thread public/r/openai-icon.json Outdated
Comment thread public/r/react.json
Comment thread public/r/tiktok-icon.json Outdated
Copy link
Copy Markdown
Contributor

@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 (2)
icons/index.ts (2)

32-33: Inconsistent naming convention for imported icons.

Alipay and Visa (line 191) don't follow the *Icon suffix naming convention used by all other icons in this file. Consider renaming for consistency:

♻️ Suggested naming alignment
 import AppStoreIcon from "./appstore-icon";
-import Alipay from "./alipay-icon";
+import AlipayIcon from "./alipay-icon";

And at line 191:

-import Visa from "./visa-icon";
+import VisaIcon from "./visa-icon";

Then update the ICON_LIST entries accordingly:

   {
     name: "alipay-icon",
-    icon: Alipay,
+    icon: AlipayIcon,
     keywords: ["ali", "pay", "alibaba", "zhifubao"],
   },
   {
     name: "visa-icon",
-    icon: Visa,
+    icon: VisaIcon,
     keywords: ["visa", "pay"],
   },

1343-1347: Consider expanding keywords for better discoverability.

Some new icon entries have sparse keywords. For example, visa-icon only has ["visa", "pay"]. Consider adding more relevant terms like "card", "payment", "credit", "debit" to improve search functionality.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4a7659d and 38bdfc4.

📒 Files selected for processing (5)
  • icons/index.ts
  • icons/netflix-icon.tsx
  • icons/openai-icon.tsx
  • icons/react-icon.tsx
  • icons/tiktok-icon.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • icons/openai-icon.tsx
🔇 Additional comments (3)
icons/react-icon.tsx (1)

1-96: LGTM! Well-structured animated icon component.

The implementation follows the established pattern for animated icons in this project, with proper use of forwardRef, useImperativeHandle, and motion/react animations. The staged animation (path drawing followed by center-dot bounce) creates a nice visual effect.

icons/netflix-icon.tsx (1)

1-80: LGTM! Clean implementation of the Netflix icon.

The component properly follows the established pattern with forwardRef, imperative handle, and hover-triggered animations. The path-drawing animation with stagger creates a nice sequential reveal effect for the Netflix "N" logo.

icons/tiktok-icon.tsx (1)

1-100: LGTM! Creative glitch effect implementation.

The three-layer approach with cyan and red offset paths creates an authentic TikTok-style glitch animation. Good use of a shared pathData variable to keep the paths in sync. The animation timing with slight delays (0.1s, 0.2s) between layers adds to the effect.

@forever-ivy forever-ivy changed the title feat: add new brand icons (alipay, appstore, netflix, openai, react, … feat: add new brand icons (alipay, appstore, netflix, openai, react,tiktok,visa,wechat) Jan 8, 2026
@Abhijit-Jha
Copy link
Copy Markdown
Member

In the icons, only the path is animated right now. Please improve the animation to make it feel more polished and intentional.

Copy link
Copy Markdown
Contributor

@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: 5

🤖 Fix all issues with AI agents
In @components/examples/payment-checkout.tsx:
- Around line 214-217: The initialization of uncontrolledSelected uses
methods[0]?.id, which yields undefined when methods is empty; update the
expression to defensively check methods.length (e.g., defaultSelectedMethodId ??
(methods.length ? methods[0].id : "")) and also ensure any derived value like
effectiveSelectedMethodId uses the same guard (check methods.length before
accessing methods[0].id) so selection logic never relies on an undefined id.

In @icons/netflix-icon.tsx:
- Line 8: The import in the icons/netflix-icon.tsx is inconsistent: replace the
current import statement that brings in motion and useAnimate from
"framer-motion" with the matching import from "motion/react" (i.e., import {
motion, useAnimate } from "motion/react") so it matches the other icon
components; update the import line only to ensure consistent package usage
across components that reference motion and useAnimate.

In @icons/visa-icon.tsx:
- Line 84: Replace the Chinese inline comment in icons/visa-icon.tsx with an
English comment; update the comment near the motion.path usage (the JSX that
uses motion.path and the initial prop) to something like: "Use motion.path and
initial to keep the element initially hidden but allow it to be revealed via
animation" so maintainers see the intent in English.

In @lib/icons.ts:
- Line 1: Remove the unused import of the symbol "path" (the import line `import
path from "path";`) from lib/icons.ts; delete the import statement and run the
linter/tsc to ensure no other references to "path" remain and that imports are
formatted correctly.

In @public/r/netflix-icon.json:
- Line 10: The component imports animation utilities from "framer-motion" but
the rest of the icon set uses "motion/react"; update the import to use
"motion/react" so NetflixIcon (and its useAnimate/animate usage and motion.svg)
use the same package entrypoint as the other icons to avoid bundling/install
discrepancies. Locate the top-level import that currently imports motion and
useAnimate and change it to import from "motion/react" (keeping the same named
imports: motion, useAnimate) and run a quick build to verify no other API
differences need adjustment.
🧹 Nitpick comments (6)
icons/paypal-icon.tsx (1)

68-74: Consider if duplicate path content serves the intended visual effect.

Both .p-top and .p-bottom groups contain identical path data (lines 69 and 73). While this appears intentional for the animation where the two layers move in opposite directions, the result when static is just a single visual element. This might relate to the reviewer's feedback about animations feeling like they "only animate the path."

If the goal is to create a richer visual effect, consider:

  1. Differentiating the two paths visually (e.g., one as fill, one as stroke)
  2. Using different path segments for top/bottom layers
  3. Adding additional animated elements beyond the mark itself

If the current approach is intentional for a specific effect, this can be safely ignored.

icons/appstore-icon.tsx (1)

12-46: Consider adding a sequence guard to prevent animation race conditions.

Unlike MastercardIcon and other icons in this PR that use sequenceRef to handle rapid hover in/out, this component lacks cancellation handling. If a user quickly hovers in and out, multiple animation sequences can overlap, causing visual artifacts.

Proposed fix
+  const sequenceRef = useRef(0);
+
   const start = useCallback(async () => {
+    sequenceRef.current++;
+    const currentSeq = sequenceRef.current;
+
     await Promise.all([
       animate(
         "path:not(.bg-none)",
         { pathLength: 0, opacity: 0 },
         { duration: 0 },
       ),
       animate(scope.current, { rotate: 0 }, { duration: 0 }),
     ]);

+    if (currentSeq !== sequenceRef.current) return;
+
     await animate(
       "path:not(.bg-none)",
       { pathLength: [0, 1], opacity: [0, 1] },
       {
         duration: 0.6,
         ease: "easeInOut",
         delay: stagger(0.1),
       },
     );

+    if (currentSeq !== sequenceRef.current) return;
+
     await animate(
       scope.current,
       { rotate: 360 },
       { duration: 0.8, ease: "easeInOut" },
     );
   }, [animate, scope]);

   const stop = useCallback(() => {
+    sequenceRef.current++;
     animate(
components/examples/payment-checkout.tsx (1)

241-251: Consider adding error handling and loading state for async payment.

The handlePay function awaits onPay but doesn't handle errors or provide user feedback during the async operation. Users won't see a loading indicator, and errors will propagate unhandled.

Suggested improvement
+  const [isPaying, setIsPaying] = useState(false);
+
   const handlePay = async () => {
     if (!selectedMethod || selectedMethod.disabled) return;
-    await onPay?.({
-      items,
-      method: selectedMethod,
-      subtotal,
-      shipping,
-      tax,
-      total,
-    });
+    setIsPaying(true);
+    try {
+      await onPay?.({
+        items,
+        method: selectedMethod,
+        subtotal,
+        shipping,
+        tax,
+        total,
+      });
+    } catch (error) {
+      console.error("Payment failed:", error);
+      // Consider exposing an onError callback
+    } finally {
+      setIsPaying(false);
+    }
   };

Then update the button:

   <Button
     type="button"
     onClick={handlePay}
-    disabled={!selectedMethod || selectedMethod.disabled}
+    disabled={!selectedMethod || selectedMethod.disabled || isPaying}
     className="h-11 w-full rounded-xl text-sm font-semibold shadow-md transition-shadow hover:shadow-lg"
   >
-    Pay {formatMoney(total, { locale, currency })}
+    {isPaying ? "Processing..." : `Pay ${formatMoney(total, { locale, currency })}`}
   </Button>
public/r/visa-icon.json (1)

8-12: Inconsistent displayName pattern.

The Visa icon uses displayName = "Visa" while other icons in this PR use the pattern "XxxIcon" (e.g., "MastercardIcon", "NetflixIcon"). Consider updating to "VisaIcon" for consistency.

Also, there's a Chinese comment in the embedded code (使用 motion.path 和 initial 确保初始隐藏,但可被动画控制显示) that should be translated to English for maintainability.

public/r/wechat-icon.json (1)

8-12: Consider adding sequence guard for animation cancellation.

Similar to the AppStoreIcon, this component lacks a sequenceRef to handle rapid hover in/out. The animation sequence with await could overlap if users hover quickly, potentially causing visual artifacts with the bubble animations.

public/r/alipay-icon.json (1)

10-10: Inconsistent component naming: Alipay vs *Icon pattern.

This component is named Alipay with displayName = "Alipay", while other icons follow the *Icon naming convention (e.g., OpenAIIcon, NetflixIcon, MastercardIcon). Consider renaming for consistency across the icon library.

Additionally, this component uses a wrapper <div> with onMouseEnter/onMouseLeave instead of motion.svg with onHoverStart/onHoverEnd like other icons. While functionally similar, maintaining a consistent pattern improves maintainability.

Proposed naming fix
-const Alipay = forwardRef<AnimatedIconHandle, AnimatedIconProps>(
+const AlipayIcon = forwardRef<AnimatedIconHandle, AnimatedIconProps>(
...
-Alipay.displayName = "Alipay";
+AlipayIcon.displayName = "AlipayIcon";

-export default Alipay;
+export default AlipayIcon;
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 38bdfc4 and 415fe7d.

📒 Files selected for processing (24)
  • components/examples/payment-checkout.tsx
  • icons/alipay-icon.tsx
  • icons/appstore-icon.tsx
  • icons/index.ts
  • icons/mastercard-icon.tsx
  • icons/netflix-icon.tsx
  • icons/paypal-icon.tsx
  • icons/react-icon.tsx
  • icons/visa-icon.tsx
  • icons/wechat-icon.tsx
  • lib/examples.ts
  • lib/icons.ts
  • public/r/alipay-icon.json
  • public/r/appstore-icon.json
  • public/r/mastercard-icon.json
  • public/r/netflix-icon.json
  • public/r/openai-icon.json
  • public/r/paypal-icon.json
  • public/r/react-icon.json
  • public/r/registry.json
  • public/r/tiktok-icon.json
  • public/r/visa-icon.json
  • public/r/wechat-icon.json
  • registry.json
🚧 Files skipped from review as they are similar to previous changes (7)
  • icons/alipay-icon.tsx
  • icons/wechat-icon.tsx
  • icons/index.ts
  • public/r/tiktok-icon.json
  • public/r/registry.json
  • icons/react-icon.tsx
  • public/r/appstore-icon.json
🧰 Additional context used
🧬 Code graph analysis (1)
components/examples/payment-checkout.tsx (2)
lib/utils.ts (1)
  • cn (4-6)
components/ui/button.tsx (1)
  • Button (61-61)
🔇 Additional comments (24)
public/r/paypal-icon.json (1)

1-20: LGTM!

The registry configuration is well-structured and follows the expected schema. The dependency on motion is appropriate for the animated icon component, and both required files (component and types) are properly declared.

lib/examples.ts (2)

2-2: LGTM!

The import is correctly added for the new example component.


19-28: LGTM!

The new Payment Checkout example entry follows the established registry pattern consistently. All required metadata fields are properly populated, and the structure aligns with the existing X Sidebar entry.

icons/visa-icon.tsx (4)

1-17: LGTM!

The imports and component setup follow the established pattern with proper TypeScript typing via AnimatedIconHandle and AnimatedIconProps.


18-43: LGTM!

The animation sequence is well-implemented with:

  • Proper sequence guard using sequenceRef to prevent race conditions
  • Coordinated animations with appropriate easing
  • Sequential reveals creating a polished effect

45-59: LGTM!

The stop callback properly cancels the animation sequence and resets to the default state. The imperative handle correctly exposes the animation controls.


61-106: LGTM!

The SVG structure and motion configuration are appropriate. Hover events are correctly wired to trigger the animations, and the component properly exports with a display name.

public/r/react-icon.json (1)

1-20: LGTM!

The registry configuration follows the correct schema and includes all necessary files with appropriate dependencies.

icons/paypal-icon.tsx (4)

1-12: LGTM!

The component setup follows the established pattern with proper imports, TypeScript typing, and animation scope initialization.


13-42: LGTM!

The animation callbacks are well-implemented:

  • Proper sequence guard prevents overlapping animations
  • Elements are positioned off-screen initially, then animated into view
  • Parallel animations with smooth easing create a cohesive effect

44-65: LGTM!

The imperative handle and SVG setup are correctly configured with hover event bindings and proper motion props.


76-82: LGTM!

The component properly closes with a display name set for debugging purposes.

icons/appstore-icon.tsx (1)

53-85: LGTM!

The SVG structure, prop handling, and imperative handle exposure follow the established pattern for animated icons in this codebase.

components/examples/payment-checkout.tsx (2)

61-170: LGTM!

The PaymentMethodOption component is well-implemented with proper accessibility (sr-only input, label association), clean hover handling for animated icons, and appropriate styling for selected/disabled states.


454-529: LGTM!

The example component provides comprehensive sample data demonstrating various payment methods and checkout items. Good for documentation and testing purposes.

icons/mastercard-icon.tsx (1)

5-92: LGTM!

Well-implemented animated icon with proper sequence guarding to handle rapid hover in/out. The animation flow (circles sliding in followed by frame drawing) creates a polished effect. The use of sequenceRef prevents race conditions during animation sequences.

lib/icons.ts (1)

104-111: New icons registered correctly.

The new brand icons (alipay, appstore, mastercard, netflix, openai, paypal, react, tiktok, visa, wechat) are properly added to the registry. Consider grouping them alphabetically with other icons for easier maintenance, though this is optional.

public/r/visa-icon.json (1)

1-20: Registry structure is correct.

The registry entry follows the shadcn/ui schema with proper dependencies and file declarations.

public/r/wechat-icon.json (1)

1-20: Registry entry structure is correct.

The wechat-icon registry entry properly declares dependencies and includes both the component and shared types files.

icons/netflix-icon.tsx (2)

18-75: LGTM!

The animation logic is well-implemented with proper sequence guarding. The chromatic aberration effect using ghost layers creates a polished, intentional animation that addresses the reviewer's feedback about making animations feel more refined.


77-130: LGTM!

Good use of a shared nPaths variable to avoid duplication across the three SVG groups. The SVG structure with ghost layers and main layer creates an effective visual effect.

public/r/openai-icon.json (1)

1-20: LGTM!

The OpenAI icon registry item is well-structured with consistent naming (OpenAIIcon), proper imports from motion/react, and a clean line-drawing animation implementation using pathLength with stagger effects.

public/r/mastercard-icon.json (1)

1-20: LGTM!

The Mastercard icon registry item follows consistent patterns: proper motion/react import, *Icon naming convention, and robust animation sequencing with the sequenceRef guard to prevent overlapping animations.

registry.json (1)

92-108: LGTM!

The new icon registry entries are well-structured and consistent:

  • All entries follow the established pattern with "motion" dependency
  • Each includes both the icon TSX file and shared types.ts
  • Entries are properly alphabetically ordered within the items array

Also applies to: 194-210, 2030-2046, 2132-2148, 2166-2182, 2234-2250, 2438-2454, 2914-2930, 3203-3219, 3271-3287

Comment thread components/examples/payment-checkout.tsx
Comment thread icons/netflix-icon.tsx Outdated
Comment thread icons/visa-icon.tsx Outdated
Comment thread lib/icons.ts Outdated
Comment thread public/r/netflix-icon.json Outdated
@forever-ivy forever-ivy changed the title feat: add new brand icons (alipay, appstore, netflix, openai, react,tiktok,visa,wechat) feat: add 10 new icons and payment checkout example Jan 9, 2026
@forever-ivy
Copy link
Copy Markdown
Author

forever-ivy commented Jan 9, 2026

10 new icons

alipay.mp4
appstore.mp4
mastercard.mp4
openai.mp4
paypal.mp4
react.mp4
tiktok.mp4
visa.mp4
wechat.mp4

Copy link
Copy Markdown
Contributor

@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: 3

🤖 Fix all issues with AI agents
In @lib/icons.ts:
- Line 372: Remove the stale configuration file public/r/hostel-icon.json that
is orphaned after changing the icon path in lib/icons.ts to "/icons/hotel-icon";
delete public/r/hostel-icon.json from the repository and ensure no references
remain (verify lib/icons.ts uses "/icons/hotel-icon" and
public/r/hotel-icon.json is the active config).

In @public/r/netflix-icon.json:
- Line 10: The animation feels flat because start/stop only set simple
opacity/scale/blur with identical easings; improve choreography in the start and
stop callbacks by adding staggered timings for ".ghost-left, .ghost-right,
.main-n" (use animate with delayed start or sequential awaits), vary easings per
element (e.g., "circOut" for paths, spring-like easing for main-n), replace or
augment scale tweens with a spring-style pop for ".main-n" (longer overshoot +
settle) and stagger path draws using small delays between each
"path:not(.bg-none)" animation; keep sequenceRef logic but orchestrate
animations with Promise.all of staggered animate calls so hover feels
intentional and brand-distinctive.
- Line 10: The start function contains an unexplained 30ms await (await new
Promise((resolve) => setTimeout(resolve, 30))) which is arbitrary and breaks the
sequenceRef pattern; either remove that delay, or replace it with a single
requestAnimationFrame-based await (e.g., await new
Promise(requestAnimationFrame)) to wait one render tick, or add a clear comment
above the line explaining why the micro-delay is required (e.g., to allow
DOM/svg paint before animations) and keep the requestAnimationFrame approach for
smoother timing; update the start useCallback (and mention sequenceRef and
animate usage) accordingly so the timing is deterministic and the sequence guard
(sequenceRef.current check) remains correct.
🧹 Nitpick comments (4)
lib/icons.ts (2)

102-109: Consider reordering for alphabetical consistency.

The alipay-icon and appstore-icon entries are inserted between arrow icons and banana, which breaks the alphabetical ordering pattern followed elsewhere in the array. For better maintainability, consider placing these icons at the beginning of the array (before or after accessibility-icon).

♻️ Suggested reordering

Move these entries to lines 2-9 (right after the array opening):

 export const ICONS = [
+  {
+    name: "alipay icon",
+    path: "/icons/alipay-icon",
+  },
+  {
+    name: "appstore icon",
+    path: "/icons/appstore-icon",
+  },
   {
     name: "accessibility icon",
     path: "/icons/accessibility-icon",
   },

And remove from their current position (lines 102-109).


426-429: Consider repositioning for alphabetical consistency.

The mastercard-icon entry is placed between mysql-icon and nodejs-icon, but alphabetically it should appear earlier (before meh-icon around line 411). This would maintain consistency with the ordering pattern used elsewhere in the array.

public/r/netflix-icon.json (2)

10-10: Hard-coded brand colors prevent theme customization.

The ghost effects use hard-coded Netflix brand colors (rgba(229, 9, 20, 0.6) and rgba(0, 255, 255, 0.6)). While this ensures brand consistency, it prevents the icon from adapting to theme changes or custom color schemes.

Consider making these colors configurable via props or CSS custom properties, allowing users to maintain brand colors while supporting theme variations.

♻️ Proposed approach using CSS custom properties

Define custom properties that default to Netflix colors:

<motion.svg
  ref={scope}
  onHoverStart={start}
  onHoverEnd={stop}
  xmlns="http://www.w3.org/2000/svg"
  width={size}
  height={size}
  viewBox="0 0 24 24"
  fill="none"
  stroke={color}
  strokeWidth={strokeWidth}
  strokeLinecap="round"
  strokeLinejoin="round"
  className={`cursor-pointer ${className}`}
  style={{
    overflow: "visible",
    "--ghost-left-color": "rgba(229, 9, 20, 0.6)",
    "--ghost-right-color": "rgba(0, 255, 255, 0.6)",
  } as React.CSSProperties}
>

Then use: stroke="var(--ghost-left-color)" and stroke="var(--ghost-right-color)".


10-10: Fragile animation selector relies on className.

The animation uses "path:not(.bg-none)" to target paths, which is fragile. If the background path's className changes or additional paths are added without this class, the animation will break or behave unexpectedly.

Consider using a more robust selector or explicitly targeting paths by className (e.g., .animatable-path).

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 415fe7d and cdf8cb6.

📒 Files selected for processing (5)
  • icons/netflix-icon.tsx
  • icons/visa-icon.tsx
  • lib/icons.ts
  • public/r/netflix-icon.json
  • public/r/visa-icon.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • public/r/visa-icon.json
  • icons/visa-icon.tsx
  • icons/netflix-icon.tsx
🔇 Additional comments (3)
public/r/netflix-icon.json (2)

14-16: LGTM!

The AnimatedIconProps and AnimatedIconHandle interfaces are well-defined with clear JSDoc documentation. The imperative handle pattern with startAnimation and stopAnimation methods provides a clean API for programmatic control of animations.


4-4: No issue found. The "motion" dependency is correctly declared and properly used throughout the codebase. The "motion/react" import path is the standard way to access the Motion library for React (version 12.23.26), distinct from the older "framer-motion" package.

Likely an incorrect or invalid review comment.

lib/icons.ts (1)

1-690: Removal of icons is safe—no references found in codebase.

The four removed icons (stadium-icon, sun-icon, text-icon, tree-icon) have no references in the TypeScript/JavaScript files, so their removal will not cause runtime errors or broken imports.

Comment thread lib/icons.ts
Comment thread public/r/netflix-icon.json Outdated
@forever-ivy
Copy link
Copy Markdown
Author

forever-ivy commented Jan 9, 2026

new example:payment checkout

image
example.mp4

Copy link
Copy Markdown
Contributor

@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

🤖 Fix all issues with AI agents
In @public/r/netflix-icon.json:
- Around line 7-12: The SVG lacks accessibility attributes; update the
AnimatedIconProps type to include an optional ariaLabel?: string and/or
ariaHidden?: boolean, accept those props in the NetflixIcon forwardRef signature
(alongside size, color, strokeWidth, className), and apply them to the root
motion.svg element (set role="img" and use aria-label={ariaLabel} when provided,
otherwise if ariaHidden is true set aria-hidden="true"); ensure NetflixIcon
still exports displayName and preserves behavior for decorative icons by
defaulting ariaHidden to false if not provided.
🧹 Nitpick comments (4)
public/r/netflix-icon.json (4)

7-12: Consider respecting prefers-reduced-motion.

Users with motion sensitivity may have prefers-reduced-motion: reduce enabled. Consider disabling or simplifying animations for these users to improve accessibility and comfort.

🎬 Suggested reduced-motion support
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;

const start = () => {
  if (prefersReducedMotion) {
    // Show final state immediately without animation
    animate(".main-n", { opacity: 1, scale: 1, filter: "blur(0px)" }, { duration: 0 });
    animate(".draw-path", { pathLength: 1 }, { duration: 0 });
    return;
  }
  
  // Existing animation code...
  animate(".ghost-left", { x: [-15, 0], opacity: [0, 0.6, 0] }, { duration: 0.4, ease: "circOut" });
  // ... rest of animations
};

7-12: Note: forwardRef is deprecated in React 19.

While forwardRef still works in React 19, the new ref-as-prop pattern is now preferred. This is an optional modernization and not urgent.

📘 React 19 ref-as-prop pattern

React 19 treats ref as a regular prop, eliminating the need for forwardRef. You can refactor to:

const NetflixIcon = ({ size = 24, color = "currentColor", strokeWidth = 2, className = "", ref }: AnimatedIconProps & { ref?: React.Ref<AnimatedIconHandle> }) => {
  const [scope, animate] = useAnimate();
  
  useImperativeHandle(ref, () => ({
    startAnimation: start,
    stopAnimation: stop,
  }));
  
  // ... rest of component
};

However, since forwardRef remains supported, this change can be deferred.


7-12: Ghost path colors are hardcoded and ignore the color prop.

The ghost effects use rgba(229, 9, 20, 0.6) (red) and rgba(0, 255, 255, 0.6) (cyan) regardless of the color prop value. This is likely intentional for Netflix branding, but it limits theming flexibility.

If color customization is desired, consider deriving ghost colors from the color prop or accepting additional props for ghost colors. Otherwise, this can remain as-is for brand consistency.


7-12: Consider upgrading to a newer motion package version.

The [email protected] dependency exists and is stable. However, the latest available version is 12.25.0, with several newer patch releases (12.23.27, 12.23.28, 12.24.x) also available. Update the dependency to benefit from recent bug fixes and improvements.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cdf8cb6 and 7d49e1d.

📒 Files selected for processing (2)
  • icons/netflix-icon.tsx
  • public/r/netflix-icon.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • icons/netflix-icon.tsx
🔇 Additional comments (3)
public/r/netflix-icon.json (3)

1-6: Registry metadata looks correct.

The registry structure follows the expected schema with appropriate motion dependency declaration.


13-17: Type definitions are well-structured.

The AnimatedIconProps and AnimatedIconHandle interfaces are clean, well-documented, and follow consistent patterns across the icon library.


18-20: Registry type declaration is correct.

The closing structure properly declares the registry type.

Comment thread public/r/netflix-icon.json
@forever-ivy forever-ivy changed the title feat: add 10 new icons and payment checkout example feat: add 9 new icons and payment checkout example Jan 9, 2026
Copy link
Copy Markdown
Contributor

@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 (2)
icons/index.ts (2)

32-33: Standardize import naming to follow the established pattern.

Import names Alipay and Visa lack the "Icon" suffix used by other icon imports (e.g., AppStoreIcon, MastercardIcon, PaypalIcon). Consistent naming improves code predictability and maintainability.

♻️ Proposed fix
-import AppStoreIcon from "./appstore-icon";
-import Alipay from "./alipay-icon";
+import AppStoreIcon from "./appstore-icon";
+import AlipayIcon from "./alipay-icon";
-import Visa from "./visa-icon";
+import VisaIcon from "./visa-icon";

Then update the corresponding ICON_LIST entries:

   {
     name: "alipay-icon",
-    icon: Alipay,
+    icon: AlipayIcon,
     keywords: ["ali", "pay", "alibaba", "zhifubao"],
   },
   {
     name: "visa-icon",
-    icon: Visa,
+    icon: VisaIcon,
     keywords: ["visa", "pay"],
   },

Also applies to: 192-192


389-393: Consider enriching keywords for better discoverability.

Some new icon entries have minimal keywords compared to similar icons. For example, visa-icon has only 2 keywords while mastercard-icon has 5. Enhanced keywords improve search and discovery.

Suggestions
   {
     name: "appstore-icon",
     icon: AppStoreIcon,
-    keywords: ["apple", "appstore"],
+    keywords: ["apple", "appstore", "ios", "app", "store", "download"],
   },
   {
     name: "react-icon",
     icon: ReactIcon,
-    keywords: ["icon", "react", "tech"],
+    keywords: ["react", "tech", "library", "frontend", "javascript"],
   },
   {
     name: "tiktok-icon",
     icon: TiktokIcon,
-    keywords: ["tech", "tiktok", "company"],
+    keywords: ["tech", "tiktok", "company", "social", "video", "media"],
   },
   {
     name: "visa-icon",
     icon: Visa,
-    keywords: ["visa", "pay"],
+    keywords: ["visa", "pay", "credit", "card", "payment"],
   },
   {
     name: "wechat-icon",
     icon: WechatIcon,
-    keywords: ["wechat", "company", "social"],
+    keywords: ["wechat", "company", "social", "chat", "messaging", "china"],
   },

Also applies to: 1259-1263, 1294-1298, 1349-1353, 1415-1419

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d49e1d and 1e1e656.

📒 Files selected for processing (4)
  • icons/index.ts
  • lib/icons.ts
  • public/r/registry.json
  • registry.json
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/icons.ts
  • registry.json
🔇 Additional comments (3)
public/r/registry.json (2)

1-6: Confirm the registry was regenerated using the build command.

Since this is an auto-generated file, ensure that npm run registry:build was executed to produce these changes rather than manually editing the JSON.


92-108: LGTM! All 9 new icon registry entries are properly structured.

The new entries for alipay-icon, appstore-icon, mastercard-icon, openai-icon, paypal-icon, react-icon, tiktok-icon, visa-icon, and wechat-icon:

  • Follow consistent structure with existing entries
  • Are correctly ordered alphabetically
  • Include proper dependencies and file references
  • Correctly omit the Netflix icon as mentioned in the PR commit messages

Also applies to: 194-210, 2030-2046, 2149-2165, 2217-2233, 2421-2437, 2897-2913, 3186-3202, 3254-3270

icons/index.ts (1)

32-33: All imported icon component files are present in the repository and properly implement the AnimatedIconProps interface.

@forever-ivy
Copy link
Copy Markdown
Author

@Abhijit-Jha I improved icon consistency and added a payment checkout example.What do you think of these designs?

@Abhijit-Jha
Copy link
Copy Markdown
Member

Interesting, sorry for the delay.
Could you please resolve the merge conflicts and confirm the following:

Is the component responsive?

When the animation is turned off, does hovering over the icons (not the text) keep the animation disabled?

@Abhijit-Jha
Copy link
Copy Markdown
Member

I’ve added the OpenAI, PayPal, and React icons. Feel free to remove them to avoid duplication

@forever-ivy forever-ivy force-pushed the feat/add-new-brand-icons branch from 1e1e656 to 87d51a0 Compare January 16, 2026 16:57
Copy link
Copy Markdown
Contributor

@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: 5

🤖 Fix all issues with AI agents
In `@icons/mastercard-icon.tsx`:
- Around line 54-57: The useImperativeHandle call is missing its dependency
array, risking stale closures for the exposed methods; update the
useImperativeHandle(ref, () => ({ startAnimation: start, stopAnimation: stop }))
invocation to include a dependency array that lists the start and stop callbacks
(e.g., useImperativeHandle(ref, () => ({ startAnimation: start, stopAnimation:
stop }), [start, stop]) ) so the ref methods are updated whenever those
functions change; ensure the referenced identifiers are the same start and stop
functions defined in this component.

In `@icons/tiktok-icon.tsx`:
- Around line 51-54: The call to useImperativeHandle in the icon component is
missing the dependency array which can lead to stale closures for the start/stop
functions; update the useImperativeHandle invocation to pass a dependency array
(e.g., [start, stop]) as the third argument so the imperative handle is
recreated when start or stop change, referencing the existing
useImperativeHandle(ref, () => ({ startAnimation: start, stopAnimation: stop }))
usage.

In `@icons/visa-icon.tsx`:
- Around line 56-59: The useImperativeHandle call that exposes startAnimation
and stopAnimation via the ref (useImperativeHandle(ref, () => ({ startAnimation:
start, stopAnimation: stop }))) is missing its dependency array; update this
invocation to include a dependency array that lists the start and stop functions
so the imperative handle updates when those functions change (i.e., provide
[start, stop] as the second argument to useImperativeHandle).

In `@icons/wechat-icon.tsx`:
- Around line 12-43: Add a sequence guard/cancel token to prevent stale
animations: introduce a sequence counter (e.g., animationSeq) stored in a ref,
increment it at the start of the hover handler, capture the current seq inside
start, and before awaiting or running any continuation (after the setTimeout
delay and before awaiting bubblesAnim) check that the captured seq still matches
the ref; if it doesn’t, abort returning early. Also ensure stop increments the
sequence (or sets a different token) to invalidate in-flight start runs, and
keep references to animate calls only for guarding — update start, stop,
bubblesAnim and any setTimeout usage accordingly similar to the pattern used in
MastercardIcon.

In `@public/r/paypal-icon.json`:
- Around line 9-11: The useImperativeHandle call inside the PaypalIcon component
lacks a dependency array which can cause the exposed
startAnimation/stopAnimation to become stale; update the useImperativeHandle
invocation that returns { startAnimation: start, stopAnimation: stop } to
include [start, stop] as its dependency array so the ref is updated whenever
start or stop change (refer to useImperativeHandle, start, stop, and
PaypalIcon).
♻️ Duplicate comments (1)
components/examples/payment-checkout.tsx (1)

214-217: Handle edge case when methods array is empty.

This concern was previously raised. If methods is empty, effectiveSelectedMethodId becomes an empty string and selectedMethod (line 234) becomes undefined. While handlePay guards against this, the UI still renders without meaningful content.

🧹 Nitpick comments (6)
components/examples/payment-checkout.tsx (1)

241-251: Consider adding error handling for the async onPay callback.

If onPay throws or rejects, the error will propagate as an unhandled promise rejection. Consider wrapping in try-catch to provide user feedback or at minimum prevent unhandled rejections.

💡 Optional: Add error handling
 const handlePay = async () => {
   if (!selectedMethod || selectedMethod.disabled) return;
-  await onPay?.({
-    items,
-    method: selectedMethod,
-    subtotal,
-    shipping,
-    tax,
-    total,
-  });
+  try {
+    await onPay?.({
+      items,
+      method: selectedMethod,
+      subtotal,
+      shipping,
+      tax,
+      total,
+    });
+  } catch (error) {
+    console.error("Payment failed:", error);
+    // Optionally: surface error to user via state
+  }
 };
icons/tiktok-icon.tsx (1)

14-40: Consider adding sequence guard for animation consistency.

Unlike other icons in this PR (MastercardIcon, VisaIcon, PaypalIcon), this component lacks the sequenceRef pattern to guard against overlapping animations during rapid hover in/out. This could cause visual glitches.

♻️ Proposed refactor
 const TiktokIcon = forwardRef<AnimatedIconHandle, AnimatedIconProps>(
   (
     { size = 24, color = "currentColor", strokeWidth = 2, className = "" },
     ref,
   ) => {
     const [scope, animate] = useAnimate();
+    const sequenceRef = useRef(0);

     const start = useCallback(async () => {
+      sequenceRef.current++;
+      const currentSeq = sequenceRef.current;
+
       await animate(
         "path:not(.bg-none)",
         { pathLength: 0, opacity: 0, x: 0, y: 0 },
         { duration: 0 },
       );

+      if (currentSeq !== sequenceRef.current) return;
+
       animate(
         ".main-path",
         { pathLength: [0, 1], opacity: [0, 1] },
         { duration: 1.5, ease: "easeInOut" },
       );
       // ... rest of animations
     }, [animate]);

     const stop = useCallback(() => {
+      sequenceRef.current++;
       animate(
         ".main-path",

Also add useRef to the imports on line 1.

icons/visa-icon.tsx (1)

10-10: Inconsistent component naming.

The component is named Visa with displayName "Visa", while other icons in this PR follow the <Name>Icon convention (e.g., MastercardIcon, TiktokIcon, PaypalIcon). Consider renaming for consistency.

♻️ Proposed refactor
-const Visa = forwardRef<AnimatedIconHandle, AnimatedIconProps>(
+const VisaIcon = forwardRef<AnimatedIconHandle, AnimatedIconProps>(
-Visa.displayName = "Visa";
+VisaIcon.displayName = "VisaIcon";

-export default Visa;
+export default VisaIcon;

Also applies to: 103-103

public/r/wechat-icon.json (1)

1-20: Consider adding animation cancellation for rapid hover scenarios.

Unlike the Visa icon which uses sequenceRef to cancel in-flight animations, WechatIcon doesn't have this protection. If users hover on/off rapidly, multiple animation sequences could overlap and cause visual glitches.

♻️ Suggested pattern (from visa-icon)

Add a useRef for sequence tracking in the component:

const sequenceRef = useRef(0);

const start = useCallback(async () => {
  sequenceRef.current++;
  const currentSeq = sequenceRef.current;
  
  // ... existing animation setup ...
  
  await new Promise((resolve) => setTimeout(resolve, 300));
  
  if (currentSeq !== sequenceRef.current) return; // bail if superseded
  
  // ... rest of animation ...
}, [animate]);
icons/openai-icon.tsx (1)

16-31: Animation duration is quite long at 2 seconds.

The path drawing animation takes 2 seconds with staggered delays, which may feel slow for a hover interaction. Consider reducing to ~0.8-1.2 seconds for a snappier feel, though this is a design preference.

Also, similar to WechatIcon, this component lacks the animation cancellation pattern (sequenceRef) that Visa uses. Rapid hover on/off could cause overlapping animations.

public/r/appstore-icon.json (1)

9-10: Make the rotation origin explicit for consistent spins.

In the embedded icons/appstore-icon.tsx content, consider setting transformOrigin (and transformBox) on the <motion.svg> so rotation stays centered across browsers.

♻️ Suggested tweak in embedded content
-        className={`cursor-pointer overflow-visible ${className}`}
+        className={`cursor-pointer overflow-visible ${className}`}
+        style={{ transformOrigin: "center", transformBox: "fill-box" }}
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1e1e656 and 87d51a0.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (28)
  • components/examples/payment-checkout.tsx
  • icons/alipay-icon.tsx
  • icons/appstore-icon.tsx
  • icons/index.ts
  • icons/mastercard-icon.tsx
  • icons/openai-icon.tsx
  • icons/paypal-icon.tsx
  • icons/react-icon.tsx
  • icons/tiktok-icon.tsx
  • icons/visa-icon.tsx
  • icons/wechat-icon.tsx
  • lib/examples.ts
  • lib/icons.ts
  • public/r/alipay-icon.json
  • public/r/appstore-icon.json
  • public/r/hotel-icon.json
  • public/r/mastercard-icon.json
  • public/r/netflix-icon.json
  • public/r/openai-icon.json
  • public/r/paypal-icon.json
  • public/r/react-icon.json
  • public/r/react.json
  • public/r/registry.json
  • public/r/tiktok-icon.json
  • public/r/travel-bag.json
  • public/r/visa-icon.json
  • public/r/wechat-icon.json
  • registry.json
🚧 Files skipped from review as they are similar to previous changes (10)
  • public/r/hotel-icon.json
  • icons/alipay-icon.tsx
  • icons/react-icon.tsx
  • icons/paypal-icon.tsx
  • public/r/registry.json
  • public/r/react-icon.json
  • public/r/react.json
  • public/r/alipay-icon.json
  • icons/index.ts
  • public/r/netflix-icon.json
🧰 Additional context used
🧬 Code graph analysis (1)
components/examples/payment-checkout.tsx (2)
lib/utils.ts (1)
  • cn (4-6)
components/ui/button.tsx (1)
  • Button (61-61)
🔇 Additional comments (28)
components/examples/payment-checkout.tsx (10)

1-19: LGTM!

Imports are well-organized and the IconComponent type alias properly captures the expected signature for animated icon components with ref forwarding.


20-36: LGTM!

The exported types PaymentMethod and CheckoutItem are well-structured with appropriate optional fields. The design allows flexibility while maintaining required core properties.


37-50: LGTM!

The formatMoney helper uses Intl.NumberFormat with a sensible fallback for invalid locale/currency combinations. Good defensive programming.


61-82: LGTM!

The animation control logic is well-implemented. The useEffect correctly stops animations when isAnimated becomes false, and the mouse event handlers respect the isAnimated flag. This addresses the reviewer concern about animations respecting the disabled state.


84-170: Good accessibility implementation.

The component properly uses a <label> with htmlFor, a visually-hidden radio input (sr-only), and respects the disabled state for both styling and interactivity. The role="radiogroup" is applied at the parent level (line 410), completing the accessible pattern.


172-195: LGTM!

The props interface follows React best practices with a clean controlled/uncontrolled pattern using selectedMethodId/defaultSelectedMethodId and showSummary/defaultShowSummary. The onPay callback signature provides all necessary checkout data.


259-270: LGTM!

The responsive container with conditional max-width based on effectiveShowSummary provides a polished UX. The layout prop on motion.div enables smooth width transitions.


273-369: Well-crafted summary panel animation.

The clipPath animation with custom easing [0.16, 1, 0.3, 1] provides a smooth reveal effect. The mode="popLayout" on AnimatePresence ensures proper layout recalculation during transitions.


409-430: LGTM!

The payment methods section properly uses role="radiogroup" with aria-label for screen reader accessibility, and each method is rendered with the accessible PaymentMethodOption component.


454-529: LGTM!

The example component provides good demonstration data with varied payment methods.

Minor note: The isAnimated ?? true on line 522 is redundant since PaymentCheckout already defaults isAnimated to true, but it doesn't cause any issues.

lib/examples.ts (2)

2-2: LGTM!

Import correctly references the new payment checkout example component.


19-28: LGTM!

The registry entry follows the established pattern and includes all required metadata. The filePath correctly points to the component location, and the description accurately reflects the component's features.

public/r/travel-bag.json (1)

1-20: LGTM!

The registry entry is correctly structured with proper schema, dependencies, and file paths. The embedded TravelBag component follows the established pattern for animated icons with proper useImperativeHandle dependency array.

icons/mastercard-icon.tsx (1)

59-96: LGTM!

The SVG structure, animation classes, and hover event bindings are well-implemented. The overflow: visible style correctly allows the slide-in animations to render outside the viewBox bounds.

public/r/paypal-icon.json (1)

1-8: LGTM!

The registry structure, schema reference, and file organization are consistent with other icon registry entries. The types.ts inclusion ensures the component has access to shared type definitions.

Also applies to: 12-20

icons/tiktok-icon.tsx (1)

56-96: LGTM!

The glitch-style animation with layered cyan and red paths creates an effective TikTok brand visual. The SVG structure and path reuse via pathData variable is clean.

icons/visa-icon.tsx (1)

61-101: LGTM!

The Visa icon implementation is well-structured with proper sequence guarding, transform origin handling, and initial opacity state. The card reveal animation with skew effect is polished.

public/r/visa-icon.json (1)

1-20: Registry entry looks good.

The Visa icon implementation follows the established pattern with forwardRef, imperative handles, and hover-triggered animations. The sequenceRef pattern for canceling in-flight animations when a new animation starts is a good approach to prevent animation conflicts.

icons/openai-icon.tsx (1)

42-67: Implementation follows established patterns.

The component correctly uses motion.svg with the scoped animate function, exposes imperative handles via useImperativeHandle, and wires hover events appropriately. The SVG paths render the OpenAI logo correctly.

public/r/openai-icon.json (1)

1-20: Registry entry is correct.

The import path issue from the previous review has been addressed - the component now correctly imports from "motion/react". The registry structure follows the shadcn schema and declares the correct motion dependency.

icons/appstore-icon.tsx (2)

12-46: Animation implementation is well-structured.

Good use of Promise.all for parallel initial state reset, and the sequential path drawing followed by rotation creates a polished effect. The durations (0.6s + 0.8s) feel appropriate for the animation complexity.

Minor consistency note: Like other icons in this PR, consider adding the sequenceRef cancellation pattern if rapid hover interactions cause visual issues in testing.


53-79: SVG structure and hover wiring looks correct.

The overflow-visible class ensures the rotation animation doesn't get clipped. The .bg-none class convention to exclude the background path from animation is clear and works well with the CSS selector.

icons/wechat-icon.tsx (1)

45-114: LGTM for the SVG structure and hover wiring.

public/r/tiktok-icon.json (1)

1-20: Registry entry looks consistent.

public/r/mastercard-icon.json (1)

9-10: Nice sequence guard to avoid overlapping animations.

lib/icons.ts (2)

102-109: New brand icon entries added consistently.

Also applies to: 426-429, 434-437, 474-477, 502-505, 594-597, 678-685


371-372: Hotel icon path alignment looks good.

registry.json (1)

92-108: Registry entries are structurally consistent.

All 9 new icon entries (alipay-icon, appstore-icon, mastercard-icon, openai-icon, paypal-icon, react-icon, tiktok-icon, visa-icon, wechat-icon) follow the established pattern and are correctly alphabetically sorted. No duplicate entries exist—the openai-icon, paypal-icon, and react-icon entries correspond to properly implemented icons already present in the codebase with matching files and exports in icons/index.ts.

Likely an incorrect or invalid review comment.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread icons/brand-mastercard-icon.tsx
Comment thread icons/brand-tiktok-icon.tsx
Comment thread icons/brand-visa-icon.tsx
Comment thread icons/wechat-icon.tsx
Comment thread public/r/paypal-icon.json
Copy link
Copy Markdown
Contributor

@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: 5

🤖 Fix all issues with AI agents
In `@icons/brand-appstore-icon.tsx`:
- Around line 48-51: Add a dependency array to the useImperativeHandle call so
the exposed handle updates when the start/stop callbacks change: in
icons/brand-appstore-icon.tsx update the useImperativeHandle(ref, () => ({
startAnimation: start, stopAnimation: stop })) invocation to include [start,
stop] as the third argument so start/stop references are not stale.

In `@icons/index.ts`:
- Around line 1445-1454: The icons array contains a duplicate entry with name
"wechat-icon" and icon WechatIcon; remove one of the duplicate objects so only a
single entry for "wechat-icon" remains (locate the two objects with name:
"wechat-icon" and icon: WechatIcon in the icons list and delete the redundant
one to avoid duplicate listings or ambiguous lookups).

In `@lib/icons.ts`:
- Around line 194-197: The icon entry in the icons list has an incorrect name
value (" icon") which will break UI display and search; update the object in
lib/icons.ts (the icon entry with path "/icons/tiktok-icon") to use a proper
name such as "tiktok icon" (or "TikTok icon") by replacing the value of the name
property so it correctly identifies the icon.

In `@public/r/brand-mastercard-icon.json`:
- Around line 8-12: The component BrandMastercardIcon has a mismatched
displayName ("MastercardIcon"); update the displayName to match the component by
changing BrandMastercardIcon.displayName to "BrandMastercardIcon" (or
alternatively rename the component to match the existing displayName), locating
the BrandMastercardIcon forwardRef declaration and the
BrandMastercardIcon.displayName assignment to make the change.

In `@public/r/registry.json`:
- Around line 2574-2590: The registry references missing icon components —
update either the source icons or the registry: either add missing icon
implementation files (create icons/openai-icon.tsx, icons/paypal-icon.tsx,
icons/react-icon.tsx, icons/appstore-icon.tsx, icons/mastercard-icon.tsx,
icons/tiktok-icon.tsx, icons/visa-icon.tsx) exporting the expected UI component
(matching the pattern used by existing icons like icons/alipay-icon.tsx and
icons/wechat-icon.tsx), or remove their entries from public/r/registry.json (the
objects whose "name" fields are "openai-icon", "paypal-icon", "react-icon",
"appstore-icon", "mastercard-icon", "tiktok-icon", "visa-icon") and re-run
whatever registry generation step you use so the file is consistent with the
icons/ directory.
♻️ Duplicate comments (3)
icons/brand-visa-icon.tsx (1)

56-59: Missing dependency array in useImperativeHandle.

This issue was previously flagged. The useImperativeHandle hook should include [start, stop] in its dependency array to avoid stale closures.

🐛 Proposed fix
-    useImperativeHandle(ref, () => ({
-      startAnimation: start,
-      stopAnimation: stop,
-    }));
+    useImperativeHandle(
+      ref,
+      () => ({
+        startAnimation: start,
+        stopAnimation: stop,
+      }),
+      [start, stop],
+    );
icons/brand-tiktok-icon.tsx (1)

51-54: Missing dependency array in useImperativeHandle.

This issue was previously flagged. Add [start, stop] as the dependency array.

🐛 Proposed fix
-    useImperativeHandle(ref, () => ({
-      startAnimation: start,
-      stopAnimation: stop,
-    }));
+    useImperativeHandle(
+      ref,
+      () => ({
+        startAnimation: start,
+        stopAnimation: stop,
+      }),
+      [start, stop],
+    );
icons/brand-mastercard-icon.tsx (1)

54-57: Missing dependency array in useImperativeHandle.

This issue was previously flagged. Add [start, stop] as the dependency array.

🐛 Proposed fix
-    useImperativeHandle(ref, () => ({
-      startAnimation: start,
-      stopAnimation: stop,
-    }));
+    useImperativeHandle(
+      ref,
+      () => ({
+        startAnimation: start,
+        stopAnimation: stop,
+      }),
+      [start, stop],
+    );
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 87d51a0 and 64b099a.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (15)
  • components/examples/payment-checkout.tsx
  • icons/brand-appstore-icon.tsx
  • icons/brand-mastercard-icon.tsx
  • icons/brand-tiktok-icon.tsx
  • icons/brand-visa-icon.tsx
  • icons/index.ts
  • lib/examples.ts
  • lib/icons.ts
  • public/r/brand-appstore-icon.json
  • public/r/brand-bags-fm-icon.json
  • public/r/brand-mastercard-icon.json
  • public/r/brand-tiktok-icon.json
  • public/r/brand-visa-icon.json
  • public/r/registry.json
  • registry.json
✅ Files skipped from review due to trivial changes (1)
  • public/r/brand-bags-fm-icon.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/examples.ts
🔇 Additional comments (13)
icons/brand-visa-icon.tsx (1)

10-43: LGTM!

The component implementation is well-structured. The use of sequenceRef for animation cancellation prevents race conditions when hover events fire rapidly. The start and stop callbacks properly include animate in their dependency arrays.

icons/brand-tiktok-icon.tsx (1)

16-49: LGTM!

The glitch animation effect using layered cyan and red paths is a creative implementation. The parallel animations in start() intentionally overlap without awaiting each other, which creates the desired chromatic aberration effect.

lib/icons.ts (1)

102-109: LGTM!

The new icon entries follow the established naming conventions and path patterns consistently.

Also applies to: 478-481, 486-489, 526-529, 554-557, 726-733

icons/brand-appstore-icon.tsx (1)

12-46: LGTM!

The animation implementation is clean. Using Promise.all for the initial reset ensures both path and rotation are synchronized before the staggered reveal begins. The rotation finale adds a polished touch to the animation.

icons/brand-mastercard-icon.tsx (1)

13-52: LGTM!

The animation implementation correctly uses sequenceRef to cancel pending animations when a new animation starts or when stop is called. This prevents visual glitches from overlapping animation sequences.

icons/index.ts (2)

32-58: New icon imports look consistent.

Also applies to: 132-175, 210-217


409-413: New icon registrations align with existing metadata patterns.

Also applies to: 479-493, 1121-1125, 1289-1298, 1309-1313, 1380-1383, 1566-1570

registry.json (1)

92-108: Registry additions follow the established schema.

Also applies to: 194-210, 721-737, 840-856, 1044-1060, 1078-1094, 2455-2471, 2574-2590, 2642-2658, 2846-2862, 3322-3338, 3611-3627, 3696-3712

public/r/brand-visa-icon.json (1)

1-20: BrandVisaIcon registry item looks good.

public/r/brand-appstore-icon.json (1)

1-20: BrandAppStoreIcon registry item looks good.

public/r/brand-tiktok-icon.json (1)

1-20: BrandTiktokIcon registry item looks good.

public/r/registry.json (1)

92-108: New icon entries follow the established registry pattern.

The added entries (alipay-icon, appstore-icon, brand-appstore-icon, brand-mastercard-icon, brand-tiktok-icon, brand-visa-icon, mastercard-icon, tiktok-icon, visa-icon, wechat-icon) correctly follow the existing structure with proper dependencies: ["motion"], file references to both the icon component and shared types.ts, and appropriate type: "registry:ui".

Also applies to: 194-210, 721-737, 840-856, 1044-1060, 1078-1094, 2455-2471, 3322-3338, 3611-3627, 3696-3712

public/r/brand-mastercard-icon.json (1)

1-20: Animation implementation is well-structured.

The component correctly uses:

  • sequenceRef pattern to cancel in-flight animations when hover state changes rapidly
  • useAnimate hook from motion/react for orchestrated multi-element animations
  • useImperativeHandle to expose programmatic animation control via ref
  • Proper cleanup in stop that resets all animated elements to their final visible state

The registry item structure with inline content and proper schema reference follows the expected format.

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment thread icons/brand-appstore-icon.tsx
Comment thread icons/index.ts
Comment thread lib/icons.ts
Comment thread public/r/brand-mastercard-icon.json
Comment thread public/r/registry.json Outdated
Copy link
Copy Markdown
Contributor

@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

🤖 Fix all issues with AI agents
In `@components/examples/payment-checkout.tsx`:
- Around line 234-252: selectedMethod can be undefined when methods is empty, so
update all places that access selectedMethod.disabled (including the Pay button
render and any conditional uses) to defensively check selectedMethod first;
specifically, change checks like selectedMethod.disabled to
(selectedMethod?.disabled ?? true) or guard with if (!selectedMethod ||
selectedMethod.disabled) before enabling the Pay button or proceeding, and
ensure handlePay remains consistent by returning early when !selectedMethod;
review usages of selectedMethod, effectiveSelectedMethodId, selectedMethodId,
handleSelect and the Pay button component to apply the defensive null/undefined
checks.
♻️ Duplicate comments (1)
icons/index.ts (1)

1414-1423: Remove the duplicate wechat-icon entry.
Two identical entries will produce duplicates in catalog/search results; keep only one.

🧹 Proposed fix
   {
     name: "wechat-icon",
     icon: WechatIcon,
     keywords: ["wechat", "company", "social"],
   },
-  {
-    name: "wechat-icon",
-    icon: WechatIcon,
-    keywords: ["wechat", "company", "social"],
-  },
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64b099a and 8576e60.

📒 Files selected for processing (4)
  • components/examples/payment-checkout.tsx
  • icons/index.ts
  • public/r/registry.json
  • registry.json
🧰 Additional context used
🧬 Code graph analysis (1)
components/examples/payment-checkout.tsx (2)
lib/utils.ts (1)
  • cn (4-6)
components/ui/button.tsx (1)
  • Button (61-61)
🔇 Additional comments (13)
components/examples/payment-checkout.tsx (10)

1-14: LGTM!

Imports are well-organized. The motion/react import path is correct for motion v12+.


16-35: LGTM!

Type definitions are clean and well-structured with appropriate optional fields.


37-50: LGTM!

Good defensive coding with try-catch and a reasonable fallback for invalid locale/currency combinations.


61-82: LGTM!

Good imperative animation control pattern using ref. The useEffect correctly stops animation when isAnimated becomes false.


84-171: LGTM!

Good accessibility pattern using native radio inputs with visual label wrapping. The conditional styling handles all states appropriately.


173-196: LGTM!

Well-designed props interface supporting both controlled and uncontrolled patterns with comprehensive callback support.


260-271: LGTM!

Good use of motion.div with layout prop for smooth container animations when summary visibility toggles.


274-370: LGTM!

The order summary panel uses AnimatePresence with mode="popLayout" correctly for smooth enter/exit animations. The clipPath animation creates a nice reveal effect.


410-431: LGTM!

Good accessibility with role="radiogroup" and aria-label. Each payment method option is correctly rendered with unique IDs.


455-534: LGTM!

Well-constructed example component with realistic sample data demonstrating the component's capabilities.

public/r/registry.json (1)

92-108: Registry additions are consistent with existing items.
The new entries match the established registry structure and reference the shared types file as expected.

Also applies to: 704-720, 823-839, 1027-1043, 1061-1077, 3577-3593

icons/index.ts (1)

32-58: New icon imports and list entries are wired correctly.
The new components are imported and registered with appropriate keywords.

Also applies to: 211-211, 403-407, 473-487, 1535-1539

registry.json (1)

92-108: Registry additions are consistent with existing items.
The new entries match the established registry structure and reference the shared types file as expected.

Also applies to: 704-720, 823-839, 1027-1043, 1061-1077, 3577-3593

✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.

Comment on lines +234 to +252
const selectedMethod =
methods.find((m) => m.id === effectiveSelectedMethodId) ?? methods[0];

const handleSelect = (methodId: string) => {
onSelectedMethodIdChange?.(methodId);
if (selectedMethodId === undefined) setUncontrolledSelected(methodId);
};

const handlePay = async () => {
if (!selectedMethod || selectedMethod.disabled) return;
await onPay?.({
items,
method: selectedMethod,
subtotal,
shipping,
tax,
total,
});
};
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.

⚠️ Potential issue | 🟡 Minor

Edge case: selectedMethod can be undefined when methods is empty.

While handlePay guards against !selectedMethod, the Pay button at line 437 uses selectedMethod.disabled which would throw if selectedMethod is undefined. The condition should be defensive.

Suggested fix
 <Button
   type="button"
   onClick={handlePay}
-  disabled={!selectedMethod || selectedMethod.disabled}
+  disabled={!selectedMethod || selectedMethod?.disabled}
   className="h-11 w-full rounded-xl text-sm font-semibold shadow-md transition-shadow hover:shadow-lg"
 >
🤖 Prompt for AI Agents
In `@components/examples/payment-checkout.tsx` around lines 234 - 252,
selectedMethod can be undefined when methods is empty, so update all places that
access selectedMethod.disabled (including the Pay button render and any
conditional uses) to defensively check selectedMethod first; specifically,
change checks like selectedMethod.disabled to (selectedMethod?.disabled ?? true)
or guard with if (!selectedMethod || selectedMethod.disabled) before enabling
the Pay button or proceeding, and ensure handlePay remains consistent by
returning early when !selectedMethod; review usages of selectedMethod,
effectiveSelectedMethodId, selectedMethodId, handleSelect and the Pay button
component to apply the defensive null/undefined checks.

@forever-ivy
Copy link
Copy Markdown
Author

paymentcheckout_example.mp4

@forever-ivy
Copy link
Copy Markdown
Author

@Abhijit-Jha Resolved merge conflicts

  • Implemented responsive design for components.

  • Ensured correct rendering when animations are disabled.

  • Removed redundant icons.

  • Updated naming for selected icons to align with conventions.

  • Ensured brand-related class names follow the established naming guidelines.

@Abhijit-Jha
Copy link
Copy Markdown
Member

I’ve left some comments for review. Please check them. @forever-ivy

Copy link
Copy Markdown
Contributor

@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

🤖 Fix all issues with AI agents
In `@registry.json`:
- Around line 704-722: The registry object contains duplicate "name" and
duplicate "path" keys which cause the second values ("brand-aistudio-icon" and
"icons/brand-aistudio-icon.tsx") to override the App Store entry; split this
into two distinct registry items so each has a unique "name"
("brand-appstore-icon" and "brand-aistudio-icon") and the correct single file
path in its "files" array (e.g., "icons/brand-appstore-icon.tsx" for the
appstore entry and "icons/brand-aistudio-icon.tsx" for the aistudio entry),
keeping the same "type", "registryDependencies", "dependencies",
"devDependencies", and the shared "icons/types.ts" file reference as needed.
♻️ Duplicate comments (2)
lib/icons.ts (1)

190-197: Fix the blank TikTok icon name.
The empty name will break name-based display/search.

🐛 Proposed fix
-    name: " icon",
+    name: "tiktok icon",
icons/index.ts (1)

1420-1429: Remove the duplicate WeChat entry.
Two identical entries can cause duplicate listings.

🧹 Proposed fix
-  {
-    name: "wechat-icon",
-    icon: WechatIcon,
-    keywords: ["wechat", "company", "social"],
-  },

Comment thread registry.json
@forever-ivy
Copy link
Copy Markdown
Author

@Abhijit-Jha I’ve resolved the merge conflicts and merged the latest changes from master into this branch

@forever-ivy
Copy link
Copy Markdown
Author

@Abhijit-Jha Apologies for the extra merge ,the conflict is now resolved and the branch is up to date with main. Thanks

@forever-ivy forever-ivy closed this Feb 2, 2026
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