Add reusable dashboard animation components#126
Conversation
🤖 CodeAnt AI — Review Status
Updated in place by CodeAnt AI · last 5 reviews |
📝 WalkthroughWalkthroughChangesDashboard animation system
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant Dashboard
participant AnimatedCard
participant AnimationWrapper
participant useInViewAnimation
Dashboard->>AnimatedCard: render KPI with staggered delay
AnimatedCard->>AnimationWrapper: forward children and scale type
AnimationWrapper->>useInViewAnimation: observe viewport
useInViewAnimation-->>AnimationWrapper: return visibility and reduced-motion state
AnimationWrapper-->>Dashboard: render animated or plain content
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
| animate={isInView ? "visible" : "hidden"} | ||
| transition={{ | ||
| delay, | ||
| ...(duration ? { duration } : {}), |
There was a problem hiding this comment.
Suggestion: The duration override uses a truthy check, so passing duration={0} is treated as “not provided” and silently ignored. This makes zero-duration transitions impossible and can cause unexpected animation timing; switch to an explicit undefined check so 0 remains a valid value. [falsy zero check]
Severity Level: Major ⚠️
- ⚠️ Zero-duration animations impossible when using AnimationWrapper.
- ⚠️ Future dashboard animation timing overrides behave unexpectedly.Steps of Reproduction ✅
1. In `frontend/src/components/Animation/AnimationWrapper.tsx:25-32`, note
`AnimationWrapper` accepts an optional `duration?: number` prop and passes it into the
Framer Motion `transition` object at lines 49-52.
2. Observe at `frontend/src/components/Animation/AnimationWrapper.tsx:49-52` that
`transition` is constructed as `transition={{ delay, ...(duration ? { duration } : {}),
}}`, meaning only truthy `duration` values are spread.
3. A developer who wants an instant (zero-duration) animation uses `AnimationWrapper`
directly, e.g. in `frontend/src/pages/Dashboard.tsx` alongside existing imports (lines
3-7), by rendering `<AnimationWrapper duration={0}>...</AnimationWrapper>` for a dashboard
section.
4. At runtime, because `duration` is `0` (falsy), the spread `...(duration ? { duration }
: {})` contributes an empty object; Framer Motion receives no `duration` override and
applies its default timing, so the animation is not instant despite `duration={0}` being
passed.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/components/Animation/AnimationWrapper.tsx
**Line:** 51:51
**Comment:**
*Falsy Zero Check: The duration override uses a truthy check, so passing `duration={0}` is treated as “not provided” and silently ignored. This makes zero-duration transitions impossible and can cause unexpected animation timing; switch to an explicit undefined check so `0` remains a valid value.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fixThere was a problem hiding this comment.
Pull request overview
This PR introduces a small, reusable Framer Motion-based animation system (variants + in-view hook + wrapper components) and applies it to key Dashboard areas to provide viewport-triggered, staggered entrance animations with reduced-motion support.
Changes:
- Added shared animation variants (
fade,slide,scale) and auseInViewAnimationhook for viewport entry +prefers-reduced-motion. - Introduced reusable components:
AnimationWrapper,AnimatedCard,FadeIn, andSlideIn. - Applied staggered KPI animations and added a
FadeInwrapper around the Live Collision Timeline section.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/utils/animationConfig.ts | Adds reusable Framer Motion variant presets (fade/slide/scale). |
| frontend/src/hooks/useInViewAnimation.ts | Adds a shared in-view + reduced-motion hook for animation triggering. |
| frontend/src/components/Animation/AnimationWrapper.tsx | Core wrapper that connects in-view logic to motion variants. |
| frontend/src/components/Animation/AnimatedCard.tsx | Convenience wrapper for scale-in card animations. |
| frontend/src/components/Animation/FadeIn.tsx | Convenience wrapper for fade-in animations. |
| frontend/src/components/Animation/SlideIn.tsx | Convenience wrapper for slide-up animations. |
| frontend/src/pages/Dashboard.tsx | Applies new reusable animations to KPI cards and the collision timeline section. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| import AnimatedCard from "@/components/Animation/AnimatedCard"; | ||
| import FadeIn from "@/components/Animation/FadeIn"; | ||
| import SlideIn from "@/components/Animation/SlideIn"; |
| <FadeIn delay={0.2}> | ||
| <div className="lg:col-span-2 flex flex-col min-h-0 min-w-0"> <div className="flex justify-between items-center mb-3"> |
| <motion.div | ||
| ref={ref as React.Ref<HTMLDivElement>} | ||
| className={className} |
| ] | ||
| : null; | ||
|
|
||
| const conjunctions = collisions.data?.data ?? []; |
There was a problem hiding this comment.
Suggestion: The collision timeline empty-state check only looks at conjunctions.length, but conjunctions is defaulted to [] even when the API request fails. This will incorrectly show “NO ACTIVE CONJUNCTION RISKS DETECTED” during backend errors; add an explicit collisions.isError branch before the empty-state message. [logic error]
Severity Level: Major ⚠️
❌ Backend outages misreported as zero conjunction risk state.
⚠️ Operators may ignore active collision risks during failures.Steps of Reproduction ✅
1. Note the collisions query usage in `Dashboard` at
`frontend/src/pages/Dashboard.tsx:58`, which calls `useCollisions({ size: 5 })`; the hook
is defined in `frontend/src/hooks/useApi.ts:47-53` and uses `useQuery` with `queryFn: ()
=> api.getCollisions(params)`.
2. Observe that `conjunctions` is derived at `Dashboard.tsx:113` as `const conjunctions =
collisions.data?.data ?? [];`, defaulting to an empty array when `collisions.data` is
`undefined` (for example, after a failed query).
3. In the Live Collision Timeline rendering at `Dashboard.tsx:194-212`, the branch is
`collisions.isLoading ? skeleton : conjunctions.length === 0 ? empty-state : map`, with no
explicit `collisions.isError` handling.
4. When `api.getCollisions` fails (React Query sets `collisions.isError = true` and
`collisions.data` undefined), `collisions.isLoading` is false and `conjunctions` becomes
`[]`, so the component renders the empty-state block "NO ACTIVE CONJUNCTION RISKS
DETECTED" at `Dashboard.tsx:200-205`, incorrectly signalling a clear catalog during a
backend error rather than showing an outage message.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/pages/Dashboard.tsx
**Line:** 113:113
**Comment:**
*Logic Error: The collision timeline empty-state check only looks at `conjunctions.length`, but `conjunctions` is defaulted to `[]` even when the API request fails. This will incorrectly show “NO ACTIVE CONJUNCTION RISKS DETECTED” during backend errors; add an explicit `collisions.isError` branch before the empty-state message.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix|
|
||
| const conjunctions = collisions.data?.data ?? []; | ||
| const agentRuns = agents.data?.data ?? []; | ||
| const agentRuns = agents.data?.data ?? []; |
There was a problem hiding this comment.
Suggestion: The agent stream uses decisions.length === 0 as the only non-loading fallback, but agentRuns is defaulted to [] on query failure, so API errors are displayed as “No agent runs active.” Add an agents.isError branch to avoid presenting outage conditions as valid no-data state. [logic error]
Severity Level: Major ⚠️
❌ Agent service outages shown as normal no-runs state.
⚠️ Operators lack agent reasoning visibility during backend failures.Steps of Reproduction ✅
1. Note the agents query usage at `frontend/src/pages/Dashboard.tsx:59`, which calls
`useAgentRuns({ size: 6 })`; the hook is defined in `frontend/src/hooks/useApi.ts:99-105`
and uses `useQuery` with `queryFn: () => api.getAgentRuns(params)`.
2. Observe that `agentRuns` is derived as `const agentRuns = agents.data?.data ?? [];` at
`Dashboard.tsx:114`, so when the agents query errors and `agents.data` is `undefined`,
`agentRuns` becomes an empty array.
3. The decisions list is built at `Dashboard.tsx:117-122` by `agentRuns.flatMap(...)` and
then sliced, and the AI Reasoning Stream UI at `Dashboard.tsx:258-309` renders
`agents.isLoading ? skeleton : decisions.length === 0 ? "No agent runs active" empty-state
: list`, with no `agents.isError` branch.
4. When `api.getAgentRuns` fails (React Query sets `agents.isError = true` and
`agents.data` undefined), `agents.isLoading` is false, `agentRuns` is `[]`, and
`decisions` is `[]`, causing the UI to show the "No agent runs active" message at
`Dashboard.tsx:275-282` instead of indicating an agent service outage, misrepresenting
backend failures as a normal no-runs condition.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/pages/Dashboard.tsx
**Line:** 114:114
**Comment:**
*Logic Error: The agent stream uses `decisions.length === 0` as the only non-loading fallback, but `agentRuns` is defaulted to `[]` on query failure, so API errors are displayed as “No agent runs active.” Add an `agents.isError` branch to avoid presenting outage conditions as valid no-data state.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix| <FadeIn delay={0.2}> | ||
| <div className="lg:col-span-2 flex flex-col min-h-0 min-w-0"> <div className="flex justify-between items-center mb-3"> |
There was a problem hiding this comment.
Suggestion: Wrapping the left timeline panel in FadeIn makes the wrapper element the actual grid item, so the lg:col-span-2 class on the inner div no longer affects grid layout. On large screens this breaks the intended 2/3 + 1/3 column split. Move the column-span class to the animated wrapper (via className) or apply animation directly to the grid item. [css layout issue]
Severity Level: Critical 🚨
❌ Large-screen dashboard layout loses intended 2/3 split.
⚠️ Collision timeline cramped, reduces readability for operators.Steps of Reproduction ✅
1. Open the dashboard view that renders the `Dashboard` component defined at
`frontend/src/pages/Dashboard.tsx:56-124` in a large-screen browser (lg breakpoint).
2. Inspect the bottom layout section at `frontend/src/pages/Dashboard.tsx:178`, which uses
`className="... grid grid-cols-1 lg:grid-cols-3 ..."`, expecting a 2/3 + 1/3 column split.
3. Note the left child is `<FadeIn delay={0.2}>` at `Dashboard.tsx:181` wrapping a nested
`<div className="lg:col-span-2 flex flex-col min-h-0 min-w-0">` at `Dashboard.tsx:182`,
and the right child is a plain `<div className="flex flex-col min-h-0">` at
`Dashboard.tsx:259`.
4. From `frontend/src/components/Animation/FadeIn.tsx:11-12` and `AnimationWrapper` in
`frontend/src/components/Animation/AnimationWrapper.tsx:25-56`, confirm `FadeIn` renders a
`motion.div` wrapper as the grid child and does not forward children's layout classes;
since `lg:col-span-2` lives on the inner `div`, the grid item has no column-span, so on
large screens the collision timeline and reasoning stream render as equal-width one-column
items instead of the intended 2/3 + 1/3 split.(Use Cmd/Ctrl + Click for best experience)
Prompt for AI Agent 🤖
This is a comment left during a code review.
**Path:** frontend/src/pages/Dashboard.tsx
**Line:** 181:182
**Comment:**
*Css Layout Issue: Wrapping the left timeline panel in `FadeIn` makes the wrapper element the actual grid item, so the `lg:col-span-2` class on the inner `div` no longer affects grid layout. On large screens this breaks the intended 2/3 + 1/3 column split. Move the column-span class to the animated wrapper (via `className`) or apply animation directly to the grid item.
Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fixThere was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@frontend/src/components/Animation/AnimationWrapper.tsx`:
- Around line 1-5: Update AnimationWrapper’s React type imports to include Ref,
then change the ref cast from React.Ref<HTMLDivElement> to Ref<HTMLDivElement>
so the module no longer relies on an unimported React namespace.
In `@frontend/src/utils/animationConfig.ts`:
- Around line 6-12: Remove the per-variant transition timing from the animation
configuration, including the visible variant and related pose definitions,
leaving only opacity, scale, and other visual state properties. Ensure
AnimationWrapper remains the sole owner of delay and duration so FadeIn and
AnimatedCard can control timing per instance.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: c3547cd2-b2ae-467a-829c-aaa97f776417
📒 Files selected for processing (7)
frontend/src/components/Animation/AnimatedCard.tsxfrontend/src/components/Animation/AnimationWrapper.tsxfrontend/src/components/Animation/FadeIn.tsxfrontend/src/components/Animation/SlideIn.tsxfrontend/src/hooks/useInViewAnimation.tsfrontend/src/pages/Dashboard.tsxfrontend/src/utils/animationConfig.ts
| import type { ReactNode } from "react"; | ||
| import { motion } from "framer-motion"; | ||
|
|
||
| import { fadeIn, slideUp, slideLeft, scaleIn } from "@/utils/animationConfig"; | ||
| import { useInViewAnimation } from "@/hooks/useInViewAnimation"; |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify tsconfig doesn't enable UMD global React access, and check for a global React import elsewhere.
fd tsconfig.json | xargs cat
rg -n 'allowUmdGlobalAccess'Repository: 7-Blocks/Kepler
Length of output: 272
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== tsconfig.app.json ==\n'
cat -n tsconfig.app.json
printf '\n== tsconfig.node.json ==\n'
cat -n tsconfig.node.json
printf '\n== AnimationWrapper.tsx ==\n'
cat -n frontend/src/components/Animation/AnimationWrapper.tsxRepository: 7-Blocks/Kepler
Length of output: 228
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== tsconfig.app.json ==\n'
cat -n tsconfig.app.json
printf '\n== tsconfig.node.json ==\n'
cat -n tsconfig.node.json
printf '\n== AnimationWrapper.tsx ==\n'
cat -n frontend/src/components/Animation/AnimationWrapper.tsx
printf '\n== React namespace usage ==\n'
rg -n 'React\.Ref|from "react"' frontend/src/components frontend/src -g '!**/node_modules/**' || trueRepository: 7-Blocks/Kepler
Length of output: 228
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== repository tsconfig files ==\n'
fd -a 'tsconfig*.json' .
printf '\n== AnimationWrapper.tsx ==\n'
fd -a 'AnimationWrapper.tsx' .
printf '\n== nearby React.Ref usages ==\n'
rg -n 'React\.Ref|from "react"' frontend -g '!**/node_modules/**' || trueRepository: 7-Blocks/Kepler
Length of output: 1824
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== frontend/tsconfig.json ==\n'
cat -n frontend/tsconfig.json
printf '\n== AnimationWrapper.tsx ==\n'
cat -n frontend/src/components/Animation/AnimationWrapper.tsxRepository: 7-Blocks/Kepler
Length of output: 2036
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== frontend/tsconfig.app.json ==\n'
cat -n frontend/tsconfig.app.json
printf '\n== package files mentioning react / typescript ==\n'
rg -n '"react"|"typescript"|`@types/react`|jsx' frontend/package.json frontend/package-lock.json frontend/pnpm-lock.yaml frontend/yarn.lock 2>/dev/null || trueRepository: 7-Blocks/Kepler
Length of output: 8147
Import Ref instead of using React.Ref
AnimationWrapper.tsx is a module and doesn’t import the React namespace, so ref={ref as React.Ref<HTMLDivElement>} will fail type-checking under this tsconfig. Use import type { Ref } from "react"; and cast to Ref<HTMLDivElement> instead.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/components/Animation/AnimationWrapper.tsx` around lines 1 - 5,
Update AnimationWrapper’s React type imports to include Ref, then change the ref
cast from React.Ref<HTMLDivElement> to Ref<HTMLDivElement> so the module no
longer relies on an unimported React namespace.
| visible: { | ||
| opacity: 1, | ||
| transition: { | ||
| duration: 0.5, | ||
| ease: "easeOut", | ||
| }, | ||
| }, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the referenced files and nearby lines.
for f in frontend/src/utils/animationConfig.ts frontend/src/components/AnimationWrapper.tsx frontend/src/pages/Dashboard.tsx; do
if [ -f "$f" ]; then
echo "===== $f ====="
wc -l "$f"
sed -n '1,220p' "$f"
echo
else
echo "MISSING: $f"
fi
doneRepository: 7-Blocks/Kepler
Length of output: 10239
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Locate the animation components referenced by Dashboard.tsx and inspect their implementations.
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' \
'export default|function FadeIn|const FadeIn|function SlideIn|const SlideIn|function AnimatedCard|const AnimatedCard|transition' \
frontend/src/components frontend/src/utils frontend/src/pages
echo "---- FILE LIST ----"
git ls-files 'frontend/src/components/**' 'frontend/src/utils/**' | sed -n '1,200p'Repository: 7-Blocks/Kepler
Length of output: 17981
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the animation component implementations referenced in Dashboard.tsx.
for f in \
frontend/src/components/Animation/AnimatedCard.tsx \
frontend/src/components/Animation/FadeIn.tsx \
frontend/src/components/Animation/SlideIn.tsx \
frontend/src/utils/animationConfig.ts
do
if [ -f "$f" ]; then
echo "===== $f ====="
wc -l "$f"
sed -n '1,220p' "$f"
echo
else
echo "MISSING: $f"
fi
doneRepository: 7-Blocks/Kepler
Length of output: 2334
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find and inspect the animation wrapper components used by Dashboard.tsx.
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' \
'AnimatedCard|FadeIn|SlideIn|variants|transition|delay' frontend/src/components
echo "---- candidate files ----"
fd -HI 'AnimatedCard.tsx|FadeIn.tsx|SlideIn.tsx|Animation.*\.tsx' frontend/src/componentsRepository: 7-Blocks/Kepler
Length of output: 10115
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Read the animation wrapper to determine how transition is composed.
f=frontend/src/components/Animation/AnimationWrapper.tsx
echo "===== $f ====="
wc -l "$f"
sed -n '1,220p' "$f"Repository: 7-Blocks/Kepler
Length of output: 1536
🌐 Web query:
Framer Motion variants transition component transition default override delay duration docs
💡 Result:
In Framer Motion, transition properties defined directly on a motion component as the transition prop serve as a global override that takes precedence over any transition settings defined within variants [1][2]. Key rules for transition overrides and defaults: 1. Component Transition Prop Priority: When you define a transition prop on a motion component, it overrides the transition object defined inside your active variant [1]. For example, if your variant specifies a duration: 0.5 but you add transition={{ duration: 2 }} to the component, the animation will use the 2-second duration [1]. 2. Default vs. Specific Transitions: Transitions can be defined globally for a component or specifically for individual animation values (e.g., opacity, x, scale) [2]. You can provide a default key within your transition object to set a fallback for all values, which is then overridden by property-specific keys [2]. 3. Orchestration Properties: Orchestration settings like delayChildren and staggerChildren are typically defined within the transition object of a parent component's variants [3][4]. These are specific to variant propagation and are not overridden by a standard transition prop on the child components themselves in the same way simple timing properties are [3][5]. 4. Inheritance: By default, child components do not inherit transitions from parents. You can enable inheritance by setting inherit: true within a child's transition prop [3][2]. This allows the child to inherit parent values while still allowing the child to override specific properties [2]. 5. Handling Complex Overrides: If you need to override a delay or duration dynamically or conditionally (e.g., changing behavior after an initial mount), common patterns include: - Using dynamic variants: Define your variants as functions that accept a custom prop to compute transition values at runtime [6][4]. - State management: Use a React state variable to update the transition prop or the custom prop dynamically based on animation events like onAnimationComplete [7]. For more specific timing requirements, properties like visualDuration (where supported) will override duration to provide a consistent visual timing [3].
Citations:
- 1: https://www.mintlify.com/motiondivision/motion/concepts/variants
- 2: https://www.mintlify.com/motiondivision/motion/api/types/transition
- 3: https://motion.dev/docs/react-transitions
- 4: https://motion.dev/tutorials/react-variants
- 5: [FEATURE] Way to override parent variant's transition properties within staggered children motiondivision/motion#2374
- 6: https://www.mintlify.com/motiondivision/motion/api/types/variants
- 7: https://stackoverflow.com/questions/66697286/override-the-transition-delay-in-react-framer-motion
🌐 Web query:
site:framer.mighty.guide variant transition component transition priority delay duration
💡 Result:
In Framer Motion, the transition property defines the animation physics, such as duration, delay, easing, and spring properties [1]. When using both variants and the transition component prop, the transition prop defined directly on the motion component acts as the default animation configuration. However, if a transition is defined within a specific variant, it will take precedence for that variant state [1]. Regarding precedence and configuration: 1. Variant Precedence: If you define a transition inside a variant, it overrides the default transition defined on the component for that specific state [1]. 2. Property-Specific Overrides: The transition property allows you to define global settings for all animated properties, but you can override these for specific properties (e.g., separate settings for rotate versus scale) [1]. When you define transition settings for a specific property, the global values for that property are ignored [1]. 3. Duration and Delay: Duration and delay are standard transition settings. If omitted, duration defaults to 0.3 seconds [1]. When defining separate transition settings for individual properties, you must explicitly include these settings, such as delay and duration, because the global defaults will no longer apply to those specific properties [1][2]. Essentially, the closer a transition definition is to the animated property (i.e., within the variant vs. the component prop), the higher its priority [1]. If global settings are ignored due to a property-specific override, you must redefine all necessary timing parameters for that specific property [1].
Citations:
- 1: https://framer.mighty.guide/the-main-properties/the-transition-property/
- 2: https://framer.mighty.guide/updates/
Move timing out of frontend/src/utils/animationConfig.ts The per-variant transition blocks still override AnimationWrapper’s delay/duration, so FadeIn and AnimatedCard can’t control timing per instance. Keep the variants to pose/opacity/scale only and let the wrapper own timing.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@frontend/src/utils/animationConfig.ts` around lines 6 - 12, Remove the
per-variant transition timing from the animation configuration, including the
visible variant and related pose definitions, leaving only opacity, scale, and
other visual state properties. Ensure AnimationWrapper remains the sole owner of
delay and duration so FadeIn and AnimatedCard can control timing per instance.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 6 out of 6 changed files in this pull request and generated 4 comments.
Comments suppressed due to low confidence (1)
frontend/src/components/Animation/AnimationWrapper.tsx:44
ref={ref as React.Ref<HTMLDivElement>}is an unsafe cast that becomes unnecessary onceuseInViewAnimationis typed to return the correct ref type (e.g.HTMLDivElement). Prefer passing the ref directly so TypeScript can validate the element/ref relationship.
ref={ref as React.Ref<HTMLDivElement>}
| export const useInViewAnimation = ( | ||
| options: UseInViewAnimationOptions = {} | ||
| ) => { | ||
| const { once = true, amount = 0.2 } = options; | ||
|
|
||
| const ref = useRef<HTMLElement | null>(null); | ||
|
|
||
| const isInView = useInView(ref, { | ||
| once, | ||
| amount, | ||
| }); | ||
|
|
||
| const prefersReducedMotion = useReducedMotion(); | ||
|
|
||
| return { | ||
| ref, | ||
| isInView, | ||
| prefersReducedMotion, | ||
| }; | ||
| }; No newline at end of file |
| const { ref, isInView, prefersReducedMotion } = | ||
| useInViewAnimation({ once }); |
| transition={{ | ||
| delay, | ||
| ...(duration ? { duration } : {}), | ||
| }} |
| export default function FadeIn(props: FadeInProps) { | ||
| return <AnimationWrapper {...props} type="fade" />; | ||
| } No newline at end of file |
|
@varshu55, Please attach screenshots of the updates/changes along with your PR. Thanks! |
User description
Description
AnimationWrapper,AnimatedCard,FadeIn, andSlideIn.useInViewAnimationhook.FadeInanimation to the Live Collision Timeline.Related Issue
Fixes #123
Checklist
Screenshots / Screen Recordings
N/A
Breaking Changes
None
ECSoC26 Submission
ECSoC26-L1– BeginnerECSoC26-L2– IntermediateECSoC26-L3– AdvancedCodeAnt-AI Description
Add reusable dashboard animations with viewport-triggered motion
What Changed
Impact
✅ Smoother dashboard loading✅ Clearer focus on key dashboard cards✅ Less motion for users who prefer reduced animation💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.
Summary by CodeRabbit
Greptile Summary
This PR adds reusable viewport-triggered animations for dashboard content. The main changes are:
Confidence Score: 5/5
This looks safe to merge.
Important Files Changed
Reviews (2): Last reviewed commit: "Merge upstream/main" | Re-trigger Greptile