This commit is contained in:
MarkLo 2025-12-02 23:32:25 +08:00
parent 34dc5b0f87
commit 40f7d0bb92
4 changed files with 77 additions and 50 deletions

View File

@ -184,6 +184,25 @@
} }
} }
/* Heartbeat animation for buttons */
@keyframes heartbeat {
0%, 100% {
transform: scale(1);
}
10% {
transform: scale(1.05);
}
20% {
transform: scale(1);
}
30% {
transform: scale(1.05);
}
40% {
transform: scale(1);
}
}
/* Animation utility classes */ /* Animation utility classes */
.animate-fade-in { .animate-fade-in {
animation: fadeIn 0.6s ease-out; animation: fadeIn 0.6s ease-out;
@ -205,6 +224,11 @@
animation: scaleUp 0.5s ease-out; animation: scaleUp 0.5s ease-out;
} }
/* Heartbeat animation for call-to-action buttons */
.animate-heartbeat {
animation: heartbeat 2s ease-in-out infinite;
}
/* Stagger delays for sequential animations */ /* Stagger delays for sequential animations */
.animate-delay-100 { .animate-delay-100 {
animation-delay: 0.1s; animation-delay: 0.1s;
@ -257,21 +281,21 @@
GRADIENT UTILITIES GRADIENT UTILITIES
======================================== */ ======================================== */
/* Gradient Backgrounds - Purple/Pink theme */ /* Gradient Backgrounds - Blue/Pink in light, Blue/Purple in dark */
.gradient-bg-primary { .gradient-bg-primary {
background: linear-gradient(135deg, #9333EA 0%, #EC4899 100%); background: linear-gradient(135deg, #3B82F6 0%, #EC4899 100%);
} }
.dark .gradient-bg-primary { .dark .gradient-bg-primary {
background: linear-gradient(135deg, #7C3AED 0%, #DB2777 100%); background: linear-gradient(135deg, #3B82F6 0%, #8B5CF6 100%);
} }
.gradient-bg-secondary { .gradient-bg-secondary {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); background: linear-gradient(135deg, #60A5FA 0%, #F472B6 100%);
} }
.dark .gradient-bg-secondary { .dark .gradient-bg-secondary {
background: linear-gradient(135deg, #c471ed 0%, #c94b4b 100%); background: linear-gradient(135deg, #60A5FA 0%, #A78BFA 100%);
} }
.gradient-bg-accent { .gradient-bg-accent {
@ -410,16 +434,30 @@
} }
} }
/* Gradient Text - Purple/Pink theme */ /* Gradient Text - Blue/Pink in light, Blue/Purple in dark */
.gradient-text-primary { .gradient-text-primary {
background: linear-gradient(135deg, #9333EA 0%, #EC4899 100%); background: linear-gradient(135deg, #3B82F6 0%, #EC4899 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.dark .gradient-text-primary {
background: linear-gradient(135deg, #3B82F6 0%, #8B5CF6 100%);
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
background-clip: text; background-clip: text;
} }
.gradient-text-secondary { .gradient-text-secondary {
background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); background: linear-gradient(135deg, #60A5FA 0%, #F472B6 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
}
.dark .gradient-text-secondary {
background: linear-gradient(135deg, #60A5FA 0%, #A78BFA 100%);
-webkit-background-clip: text; -webkit-background-clip: text;
-webkit-text-fill-color: transparent; -webkit-text-fill-color: transparent;
background-clip: text; background-clip: text;

View File

@ -26,7 +26,7 @@ export default function HomePage() {
<Link href="/analysis"> <Link href="/analysis">
<Button <Button
size="lg" size="lg"
className="bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 shadow-lg hover:shadow-xl transition-shadow" className="bg-gradient-to-r from-blue-500 to-pink-500 dark:from-blue-600 dark:to-purple-600 hover:from-blue-600 hover:to-pink-600 dark:hover:from-blue-700 dark:hover:to-purple-700 shadow-lg hover:shadow-xl transition-all animate-heartbeat"
> >
</Button> </Button>
@ -335,7 +335,7 @@ export default function HomePage() {
<Link href="/analysis"> <Link href="/analysis">
<Button <Button
size="lg" size="lg"
className="bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 text-lg px-8 py-6 shadow-lg hover:shadow-2xl transition-all" className="bg-gradient-to-r from-blue-500 to-pink-500 dark:from-blue-600 dark:to-purple-600 hover:from-blue-600 hover:to-pink-600 dark:hover:from-blue-700 dark:hover:to-purple-700 text-lg px-8 py-6 shadow-lg hover:shadow-2xl transition-all animate-heartbeat"
> >
</Button> </Button>
@ -491,7 +491,7 @@ function WorkflowStep({
}) { }) {
return ( return (
<div className="flex gap-4 items-start"> <div className="flex gap-4 items-start">
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-gradient-to-r from-blue-600 to-purple-600 text-white flex items-center justify-center font-bold"> <div className="flex-shrink-0 w-8 h-8 rounded-full bg-gradient-to-r from-blue-500 to-pink-500 dark:from-blue-600 dark:to-purple-600 text-white flex items-center justify-center font-bold">
{number} {number}
</div> </div>
<div> <div>

View File

@ -151,47 +151,36 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
<FormField <FormField
control={form.control} control={form.control}
name="analysts" name="analysts"
render={() => ( render={({ field }) => (
<FormItem> <FormItem>
<div className="grid grid-cols-2 md:grid-cols-4 gap-4"> <div className="grid grid-cols-2 md:grid-cols-4 gap-4">
{ANALYSTS.map((analyst) => ( {ANALYSTS.map((analyst) => (
<FormField <FormItem
key={analyst.value} key={analyst.value}
control={form.control} className="flex flex-row items-start space-x-3 space-y-0"
name="analysts" >
render={({ field }) => { <FormControl>
return ( <Checkbox
<FormItem checked={field.value?.includes(analyst.value)}
key={analyst.value} onCheckedChange={(checked) => {
className="flex flex-row items-start space-x-3 space-y-0" return checked
> ? field.onChange([
<FormControl> ...(field.value ?? []),
<Checkbox analyst.value,
checked={field.value?.includes( ])
analyst.value : field.onChange(
)} field.value?.filter(
onCheckedChange={(checked) => { (value: string) =>
return checked value !== analyst.value
? field.onChange([ )
...(field.value ?? []), );
analyst.value, }}
]) />
: field.onChange( </FormControl>
field.value?.filter( <FormLabel className="font-normal cursor-pointer">
(value: string) => {analyst.label}
value !== analyst.value </FormLabel>
) </FormItem>
);
}}
/>
</FormControl>
<FormLabel className="font-normal cursor-pointer">
{analyst.label}
</FormLabel>
</FormItem>
);
}}
/>
))} ))}
</div> </div>
<FormMessage /> <FormMessage />
@ -798,7 +787,7 @@ export function AnalysisForm({ onSubmit, loading = false }: AnalysisFormProps) {
<Button <Button
type="submit" type="submit"
className="w-full bg-gradient-to-r from-blue-600 to-purple-600 hover:from-blue-700 hover:to-purple-700 shadow-lg hover:shadow-xl transition-all" className="w-full bg-gradient-to-r from-blue-500 to-pink-500 dark:from-blue-600 dark:to-purple-600 hover:from-blue-600 hover:to-pink-600 dark:hover:from-blue-700 dark:hover:to-purple-700 shadow-lg hover:shadow-xl transition-all animate-heartbeat"
disabled={loading} disabled={loading}
size="lg" size="lg"
> >

View File

@ -6,7 +6,7 @@ import { ThemeToggle } from "@/components/theme/ThemeToggle";
export function Header() { export function Header() {
return ( return (
<header className="border-b bg-gradient-to-r from-blue-600 to-purple-600 text-white"> <header className="border-b bg-gradient-to-r from-blue-500 to-pink-500 dark:from-blue-600 dark:to-purple-600 text-white">
<div className="container mx-auto px-4 py-6"> <div className="container mx-auto px-4 py-6">
<div className="flex items-center justify-between"> <div className="flex items-center justify-between">
<Link href="/" className="flex items-center gap-2"> <Link href="/" className="flex items-center gap-2">