-
Notifications
You must be signed in to change notification settings - Fork 3
[READY] Change Logo redirect behaviour to stay under /widget in the widget flow + introduce useReducedMotion #1028
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
✅ Deploy Preview for vortexfi ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for vortex-sandbox ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
The main purpose of the PR is what we discussed: when user is in the /widget flow and clicks on "Vortex" then they're going to stay under /widget and the flow resets. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This pull request introduces reduced-motion accessibility support across the frontend application and modifies the Logo click behavior to keep navigation within the /widget route when in widget mode.
Changes:
- Integrates
useReducedMotionhook from framer-motion across 13 animation components to respect users' motion preferences - Updates Logo redirect behavior to navigate to
/{-$locale}/widgetwhen in widget mode (instead of always going to root) - Adds
balanceUsdfield toAssetHubTokenDetailsWithBalanceinterface with placeholder "0.00" values - Introduces standardized animation constants (
easings,durations) inconstants/animations.ts - Improves performance by replacing
transition-allwith specific transition properties - Adds comprehensive Storybook stories for 7 components demonstrating reduced motion support
- Enhances type safety in API controllers with proper generic type parameters
Reviewed changes
Copilot reviewed 32 out of 33 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
packages/shared/src/tokens/types/assethub.ts |
Adds balanceUsd field to AssetHubTokenDetailsWithBalance interface |
apps/frontend/src/hooks/useOnchainTokenBalances.ts |
Updates all balance initialization to include balanceUsd field |
apps/frontend/src/constants/animations.ts |
Adds standardized easing curves, durations, and animation variants |
apps/frontend/src/components/Navbar/hooks/useNavbarHandlers.ts |
Updates logo navigation to respect widget mode context |
apps/frontend/src/components/Navbar/index.tsx |
Adds z-index to header for proper layering |
apps/frontend/src/components/menus/Menu/index.tsx |
Integrates useReducedMotion for accessible menu animations |
apps/frontend/src/components/TokenSelection/** |
Adds reduced motion support to network/token selection animations |
apps/frontend/src/components/TermsAndConditions/index.tsx |
Implements reduced motion for terms acceptance animations |
apps/frontend/src/components/Stepper/** |
Updates stepper animations with reduced motion and specific transitions |
apps/frontend/src/components/RampToggle/index.tsx |
Adds reduced motion support for toggle indicator animation |
apps/frontend/src/components/KycLevel2Toggle/index.tsx |
Implements reduced motion for document type toggle |
apps/frontend/src/components/CollapsibleCard/index.tsx |
Refactors to use grid-template-rows animation with reduced motion |
apps/frontend/src/components/Accordion/index.tsx |
Removes layout animations and adds reduced motion support |
apps/frontend/src/components/Navbar/MobileMenu.tsx |
Updates mobile menu with reduced motion variants |
apps/frontend/src/components/Avenia/** |
Adds reduced motion to KYC flow animations |
apps/frontend/src/components/EmailForm/index.tsx |
Replaces transition-all with specific properties |
apps/frontend/src/stories/** |
Adds 7 new Storybook stories with reduced motion test cases |
apps/frontend/.storybook/main.ts |
Removes unnecessary type annotation |
apps/api/src/api/controllers/** |
Enhances type safety with proper Request generic parameters |
Comments suppressed due to low confidence (2)
apps/frontend/src/components/Navbar/MobileMenu.tsx:107
- When reduced motion is enabled, the parent
motion.divusesreducedMotionVariantsbut the child elements (lines 79, 93, 107) still usemenuItemVariantsandbuttonVariantswhich include animations. Since the parent doesn't have staggerChildren in reduced motion mode, the child animations will still execute. Consider either passingshouldReduceMotiondown and conditionally using simpler variants for children, or ensure child variants also respect reduced motion by checking the parent's animation state.
variants={shouldReduceMotion ? reducedMotionVariants : menuVariants}
>
<nav className="group flex flex-col px-6 py-4">
<motion.div variants={menuItemVariants}>
<Link
activeProps={{
className: "text-white group-hover:[&:not(:hover)]:text-gray-400"
}}
className="block w-full px-2 py-3 text-left text-gray-400 text-xl transition-colors hover:text-white"
onClick={onMenuItemClick}
params={params}
to="/{-$locale}"
>
{t("components.navbar.individuals")}
</Link>
</motion.div>
<motion.div variants={menuItemVariants}>
<Link
activeProps={{
className: "text-white group-hover:[&:not(:hover)]:text-gray-400"
}}
className="block w-full px-2 py-3 text-left text-gray-400 text-xl transition-colors hover:text-white"
onClick={onMenuItemClick}
params={params}
to="/{-$locale}/business"
>
{t("components.navbar.business")}
</Link>
</motion.div>
<motion.div className="mt-6 mb-4" variants={buttonVariants}>
apps/frontend/src/components/TermsAndConditions/index.tsx:33
- The
fadeOutAnimationobject (lines 15-19) is used in the exit animation at line 33, but it doesn't check for reduced motion preferences. When users have reduced motion enabled, the exit animation should be instant. Consider conditionally applying this animation based onuseReducedMotion()hook, similar to how other animations in this component are handled.
const fadeOutAnimation = {
opacity: [1, 1, 0],
scale: [1, 1.05, 0],
transition: { duration: durations.slow, ease: easings.easeOutCubic }
};
export const TermsAndConditions = (props: TermsAndConditionsProps) => {
const { termsAccepted } = props;
return <AnimatePresence mode="wait">{!termsAccepted && <TermsAndConditionsContent {...props} />}</AnimatePresence>;
};
const TermsAndConditionsContent = ({
toggleTermsChecked,
setTermsError,
termsChecked,
termsError
}: TermsAndConditionsProps) => (
<motion.div exit={fadeOutAnimation} key="terms-conditions">
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| )} | ||
| </AnimatePresence> | ||
| <div | ||
| className={`grid transition-[grid-template-rows] duration-150 ease-out ${className || ""}`} |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CSS class uses hardcoded duration-150 but the animation durations should respect reduced motion preferences. When prefers-reduced-motion is enabled, the CSS transition should also be instant. Consider adding the motion-reduce:transition-none utility class to the div at line 15-18.
| className={`grid transition-[grid-template-rows] duration-150 ease-out ${className || ""}`} | |
| className={`grid transition-[grid-template-rows] duration-150 ease-out motion-reduce:transition-none ${className || ""}`} |
| )} | ||
| </AnimatePresence> | ||
| <div | ||
| className={`grid transition-[grid-template-rows] duration-300 ease-out ${className}`} |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CSS class uses hardcoded duration-300 but should respect reduced motion preferences. Consider adding the motion-reduce:transition-none utility class to ensure the grid-template-rows transition is also instant when users have reduced motion enabled.
| className={`grid transition-[grid-template-rows] duration-300 ease-out ${className}`} | |
| className={`grid transition-[grid-template-rows] duration-300 ease-out motion-reduce:transition-none ${className}`} |
| )} | ||
| </AnimatePresence> | ||
| <div | ||
| className="grid transition-[grid-template-rows] duration-300 ease-out" |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The CSS class uses hardcoded duration-300 but should respect reduced motion preferences. Consider adding the motion-reduce:transition-none utility class to ensure the grid-template-rows transition is also instant when users have reduced motion enabled.
| className="grid transition-[grid-template-rows] duration-300 ease-out" | |
| className="grid transition-[grid-template-rows] duration-300 ease-out motion-reduce:transition-none" |
|
|
||
| export const Navbar = () => ( | ||
| <header className="relative"> | ||
| <header className="relative z-60"> |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
z-60 is not a standard Tailwind CSS utility class. Tailwind's default z-index scale includes z-0, z-10, z-20, z-30, z-40, z-50, and z-auto, but not z-60. If this is intended to be a custom z-index value, it should be defined in the Tailwind config file. Otherwise, consider using z-50 or defining a custom value in the Tailwind configuration.
| <header className="relative z-60"> | |
| <header className="relative z-50"> |
| fast: 0.15, // 100ms - micro-interactions (hover states) | ||
| micro: 0.1, // 150ms - tooltips, dropdowns |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment for durations.fast states "100ms" but the value is 0.15 which equals 150ms. Similarly, durations.micro states "150ms" but has value 0.1 which equals 100ms. These comments appear to be swapped.
| fast: 0.15, // 100ms - micro-interactions (hover states) | |
| micro: 0.1, // 150ms - tooltips, dropdowns | |
| fast: 0.1, // 100ms - micro-interactions (hover states) | |
| micro: 0.15, // 150ms - tooltips, dropdowns |
| }; | ||
|
|
||
| const InteractiveDemo = () => { | ||
| const [openItems, setOpenItems] = useState<string[]>(["item-1"]); |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable setOpenItems.
| const [openItems, setOpenItems] = useState<string[]>(["item-1"]); | |
| const [openItems] = useState<string[]>(["item-1"]); |
| shouldReduceMotion | ||
| ? { duration: 0 } | ||
| : { | ||
| delay: isOpen ? durations.fast : 0, |
Copilot
AI
Jan 30, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This use of variable 'isOpen' always evaluates to true.
| delay: isOpen ? durations.fast : 0, | |
| delay: durations.fast, |
…ect animation durations, and cleanup unused vars Co-authored-by: ebma <[email protected]>
Address code review feedback: accessibility, z-index fix, and cleanup
📋 Summary
This PR adjusts the widget flow so clicking the Logo keeps navigation under the
/widgetroute, and introduces auseReducedMotionhook to respect users’ reduced-motion preferences for animations.🎯 Key Changes
/widgetrather than bouncing to a broader app route.useReducedMotionto detect reduced-motion preference and allow disabling/reducing animations accordingly.📛 Breaking changes: No.
🆙 Dependencies: No.
⚙️ Configuration: No.
✅ Review Focus Areas
/widget(including nested routes, query params, and back/forward browser navigation).useReducedMotionis wired to the correct animation/transition paths and that “reduced motion” mode results in usable UI (no missing state changes that were previously animation-driven)./widget(e.g., hardcoded links or redirects).