feat: add animations

This commit is contained in:
Henry Li
2026-02-07 10:30:35 +08:00
parent c3f9089e95
commit fc543a9b30
2 changed files with 67 additions and 43 deletions

View File

@@ -5,7 +5,10 @@ import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { Icon } from "@radix-ui/react-select"; import { Icon } from "@radix-ui/react-select";
import type { LucideIcon } from "lucide-react"; import type { LucideIcon } from "lucide-react";
import type { ComponentProps } from "react"; import { Children, type ComponentProps } from "react";
const STAGGER_DELAY_MS = 60;
const STAGGER_DELAY_MS_OFFSET = 200;
export type SuggestionsProps = ComponentProps<typeof ScrollArea>; export type SuggestionsProps = ComponentProps<typeof ScrollArea>;
@@ -16,7 +19,20 @@ export const Suggestions = ({
}: SuggestionsProps) => ( }: SuggestionsProps) => (
<ScrollArea className="overflow-x-auto whitespace-nowrap" {...props}> <ScrollArea className="overflow-x-auto whitespace-nowrap" {...props}>
<div className={cn("flex w-max flex-nowrap items-center gap-2", className)}> <div className={cn("flex w-max flex-nowrap items-center gap-2", className)}>
{children} {Children.map(children, (child, index) =>
child != null ? (
<span
className="animate-fade-in-up inline-block opacity-0"
style={{
animationDelay: `${STAGGER_DELAY_MS_OFFSET + index * STAGGER_DELAY_MS}ms`,
}}
>
{child}
</span>
) : (
child
),
)}
</div> </div>
<ScrollBar className="hidden" orientation="horizontal" /> <ScrollBar className="hidden" orientation="horizontal" />
</ScrollArea> </ScrollArea>

View File

@@ -85,6 +85,17 @@
} }
} }
--animate-fade-in-up: fade-in-up 0.15s ease-in-out forwards;
@keyframes fade-in-up {
0% {
opacity: 0;
transform: translateY(1rem) scale(1.2);
}
100% {
opacity: 1;
}
}
--animate-bouncing: bouncing 0.5s infinite alternate; --animate-bouncing: bouncing 0.5s infinite alternate;
@keyframes bouncing { @keyframes bouncing {
to { to {
@@ -104,6 +115,18 @@
transform: scaleX(1); transform: scaleX(1);
} }
} }
--animate-suggestion-in: suggestion-in 0.2s ease-out forwards;
@keyframes suggestion-in {
0% {
opacity: 0;
transform: translateY(-1.25rem);
}
100% {
opacity: 1;
transform: translateY(0);
}
}
} }
@theme inline { @theme inline {
@@ -145,57 +168,42 @@
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-border: var(--sidebar-border); --color-sidebar-border: var(--sidebar-border);
--color-sidebar-ring: var(--sidebar-ring); --color-sidebar-ring: var(--sidebar-ring);
--animate-aurora: --animate-aurora: aurora 8s ease-in-out infinite alternate;
aurora 8s ease-in-out infinite alternate;
@keyframes aurora { @keyframes aurora {
0% { 0% {
background-position: background-position: 0% 50%;
0% 50%; transform: rotate(-5deg) scale(0.9);
transform:
rotate(-5deg) scale(0.9);
} }
25% { 25% {
background-position: background-position: 50% 100%;
50% 100%; transform: rotate(5deg) scale(1.1);
transform:
rotate(5deg) scale(1.1);
} }
50% { 50% {
background-position: background-position: 100% 50%;
100% 50%; transform: rotate(-3deg) scale(0.95);
transform:
rotate(-3deg) scale(0.95);
} }
75% { 75% {
background-position: background-position: 50% 0%;
50% 0%; transform: rotate(3deg) scale(1.05);
transform:
rotate(3deg) scale(1.05);
} }
100% { 100% {
background-position: background-position: 0% 50%;
0% 50%; transform: rotate(-5deg) scale(0.9);
transform:
rotate(-5deg) scale(0.9);
} }
} }
--animate-shine: --animate-shine: shine var(--duration) infinite linear;
shine var(--duration) infinite linear
;
@keyframes shine { @keyframes shine {
0% { 0% {
background-position: background-position: 0% 0%;
0% 0%;
} }
50% { 50% {
background-position: background-position: 100% 100%;
100% 100%;
} }
to { to {
background-position: background-position: 0% 0%;
0% 0%;
} }
}} }
}
:root { :root {
--radius: 0.625rem; --radius: 0.625rem;
@@ -297,4 +305,4 @@
--container-width-sm: calc(var(--spacing) * 144); --container-width-sm: calc(var(--spacing) * 144);
--container-width-md: calc(var(--spacing) * 204); --container-width-md: calc(var(--spacing) * 204);
--container-width-lg: calc(var(--spacing) * 256); --container-width-lg: calc(var(--spacing) * 256);
} }