Skip to content

Commit f8040ac

Browse files
committed
Add beautiful animations to credit indicator
- Credit badge animates when value changes (scale, opacity, color transitions) - Spring animations with bounce effect for smooth, natural feel - Credit number slides in from above with staggered timing - Color transitions smoothly between normal (yellow) and low (orange) states - Low credits text slides in from left with spring animation - Enhanced hover/tap interactions with scale effects - Professional, polished feel with motion.div and key-based re-rendering - Smooth transitions make credit changes feel responsive and engaging
1 parent 85f16c6 commit f8040ac

File tree

1 file changed

+54
-13
lines changed

1 file changed

+54
-13
lines changed

app/components/TextGenerator/ReadingPassage.tsx

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,10 @@ const ReadingPassage = () => {
3535
const handleClickOutside = (event: MouseEvent) => {
3636
if (showCreditsInfo) {
3737
const target = event.target as HTMLElement;
38-
if (!target.closest('[data-testid="hover-credits-display"]') &&
39-
!target.closest('.credits-info-panel')) {
38+
if (
39+
!target.closest('[data-testid="hover-credits-display"]') &&
40+
!target.closest('.credits-info-panel')
41+
) {
4042
setShowCreditsInfo(false);
4143
}
4244
}
@@ -70,24 +72,63 @@ const ReadingPassage = () => {
7072
<div className="flex items-center space-x-4">
7173
{hover.progressionPhase === 'credits' && (
7274
<div className="flex items-center space-x-2 relative">
73-
<div
74-
className={`flex items-center justify-center w-8 h-8 rounded-full text-sm font-medium cursor-pointer transition-all duration-200 hover:scale-105 ${
75-
hover.creditsAvailable <= 2
76-
? 'text-orange-400 bg-orange-900/30 hover:bg-orange-900/50'
77-
: 'text-yellow-400 bg-gray-700/50 hover:bg-gray-700/70'
78-
}`}
75+
<motion.div
76+
key={hover.creditsAvailable} // Triggers animation when credits change
77+
initial={{ scale: 0.8, opacity: 0.7 }}
78+
animate={{
79+
scale: 1,
80+
opacity: 1,
81+
backgroundColor: hover.creditsAvailable <= 2
82+
? 'rgba(251, 146, 60, 0.3)' // orange-900/30
83+
: 'rgba(55, 65, 81, 0.5)', // gray-700/50
84+
color: hover.creditsAvailable <= 2
85+
? 'rgb(251, 146, 60)' // orange-400
86+
: 'rgb(250, 204, 21)' // yellow-400
87+
}}
88+
transition={{
89+
type: "spring",
90+
stiffness: 300,
91+
damping: 20,
92+
duration: 0.3
93+
}}
94+
whileHover={{ scale: 1.05 }}
95+
whileTap={{ scale: 0.95 }}
96+
className="flex items-center justify-center w-8 h-8 rounded-full text-sm font-medium cursor-pointer transition-all duration-200"
7997
data-testid="hover-credits-display"
8098
title={t('practice.hoverCreditsTooltip') || 'Translation Credits Info'}
8199
onClick={handleCreditsClick}
82100
>
83-
<span>{hover.creditsAvailable}</span>
84-
</div>
101+
<motion.span
102+
key={`credit-${hover.creditsAvailable}`}
103+
initial={{ y: -10, opacity: 0 }}
104+
animate={{ y: 0, opacity: 1 }}
105+
transition={{
106+
type: "spring",
107+
stiffness: 400,
108+
damping: 25,
109+
delay: 0.1
110+
}}
111+
>
112+
{hover.creditsAvailable}
113+
</motion.span>
114+
</motion.div>
85115
{hover.creditsAvailable <= 2 && (
86-
<span className="text-xs text-orange-300 hidden sm:inline">
116+
<motion.span
117+
initial={{ opacity: 0, x: -10 }}
118+
animate={{ opacity: 1, x: 0 }}
119+
exit={{ opacity: 0, x: -10 }}
120+
transition={{
121+
type: "spring",
122+
stiffness: 300,
123+
damping: 20,
124+
delay: 0.2
125+
}}
126+
className="text-xs text-orange-300 hidden sm:inline"
127+
>
87128
{t('practice.lowCredits')}
88-
</span>
129+
</motion.span>
89130
)}
90-
131+
91132
{showCreditsInfo && (
92133
<motion.div
93134
initial={{ opacity: 0, y: -10 }}

0 commit comments

Comments
 (0)