Skip to content

Add reusable dashboard animation components#126

Open
varshu55 wants to merge 2 commits into
7-Blocks:mainfrom
varshu55:feature/dashboard-card-animations
Open

Add reusable dashboard animation components#126
varshu55 wants to merge 2 commits into
7-Blocks:mainfrom
varshu55:feature/dashboard-card-animations

Conversation

@varshu55

@varshu55 varshu55 commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

User description

Description

  • Added reusable animation components using Framer Motion.
  • Created AnimationWrapper, AnimatedCard, FadeIn, and SlideIn.
  • Added reusable animation configuration and useInViewAnimation hook.
  • Applied staggered animations to KPI cards.
  • Added FadeIn animation to the Live Collision Timeline.
  • Animations trigger on viewport entry and the project builds successfully.

Related Issue

Fixes #123

Checklist

  • I have read the contributing guidelines
  • My code follows the project guidelines
  • I have completed testing of my changes
  • Documentation has been updated (if applicable)

Screenshots / Screen Recordings

N/A

Breaking Changes

None


ECSoC26 Submission

  • ECSoC26-L1 – Beginner
  • ECSoC26-L2 – Intermediate
  • ECSoC26-L3 – Advanced

CodeAnt-AI Description

Add reusable dashboard animations with viewport-triggered motion

What Changed

  • Dashboard KPI cards now animate in one by one as they enter view, instead of appearing all at once
  • The live collision timeline now fades in when shown on screen
  • Added reusable animation styles for fade, slide, and scale effects so dashboard sections can share the same motion behavior
  • Motion is disabled for users who prefer reduced movement

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:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

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:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

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

  • New Features
    • Added smooth, scroll-triggered animations for dashboard cards and content sections.
    • Added fade, slide, and scale animation styles with customizable timing.
    • Added reduced-motion support for accessibility.
    • Improved dashboard loading and empty states for collision risks and AI reasoning.
    • Added a clear connection-error message when dashboard data cannot be loaded.
    • Enhanced KPI cards with staggered entrance effects and contextual sub-values.

Greptile Summary

This PR adds reusable viewport-triggered animations for dashboard content. The main changes are:

  • Shared fade, slide, and scale animation variants.
  • Reusable wrappers for animated cards and sections.
  • Viewport detection and reduced-motion support.

Confidence Score: 5/5

This looks safe to merge.

  • The timeline panel is again a direct grid child, so its desktop column span is preserved.
  • No blocking issues remain in the updated code.

Important Files Changed

Filename Overview
frontend/src/components/Animation/AnimationWrapper.tsx Adds the shared motion wrapper with variant selection, timing options, and reduced-motion handling.
frontend/src/components/Animation/AnimatedCard.tsx Adds a reusable scale-animation wrapper for card content.
frontend/src/components/Animation/FadeIn.tsx Adds a reusable fade-animation wrapper.
frontend/src/components/Animation/SlideIn.tsx Adds a reusable upward-slide animation wrapper.
frontend/src/hooks/useInViewAnimation.ts Adds shared viewport detection and reduced-motion preference handling.
frontend/src/utils/animationConfig.ts Defines shared Framer Motion variants for fade, slide, and scale effects.

Reviews (2): Last reviewed commit: "Merge upstream/main" | Re-trigger Greptile

Copilot AI review requested due to automatic review settings July 22, 2026 13:18
@codeant-ai

codeant-ai Bot commented Jul 22, 2026

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
🔄 Incremental review in progress… b9bea1c Jul 22, 2026 · 15:08
✅ Reviewed your PR 2685dee Jul 22, 2026 · 13:18 13:23

Updated in place by CodeAnt AI · last 5 reviews

@github-actions github-actions Bot added ECSoC26 Official label for ECSoC26 event contributions. ECSoC26-L1 Level 1 contribution for the ECSoC26 event. bug Something isn't working documentation Improvements or additions to documentation frontend Frontend development size/XL Very large or complex contribution. type:bug Fixes an existing bug or unexpected behavior. type:documentation Improves project documentation. type:frontend Changes frontend or client-side code. labels Jul 22, 2026
@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Dashboard animation system

