From 45bcad9788aec8970034d48d6e71b43f0273e7f9 Mon Sep 17 00:00:00 2001 From: Avery Felts Date: Sat, 24 Jan 2026 11:18:38 -0700 Subject: [PATCH] Add UI polish: animations, mobile responsiveness, and visual enhancements - Update daily quotes to 36 curated motivational quotes from notable figures - Add entrance animations (fade-in, slide-in, scale-in) with staggered delays - Add hover effects on cards and buttons with smooth transitions - Improve mobile responsiveness: stacking layouts, responsive text, touch targets - Enhance glassmorphism with stronger blur and gradient orbs on cards - Add gradient logo for QuitTraq branding - Improve quote section with decorative elements and inner glow - Refine streak celebrations and weekly target indicators - Update background with multiple color gradient spots Co-Authored-By: Claude Opus 4.5 --- src/app/globals.css | 270 ++++++++++++++++++++++- src/components/Dashboard.tsx | 42 ++-- src/components/QuitPlanCard.tsx | 36 +-- src/components/StatsCard.tsx | 39 ++-- src/components/SubstanceTrackingPage.tsx | 30 +-- src/components/UsageCalendar.tsx | 111 +++++----- src/components/UsageTrendGraph.tsx | 8 +- src/components/UserHeader.tsx | 24 +- 8 files changed, 424 insertions(+), 136 deletions(-) diff --git a/src/app/globals.css b/src/app/globals.css index 104d828..3ba615b 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -174,10 +174,11 @@ font-family: var(--font-sans); letter-spacing: var(--tracking-normal); background: linear-gradient(135deg, - #1a1a2e 0%, - #16213e 25%, - #1a1a2e 50%, - #0f0f1a 75%, + #0f0f1a 0%, + #1a1a2e 20%, + #16213e 40%, + #1a1a2e 60%, + #0f0f1a 80%, #1a1a2e 100%); background-attachment: fixed; min-height: 100vh; @@ -191,9 +192,11 @@ right: 0; bottom: 0; background: - radial-gradient(ellipse at 20% 20%, rgba(120, 119, 198, 0.15) 0%, transparent 50%), - radial-gradient(ellipse at 80% 80%, rgba(74, 85, 104, 0.2) 0%, transparent 50%), - radial-gradient(ellipse at 40% 60%, rgba(45, 55, 72, 0.15) 0%, transparent 40%); + radial-gradient(ellipse at 15% 10%, rgba(99, 102, 241, 0.15) 0%, transparent 40%), + radial-gradient(ellipse at 85% 20%, rgba(168, 85, 247, 0.12) 0%, transparent 35%), + radial-gradient(ellipse at 50% 50%, rgba(45, 55, 72, 0.1) 0%, transparent 50%), + radial-gradient(ellipse at 20% 80%, rgba(34, 197, 94, 0.08) 0%, transparent 40%), + radial-gradient(ellipse at 80% 85%, rgba(239, 68, 68, 0.08) 0%, transparent 35%); pointer-events: none; z-index: -1; } @@ -202,4 +205,257 @@ .rdp { --rdp-cell-size: 36px; } + + /* Mobile calendar adjustments */ + @media (max-width: 640px) { + .rdp { + --rdp-cell-size: 32px; + font-size: 0.875rem; + } + } +} + +/* Animation keyframes */ +@keyframes fade-in { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes fade-in-up { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes fade-in-down { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +@keyframes scale-in { + from { + opacity: 0; + transform: scale(0.95); + } + to { + opacity: 1; + transform: scale(1); + } +} + +@keyframes slide-in-right { + from { + opacity: 0; + transform: translateX(20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes slide-in-left { + from { + opacity: 0; + transform: translateX(-20px); + } + to { + opacity: 1; + transform: translateX(0); + } +} + +@keyframes pulse-subtle { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.7; } +} + +@keyframes float { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-5px); } +} + +@keyframes shimmer { + 0% { background-position: -200% 0; } + 100% { background-position: 200% 0; } +} + +@keyframes glow { + 0%, 100% { box-shadow: 0 0 5px rgba(99, 102, 241, 0.5); } + 50% { box-shadow: 0 0 20px rgba(99, 102, 241, 0.8); } +} + +/* Animation utility classes */ +.animate-fade-in { + animation: fade-in 0.5s ease-out forwards; +} + +.animate-fade-in-up { + animation: fade-in-up 0.5s ease-out forwards; +} + +.animate-fade-in-down { + animation: fade-in-down 0.5s ease-out forwards; +} + +.animate-scale-in { + animation: scale-in 0.4s ease-out forwards; +} + +.animate-slide-in-right { + animation: slide-in-right 0.5s ease-out forwards; +} + +.animate-slide-in-left { + animation: slide-in-left 0.5s ease-out forwards; +} + +.animate-pulse-subtle { + animation: pulse-subtle 2s ease-in-out infinite; +} + +.animate-float { + animation: float 3s ease-in-out infinite; +} + +.animate-glow { + animation: glow 2s ease-in-out infinite; +} + +/* Stagger delay utilities */ +.delay-100 { animation-delay: 100ms; } +.delay-200 { animation-delay: 200ms; } +.delay-300 { animation-delay: 300ms; } +.delay-400 { animation-delay: 400ms; } +.delay-500 { animation-delay: 500ms; } + +/* Start hidden for animations */ +.opacity-0 { opacity: 0; } + +/* Smooth transitions */ +.transition-smooth { + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); +} + +/* Interactive hover effects */ +.hover-lift { + transition: transform 0.2s ease, box-shadow 0.2s ease; +} + +.hover-lift:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.3); +} + +.hover-scale { + transition: transform 0.2s ease; +} + +.hover-scale:hover { + transform: scale(1.02); +} + +.hover-glow { + transition: box-shadow 0.3s ease; +} + +.hover-glow:hover { + box-shadow: 0 0 20px rgba(99, 102, 241, 0.4); +} + +/* Glassmorphism effect */ +.glass { + background: rgba(255, 255, 255, 0.05); + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.1); +} + +.glass-strong { + background: rgba(255, 255, 255, 0.1); + backdrop-filter: blur(20px); + border: 1px solid rgba(255, 255, 255, 0.15); +} + +/* Premium card effect */ +.card-premium { + background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%); + backdrop-filter: blur(20px); + border: 1px solid rgba(255, 255, 255, 0.18); + box-shadow: + 0 8px 32px rgba(0, 0, 0, 0.1), + inset 0 1px 0 rgba(255, 255, 255, 0.1); +} + +/* Gradient text */ +.gradient-text { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.gradient-text-warm { + background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* Subtle inner glow for cards */ +.inner-glow { + box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1); +} + +/* Text shadow for better readability */ +.text-shadow { + text-shadow: 0 2px 4px rgba(0, 0, 0, 0.3); +} + +.text-shadow-sm { + text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); +} + +/* Gradient borders */ +.gradient-border { + position: relative; +} + +.gradient-border::before { + content: ''; + position: absolute; + inset: 0; + border-radius: inherit; + padding: 1px; + background: linear-gradient(135deg, rgba(99, 102, 241, 0.5), rgba(168, 85, 247, 0.5)); + -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); + mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0); + -webkit-mask-composite: xor; + mask-composite: exclude; + pointer-events: none; +} + +/* Noise texture overlay for depth */ +.noise-overlay { + position: relative; +} + +.noise-overlay::after { + content: ''; + position: absolute; + inset: 0; + background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='noiseFilter'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23noiseFilter)'/%3E%3C/svg%3E"); + opacity: 0.03; + pointer-events: none; + border-radius: inherit; } diff --git a/src/components/Dashboard.tsx b/src/components/Dashboard.tsx index 4e492fc..5406971 100644 --- a/src/components/Dashboard.tsx +++ b/src/components/Dashboard.tsx @@ -137,35 +137,43 @@ export function Dashboard({ user }: DashboardProps) { {preferences && ( <> {/* Floating Log Button */} -
+
- - +
+ +
+
+ +
- - +
+ +
+
+ +
diff --git a/src/components/QuitPlanCard.tsx b/src/components/QuitPlanCard.tsx index 79d234e..a7e5e5a 100644 --- a/src/components/QuitPlanCard.tsx +++ b/src/components/QuitPlanCard.tsx @@ -40,11 +40,12 @@ export function QuitPlanCard({ if (!plan) { return ( - - - +
+ + Your Personalized Plan @@ -52,17 +53,17 @@ export function QuitPlanCard({ We're tracking your usage to build your custom quit plan - -
+ +
Tracking Progress {daysRemaining > 0 ? `${daysRemaining} days left` : 'Ready!'}
-
+
@@ -77,7 +78,7 @@ export function QuitPlanCard({ Great work! Your average daily usage is{' '} {currentAverage} per day.

- @@ -106,11 +107,12 @@ export function QuitPlanCard({ const currentTarget = weekNumber <= totalWeeks ? plan.weeklyTargets[weekNumber - 1] : 0; return ( - - - +
+ + Your Quit Plan @@ -118,24 +120,24 @@ export function QuitPlanCard({ Week {Math.min(weekNumber, totalWeeks)} of {totalWeeks} - 25% weekly reduction - -
+ +

This week's daily target

-

+

{currentTarget !== null && currentTarget > 0 ? currentTarget : '0'}

per day

-
+

Weekly targets:

{plan.weeklyTargets.map((target, index) => (
- - +
+ + {substanceLabel} Stats -
-
-

{todayUsage}

-

Today

+
+
+

{todayUsage}

+

Today

-
-

{weekAverage}

-

Daily Avg (7d)

+
+

{weekAverage}

+

Daily Avg (7d)

-
-

{streak}

-

Free days

+
+

{streak}

+

Free days

-
-

{totalDays}

-

Days tracked

+
+

{totalDays}

+

Days tracked

{streak > 0 && ( -
-

🎉 {streak} day{streak > 1 ? 's' : ''} {substanceLabel.toLowerCase()}-free!

-

Keep up the great work!

+
+

{streak} day{streak > 1 ? 's' : ''} {substanceLabel.toLowerCase()}-free!

+

Keep up the great work!

)} diff --git a/src/components/SubstanceTrackingPage.tsx b/src/components/SubstanceTrackingPage.tsx index 52d9b8d..126ce42 100644 --- a/src/components/SubstanceTrackingPage.tsx +++ b/src/components/SubstanceTrackingPage.tsx @@ -62,42 +62,46 @@ export function SubstanceTrackingPage({ user, substance }: SubstanceTrackingPage
{/* Substance Header */} -
-
-
- +
+
+
+
-

{substanceLabel} Tracking

-

Monitor your {substanceLabel.toLowerCase()} usage and progress

+

{substanceLabel} Tracking

+

Monitor your {substanceLabel.toLowerCase()} usage and progress

{/* Today's Status Message */} -
+
{todayCount === 0 ? ( -

+

Great job, nothing yet!

) : ( -

+

{todayCount} {todayCount === 1 ? (substance === 'nicotine' ? 'puff' : 'hit') : unitLabel} recorded, you got this!

)}
{/* Inspirational Message */} -
-

+

+

"One day at a time..."

{/* Stats and Graph */}
- - +
+ +
+
+ +
diff --git a/src/components/UsageCalendar.tsx b/src/components/UsageCalendar.tsx index 3a4b8e1..f138780 100644 --- a/src/components/UsageCalendar.tsx +++ b/src/components/UsageCalendar.tsx @@ -17,37 +17,42 @@ import { ChevronLeftIcon, ChevronRightIcon, Cigarette, Leaf, Sparkles } from 'lu import { useTheme } from '@/lib/theme-context'; const quotes = [ - { text: "The secret of getting ahead is getting started.", author: "Mark Twain" }, - { text: "It does not matter how slowly you go as long as you do not stop.", author: "Confucius" }, - { text: "Your future self will thank you for the choices you make today.", author: "Unknown" }, - { text: "Every moment is a fresh beginning.", author: "T.S. Eliot" }, - { text: "Believe you can and you're halfway there.", author: "Theodore Roosevelt" }, - { text: "Small steps every day lead to big changes over time.", author: "Unknown" }, - { text: "You are stronger than your cravings.", author: "Unknown" }, - { text: "The best time to plant a tree was 20 years ago. The second best time is now.", author: "Chinese Proverb" }, - { text: "Progress, not perfection, is what we should be asking of ourselves.", author: "Julia Cameron" }, - { text: "The greatest glory in living lies not in never falling, but in rising every time we fall.", author: "Nelson Mandela" }, - { text: "Your life does not get better by chance, it gets better by change.", author: "Jim Rohn" }, - { text: "You don't have to be great to start, but you have to start to be great.", author: "Zig Ziglar" }, - { text: "The pain of discipline is far less than the pain of regret.", author: "Sarah Bombell" }, - { text: "One day or day one. You decide.", author: "Unknown" }, - { text: "Your health is an investment, not an expense.", author: "Unknown" }, - { text: "The comeback is always stronger than the setback.", author: "Unknown" }, - { text: "Difficult roads often lead to beautiful destinations.", author: "Zig Ziglar" }, - { text: "Success is the sum of small efforts repeated day in and day out.", author: "Robert Collier" }, - { text: "Fall seven times, stand up eight.", author: "Japanese Proverb" }, - { text: "Great things never come from comfort zones.", author: "Unknown" }, - { text: "Every champion was once a contender that refused to give up.", author: "Rocky Balboa" }, - { text: "Don't stop when you're tired. Stop when you're done.", author: "Unknown" }, - { text: "Break free from the chains of habit and unlock your true potential.", author: "Unknown" }, - { text: "Dream it. Wish it. Do it.", author: "Unknown" }, - { text: "Your limitation—it's only your imagination.", author: "Unknown" }, - { text: "You are not defined by your past. You are prepared by it.", author: "Unknown" }, - { text: "Don't let yesterday take up too much of today.", author: "Will Rogers" }, - { text: "What lies behind us and what lies before us are tiny matters compared to what lies within us.", author: "Ralph Waldo Emerson" }, - { text: "The only person you are destined to become is the person you decide to be.", author: "Ralph Waldo Emerson" }, { text: "The only way to do great work is to love what you do.", author: "Steve Jobs" }, - { text: "The harder you work for something, the greater you'll feel when you achieve it.", author: "Unknown" }, + { text: "It is during our darkest moments that we must focus to see the light.", author: "Aristotle" }, + { text: "The greatest glory in living lies not in never falling, but in rising every time we fall.", author: "Nelson Mandela" }, + { text: "In the middle of difficulty lies opportunity.", author: "Albert Einstein" }, + { text: "What you get by achieving your goals is not as important as what you become by achieving your goals.", author: "Zig Ziglar" }, + { text: "The future belongs to those who believe in the beauty of their dreams.", author: "Eleanor Roosevelt" }, + { text: "It does not matter how slowly you go as long as you do not stop.", author: "Confucius" }, + { text: "Everything you've ever wanted is on the other side of fear.", author: "George Addair" }, + { text: "The best time to plant a tree was 20 years ago. The second best time is now.", author: "Chinese Proverb" }, + { text: "You are never too old to set another goal or to dream a new dream.", author: "C.S. Lewis" }, + { text: "The only impossible journey is the one you never begin.", author: "Tony Robbins" }, + { text: "Success is not final, failure is not fatal: it is the courage to continue that counts.", author: "Winston Churchill" }, + { text: "Believe you can and you're halfway there.", author: "Theodore Roosevelt" }, + { text: "The pain you feel today will be the strength you feel tomorrow.", author: "Arnold Schwarzenegger" }, + { text: "Your life does not get better by chance, it gets better by change.", author: "Jim Rohn" }, + { text: "The secret of change is to focus all of your energy not on fighting the old, but on building the new.", author: "Socrates" }, + { text: "What lies behind us and what lies before us are tiny matters compared to what lies within us.", author: "Ralph Waldo Emerson" }, + { text: "The man who moves a mountain begins by carrying away small stones.", author: "Confucius" }, + { text: "Our greatest weakness lies in giving up. The most certain way to succeed is always to try just one more time.", author: "Thomas Edison" }, + { text: "Fall seven times, stand up eight.", author: "Japanese Proverb" }, + { text: "You don't have to be great to start, but you have to start to be great.", author: "Zig Ziglar" }, + { text: "The only person you are destined to become is the person you decide to be.", author: "Ralph Waldo Emerson" }, + { text: "When you reach the end of your rope, tie a knot in it and hang on.", author: "Franklin D. Roosevelt" }, + { text: "Do not wait to strike till the iron is hot; but make it hot by striking.", author: "William Butler Yeats" }, + { text: "Whether you think you can or you think you can't, you're right.", author: "Henry Ford" }, + { text: "The mind is everything. What you think you become.", author: "Buddha" }, + { text: "Strength does not come from physical capacity. It comes from an indomitable will.", author: "Mahatma Gandhi" }, + { text: "A journey of a thousand miles begins with a single step.", author: "Lao Tzu" }, + { text: "He who conquers himself is the mightiest warrior.", author: "Confucius" }, + { text: "The wound is the place where the light enters you.", author: "Rumi" }, + { text: "Rock bottom became the solid foundation on which I rebuilt my life.", author: "J.K. Rowling" }, + { text: "You have power over your mind, not outside events. Realize this, and you will find strength.", author: "Marcus Aurelius" }, + { text: "Out of suffering have emerged the strongest souls.", author: "Kahlil Gibran" }, + { text: "The only limit to our realization of tomorrow will be our doubts of today.", author: "Franklin D. Roosevelt" }, + { text: "Courage is not the absence of fear, but rather the judgment that something else is more important than fear.", author: "Ambrose Redmoon" }, + { text: "Every morning brings new potential, but if you dwell on the misfortunes of the day before, you tend to overlook tremendous opportunities.", author: "Harvey Mackay" }, ]; interface UsageCalendarProps { @@ -231,14 +236,14 @@ export function UsageCalendar({ usageData, onDataUpdate }: UsageCalendarProps) { return ( <> - + Usage Calendar -
+
{/* Calendar */} -
+
-
- - Daily Inspiration +
+
+
+ + Daily Inspiration +
+

+ “{dailyQuote.text}” +

+

+ — {dailyQuote.author} +

-

- “{dailyQuote.text}” -

-

- — {dailyQuote.author} -

-
+
-
+
No usage
-
+
Today
-
+
Nicotine
-
+
Marijuana
-
+
Both
diff --git a/src/components/UsageTrendGraph.tsx b/src/components/UsageTrendGraph.tsx index 48380ce..e8b1957 100644 --- a/src/components/UsageTrendGraph.tsx +++ b/src/components/UsageTrendGraph.tsx @@ -62,7 +62,7 @@ export function UsageTrendGraph({ usageData, substance }: UsageTrendGraphProps) }, [chartData]); return ( - + {substanceLabel} Usage Trend @@ -117,14 +117,14 @@ export function UsageTrendGraph({ usageData, substance }: UsageTrendGraphProps)
-
+

{average}

Daily Average

-
+

{trend}

- {trend === 'decreasing' ? '📉 Great progress!' : trend === 'increasing' ? '📈 Stay strong!' : '➡️ Holding steady'} + {trend === 'decreasing' ? 'Great progress!' : trend === 'increasing' ? 'Stay strong!' : 'Holding steady'}

diff --git a/src/components/UserHeader.tsx b/src/components/UserHeader.tsx index 8cf17d9..1520236 100644 --- a/src/components/UserHeader.tsx +++ b/src/components/UserHeader.tsx @@ -50,11 +50,17 @@ export function UserHeader({ user }: UserHeaderProps) { background: 'linear-gradient(135deg, rgba(10, 10, 20, 0.98) 0%, rgba(20, 30, 60, 0.95) 50%, rgba(15, 25, 50, 0.98) 100%)', backdropFilter: 'blur(10px)', }}> -
-
+
+

handleNavigate('/')} + style={{ + background: 'linear-gradient(135deg, #a78bfa 0%, #818cf8 50%, #6366f1 100%)', + WebkitBackgroundClip: 'text', + WebkitTextFillColor: 'transparent', + backgroundClip: 'text', + }} > QuitTraq

@@ -65,16 +71,16 @@ export function UserHeader({ user }: UserHeaderProps) { )}
-
+
@@ -111,8 +117,8 @@ export function UserHeader({ user }: UserHeaderProps) {
{userName && ( -
-

+

+

Welcome {userName}, you got this!