feat: add 9 new icons and payment checkout example#63
feat: add 9 new icons and payment checkout example#63forever-ivy wants to merge 26 commits intoitshover:masterfrom
Conversation
|
@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. |
📝 WalkthroughWalkthroughAdds many new animated icon components and registry entries, plus a new PaymentCheckout example component and its registration entry. Changes
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
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
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 touseImperativeHandle.The
useImperativeHandlehook 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
useImperativeHandlecall 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 touseImperativeHandle.The
useImperativeHandlehook 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 touseImperativeHandle.The
useImperativeHandlecall 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.svgin a<div className="inline-flex items-center justify-center">, whileicons/react.tsxrenders themotion.svgdirectly. Additionally, theoverflowstyle is applied inline here (style={{ overflow: "visible" }}), whereasreact.tsxincludes 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 declaredmotiondependency, use the same import path.Proposed fix
-import { motion, useAnimate, stagger } from "framer-motion"; +import { motion, useAnimate, stagger } from "motion/react";
70-84: MissingonHoverEndhandler.Other icons in the PR (e.g., OpenAI, AppStore) use both
onHoverStartandonHoverEndto manage animation state. This component only hasonHoverStart={playSingleJitter}without a correspondingonHoverEnd. While the jitter is brief, addingonHoverEndwould 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
AlipaywithdisplayName = "Alipay", while other icons in the PR use theIconsuffix (e.g.,AppStoreIcon,OpenAIIcon,TiktokIcon,WechatIcon). For consistency, consider renaming toAlipayIcon.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 importstaggerfrom the same module asuseAnimate. 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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (22)
icons/alipay-icon.tsxicons/appstore-icon.tsxicons/index.tsicons/netflix-icon.tsxicons/openai-icon.tsxicons/react.tsxicons/tiktok-icon.tsxicons/visa-icon.tsxicons/wechat-icon.tsxlib/icons.tspublic/r/alipay-icon.jsonpublic/r/appstore-icon.jsonpublic/r/hotel-icon.jsonpublic/r/netflix-icon.jsonpublic/r/openai-icon.jsonpublic/r/react.jsonpublic/r/registry.jsonpublic/r/tiktok-icon.jsonpublic/r/travel-bag.jsonpublic/r/visa-icon.jsonpublic/r/wechat-icon.jsonregistry.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
pathDataas 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-iconto/icons/hotel-iconresolves 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 whencolorprop changes.The
startcallback depends oncolor, anduseEffectdepends onstart. This means changing thecolorprop 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.tsxreview.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
icons/index.ts (2)
32-33: Inconsistent naming convention for imported icons.
AlipayandVisa(line 191) don't follow the*Iconsuffix 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-icononly 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
📒 Files selected for processing (5)
icons/index.tsicons/netflix-icon.tsxicons/openai-icon.tsxicons/react-icon.tsxicons/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
pathDatavariable to keep the paths in sync. The animation timing with slight delays (0.1s, 0.2s) between layers adds to the effect.
|
In the icons, only the path is animated right now. Please improve the animation to make it feel more polished and intentional. |
There was a problem hiding this comment.
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-topand.p-bottomgroups 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:
- Differentiating the two paths visually (e.g., one as fill, one as stroke)
- Using different path segments for top/bottom layers
- 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
MastercardIconand other icons in this PR that usesequenceRefto 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
handlePayfunction awaitsonPaybut 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: InconsistentdisplayNamepattern.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 asequenceRefto handle rapid hover in/out. The animation sequence withawaitcould overlap if users hover quickly, potentially causing visual artifacts with the bubble animations.public/r/alipay-icon.json (1)
10-10: Inconsistent component naming:Alipayvs*Iconpattern.This component is named
AlipaywithdisplayName = "Alipay", while other icons follow the*Iconnaming convention (e.g.,OpenAIIcon,NetflixIcon,MastercardIcon). Consider renaming for consistency across the icon library.Additionally, this component uses a wrapper
<div>withonMouseEnter/onMouseLeaveinstead ofmotion.svgwithonHoverStart/onHoverEndlike 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
📒 Files selected for processing (24)
components/examples/payment-checkout.tsxicons/alipay-icon.tsxicons/appstore-icon.tsxicons/index.tsicons/mastercard-icon.tsxicons/netflix-icon.tsxicons/paypal-icon.tsxicons/react-icon.tsxicons/visa-icon.tsxicons/wechat-icon.tsxlib/examples.tslib/icons.tspublic/r/alipay-icon.jsonpublic/r/appstore-icon.jsonpublic/r/mastercard-icon.jsonpublic/r/netflix-icon.jsonpublic/r/openai-icon.jsonpublic/r/paypal-icon.jsonpublic/r/react-icon.jsonpublic/r/registry.jsonpublic/r/tiktok-icon.jsonpublic/r/visa-icon.jsonpublic/r/wechat-icon.jsonregistry.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
motionis 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
AnimatedIconHandleandAnimatedIconProps.
18-43: LGTM!The animation sequence is well-implemented with:
- Proper sequence guard using
sequenceRefto 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
PaymentMethodOptioncomponent 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
sequenceRefprevents 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
nPathsvariable 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 frommotion/react, and a clean line-drawing animation implementation usingpathLengthwith stagger effects.public/r/mastercard-icon.json (1)
1-20: LGTM!The Mastercard icon registry item follows consistent patterns: proper
motion/reactimport,*Iconnaming convention, and robust animation sequencing with thesequenceRefguard 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
|
10 new icons alipay.mp4appstore.mp4mastercard.mp4openai.mp4paypal.mp4react.mp4tiktok.mp4visa.mp4wechat.mp4 |
There was a problem hiding this comment.
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-iconandappstore-iconentries 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 afteraccessibility-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-iconentry is placed betweenmysql-iconandnodejs-icon, but alphabetically it should appear earlier (beforemeh-iconaround 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)andrgba(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)"andstroke="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
📒 Files selected for processing (5)
icons/netflix-icon.tsxicons/visa-icon.tsxlib/icons.tspublic/r/netflix-icon.jsonpublic/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
AnimatedIconPropsandAnimatedIconHandleinterfaces are well-defined with clear JSDoc documentation. The imperative handle pattern withstartAnimationandstopAnimationmethods 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.
There was a problem hiding this comment.
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 respectingprefers-reduced-motion.Users with motion sensitivity may have
prefers-reduced-motion: reduceenabled. 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:forwardRefis deprecated in React 19.While
forwardRefstill 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
refas a regular prop, eliminating the need forforwardRef. 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
forwardRefremains supported, this change can be deferred.
7-12: Ghost path colors are hardcoded and ignore thecolorprop.The ghost effects use
rgba(229, 9, 20, 0.6)(red) andrgba(0, 255, 255, 0.6)(cyan) regardless of thecolorprop value. This is likely intentional for Netflix branding, but it limits theming flexibility.If color customization is desired, consider deriving ghost colors from the
colorprop 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
📒 Files selected for processing (2)
icons/netflix-icon.tsxpublic/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
AnimatedIconPropsandAnimatedIconHandleinterfaces 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.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (2)
icons/index.ts (2)
32-33: Standardize import naming to follow the established pattern.Import names
AlipayandVisalack 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-iconhas only 2 keywords whilemastercard-iconhas 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
📒 Files selected for processing (4)
icons/index.tslib/icons.tspublic/r/registry.jsonregistry.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:buildwas 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 theAnimatedIconPropsinterface.
|
@Abhijit-Jha I improved icon consistency and added a payment checkout example.What do you think of these designs? |
|
Interesting, sorry for the delay. Is the component responsive? When the animation is turned off, does hovering over the icons (not the text) keep the animation disabled? |
|
I’ve added the OpenAI, PayPal, and React icons. Feel free to remove them to avoid duplication |
…tiktok, visa, wechat)
1e1e656 to
87d51a0
Compare
…tiktok, visa, wechat)
There was a problem hiding this comment.
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 whenmethodsarray is empty.This concern was previously raised. If
methodsis empty,effectiveSelectedMethodIdbecomes an empty string andselectedMethod(line 234) becomesundefined. WhilehandlePayguards 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 asynconPaycallback.If
onPaythrows 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
sequenceRefpattern 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
useRefto the imports on line 1.icons/visa-icon.tsx (1)
10-10: Inconsistent component naming.The component is named
Visawith displayName"Visa", while other icons in this PR follow the<Name>Iconconvention (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
sequenceRefto 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
useReffor 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.tsxcontent, consider settingtransformOrigin(andtransformBox) 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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (28)
components/examples/payment-checkout.tsxicons/alipay-icon.tsxicons/appstore-icon.tsxicons/index.tsicons/mastercard-icon.tsxicons/openai-icon.tsxicons/paypal-icon.tsxicons/react-icon.tsxicons/tiktok-icon.tsxicons/visa-icon.tsxicons/wechat-icon.tsxlib/examples.tslib/icons.tspublic/r/alipay-icon.jsonpublic/r/appstore-icon.jsonpublic/r/hotel-icon.jsonpublic/r/mastercard-icon.jsonpublic/r/netflix-icon.jsonpublic/r/openai-icon.jsonpublic/r/paypal-icon.jsonpublic/r/react-icon.jsonpublic/r/react.jsonpublic/r/registry.jsonpublic/r/tiktok-icon.jsonpublic/r/travel-bag.jsonpublic/r/visa-icon.jsonpublic/r/wechat-icon.jsonregistry.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
IconComponenttype alias properly captures the expected signature for animated icon components with ref forwarding.
20-36: LGTM!The exported types
PaymentMethodandCheckoutItemare well-structured with appropriate optional fields. The design allows flexibility while maintaining required core properties.
37-50: LGTM!The
formatMoneyhelper usesIntl.NumberFormatwith a sensible fallback for invalid locale/currency combinations. Good defensive programming.
61-82: LGTM!The animation control logic is well-implemented. The
useEffectcorrectly stops animations whenisAnimatedbecomes false, and the mouse event handlers respect theisAnimatedflag. This addresses the reviewer concern about animations respecting the disabled state.
84-170: Good accessibility implementation.The component properly uses a
<label>withhtmlFor, a visually-hidden radio input (sr-only), and respects thedisabledstate for both styling and interactivity. Therole="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/defaultSelectedMethodIdandshowSummary/defaultShowSummary. TheonPaycallback signature provides all necessary checkout data.
259-270: LGTM!The responsive container with conditional max-width based on
effectiveShowSummaryprovides a polished UX. Thelayoutprop onmotion.divenables smooth width transitions.
273-369: Well-crafted summary panel animation.The
clipPathanimation with custom easing[0.16, 1, 0.3, 1]provides a smooth reveal effect. Themode="popLayout"onAnimatePresenceensures proper layout recalculation during transitions.
409-430: LGTM!The payment methods section properly uses
role="radiogroup"witharia-labelfor screen reader accessibility, and each method is rendered with the accessiblePaymentMethodOptioncomponent.
454-529: LGTM!The example component provides good demonstration data with varied payment methods.
Minor note: The
isAnimated ?? trueon line 522 is redundant sincePaymentCheckoutalready defaultsisAnimatedtotrue, 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
filePathcorrectly 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
useImperativeHandledependency array.icons/mastercard-icon.tsx (1)
59-96: LGTM!The SVG structure, animation classes, and hover event bindings are well-implemented. The
overflow: visiblestyle 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
pathDatavariable 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. ThesequenceRefpattern 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.svgwith the scopedanimatefunction, exposes imperative handles viauseImperativeHandle, 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 correctmotiondependency.icons/appstore-icon.tsx (2)
12-46: Animation implementation is well-structured.Good use of
Promise.allfor 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
sequenceRefcancellation pattern if rapid hover interactions cause visual issues in testing.
53-79: SVG structure and hover wiring looks correct.The
overflow-visibleclass ensures the rotation animation doesn't get clipped. The.bg-noneclass 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.
There was a problem hiding this comment.
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 inuseImperativeHandle.This issue was previously flagged. The
useImperativeHandlehook 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 inuseImperativeHandle.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 inuseImperativeHandle.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
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (15)
components/examples/payment-checkout.tsxicons/brand-appstore-icon.tsxicons/brand-mastercard-icon.tsxicons/brand-tiktok-icon.tsxicons/brand-visa-icon.tsxicons/index.tslib/examples.tslib/icons.tspublic/r/brand-appstore-icon.jsonpublic/r/brand-bags-fm-icon.jsonpublic/r/brand-mastercard-icon.jsonpublic/r/brand-tiktok-icon.jsonpublic/r/brand-visa-icon.jsonpublic/r/registry.jsonregistry.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
sequenceReffor animation cancellation prevents race conditions when hover events fire rapidly. Thestartandstopcallbacks properly includeanimatein 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.allfor 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
sequenceRefto cancel pending animations when a new animation starts or whenstopis 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 sharedtypes.ts, and appropriatetype: "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:
sequenceRefpattern to cancel in-flight animations when hover state changes rapidlyuseAnimatehook from motion/react for orchestrated multi-element animationsuseImperativeHandleto expose programmatic animation control via ref- Proper cleanup in
stopthat resets all animated elements to their final visible stateThe registry item structure with inline
contentand proper schema reference follows the expected format.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
There was a problem hiding this comment.
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 duplicatewechat-iconentry.
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
📒 Files selected for processing (4)
components/examples/payment-checkout.tsxicons/index.tspublic/r/registry.jsonregistry.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/reactimport 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
useEffectcorrectly stops animation whenisAnimatedbecomes 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.divwithlayoutprop for smooth container animations when summary visibility toggles.
274-370: LGTM!The order summary panel uses
AnimatePresencewithmode="popLayout"correctly for smooth enter/exit animations. TheclipPathanimation creates a nice reveal effect.
410-431: LGTM!Good accessibility with
role="radiogroup"andaria-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.
| 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, | ||
| }); | ||
| }; |
There was a problem hiding this comment.
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.
paymentcheckout_example.mp4 |
|
@Abhijit-Jha Resolved merge conflicts
|
|
I’ve left some comments for review. Please check them. @forever-ivy |
There was a problem hiding this comment.
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"], - },
|
@Abhijit-Jha I’ve resolved the merge conflicts and merged the latest changes from master into this branch |
|
@Abhijit-Jha Apologies for the extra merge ,the conflict is now resolved and the branch is up to date with main. Thanks |

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
npm run checkpassesnpm run registry:buildpasses (for new icons)Release Notes
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.