Layer / File(s) Summary
Animation variants and viewport hook
frontend/src/utils/animationConfig.ts, frontend/src/hooks/useInViewAnimation.ts
Adds reusable fade, slide, and scale variants plus viewport and reduced-motion state handling.
Reusable animation wrappers
frontend/src/components/Animation/*
Adds configurable AnimationWrapper and AnimatedCard, FadeIn, and SlideIn presets.
Dashboard animated rendering
frontend/src/pages/Dashboard.tsx
Adds animated KPI cards, wraps the collision timeline in FadeIn, and restructures loading, error, empty, and populated rendering states.

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
Loading

Possibly related PRs

Suggested labels: enhancement, type:feature

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The PR implements the reusable animation system, viewport-triggered motion, staggered cards, and reduced-motion support requested by issue #123.
Out of Scope Changes check ✅ Passed The changes stay focused on the dashboard animation system and related UI wiring, with no clear unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title is concise and accurately summarizes the main change: reusable dashboard animation components.
Description check ✅ Passed The description covers all required template sections, including related issue, checklist, screenshots, breaking changes, and ECSoC26 submission.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@codeant-ai codeant-ai Bot added the size:L Large size label Jul 22, 2026
@github-actions github-actions Bot added AI Artificial Intelligence and Machine Learning enhancement New feature or request type:feature Introduces a new feature or enhancement. labels Jul 22, 2026
Comment thread frontend/src/pages/Dashboard.tsx Outdated
animate={isInView ? "visible" : "hidden"}
transition={{
delay,
...(duration ? { duration } : {}),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in VSCode Claude

(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 fix
👍 | 👎

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR 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 a useInViewAnimation hook for viewport entry + prefers-reduced-motion.
  • Introduced reusable components: AnimationWrapper, AnimatedCard, FadeIn, and SlideIn.
  • Applied staggered KPI animations and added a FadeIn wrapper 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.

Comment thread frontend/src/pages/Dashboard.tsx Outdated
Comment on lines +5 to +7
import AnimatedCard from "@/components/Animation/AnimatedCard";
import FadeIn from "@/components/Animation/FadeIn";
import SlideIn from "@/components/Animation/SlideIn";
Comment thread frontend/src/pages/Dashboard.tsx Outdated
Comment on lines +181 to +182
<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">
Comment on lines +43 to +45
<motion.div
ref={ref as React.Ref<HTMLDivElement>}
className={className}
]
: null;

const conjunctions = collisions.data?.data ?? [];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in VSCode Claude

(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
👍 | 👎

Comment thread frontend/src/pages/Dashboard.tsx Outdated

const conjunctions = collisions.data?.data ?? [];
const agentRuns = agents.data?.data ?? [];
const agentRuns = agents.data?.data ?? [];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in VSCode Claude

(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
👍 | 👎

Comment thread frontend/src/pages/Dashboard.tsx Outdated
Comment on lines +181 to +182
<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">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in VSCode Claude

(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 fix
👍 | 👎

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

📥 Commits

Reviewing files that changed from the base of the PR and between 22a6054 and 2685dee.

📒 Files selected for processing (7)
  • frontend/src/components/Animation/AnimatedCard.tsx
  • frontend/src/components/Animation/AnimationWrapper.tsx
  • frontend/src/components/Animation/FadeIn.tsx
  • frontend/src/components/Animation/SlideIn.tsx
  • frontend/src/hooks/useInViewAnimation.ts
  • frontend/src/pages/Dashboard.tsx
  • frontend/src/utils/animationConfig.ts

Comment on lines +1 to +5
import type { ReactNode } from "react";
import { motion } from "framer-motion";

import { fadeIn, slideUp, slideLeft, scaleIn } from "@/utils/animationConfig";
import { useInViewAnimation } from "@/hooks/useInViewAnimation";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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.tsx

Repository: 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/**' || true

Repository: 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/**' || true

Repository: 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.tsx

Repository: 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 || true

Repository: 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.

Comment on lines +6 to +12
visible: {
opacity: 1,
transition: {
duration: 0.5,
ease: "easeOut",
},
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 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
done

Repository: 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
done

Repository: 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/components

Repository: 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:


🌐 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:


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.

Copilot AI review requested due to automatic review settings July 22, 2026 15:08
@github-actions github-actions Bot added size/M Medium-sized contribution. size:M This PR changes 30-99 lines, ignoring generated files labels Jul 22, 2026

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 once useInViewAnimation is 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>}

Comment on lines +9 to +28
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
Comment on lines +33 to +34
const { ref, isInView, prefersReducedMotion } =
useInViewAnimation({ once });
Comment on lines +49 to +52
transition={{
delay,
...(duration ? { duration } : {}),
}}
Comment on lines +11 to +13
export default function FadeIn(props: FadeInProps) {
return <AnimationWrapper {...props} type="fade" />;
} No newline at end of file
@krishkhinchi

Copy link
Copy Markdown
Member

@varshu55, Please attach screenshots of the updates/changes along with your PR. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI Artificial Intelligence and Machine Learning bug Something isn't working documentation Improvements or additions to documentation ECSoC26-L1 Level 1 contribution for the ECSoC26 event. ECSoC26 Official label for ECSoC26 event contributions. enhancement New feature or request frontend Frontend development size:L Large size size/M Medium-sized contribution. size:M This PR changes 30-99 lines, ignoring generated files size/XL Very large or complex contribution. type:bug Fixes an existing bug or unexpected behavior. type:documentation Improves project documentation. type:feature Introduces a new feature or enhancement. type:frontend Changes frontend or client-side code.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add Smooth Card Entrance Animations Across the Dashboard

3 participants