Animated List

An accessible and customizable AnimatedList component that lists items with sequential animations.

🚀

Item 1

Item 1 description

Active
📦

Item 2

Item 2 description

Inactive
💡

Item 3

Item 3 description

Active
🎯

Item 4

Item 4 description

Pending
🔒

Item 5

Item 5 description

Active

Item 6

Item 6 description

Inactive

Install

pnpm dlx shadcn@latest add https://www.katestroyui.com/r/animated-list

Usage

1import { AnimatedList } from "@/components/ui/animated-list";
2import { useState, useMemo } from "react";
3import { cn } from "@/lib/utils";
4
5const listItems = [
6 {
7 id: 1,
8 title: "Item 1",
9 gradient: "from-blue-500 to-purple-600",
10 description: "Item 1 description",
11 icon: "🚀",
12 status: "Active",
13 },
14 {
15 id: 2,
16 title: "Item 2",
17 gradient: "from-green-500 to-teal-600",
18 description: "Item 2 description",
19 icon: "📦",
20 status: "Inactive",
21 },
22 {
23 id: 3,
24 title: "Item 3",
25 gradient: "from-orange-500 to-red-600",
26 description: "Item 3 description",
27 icon: "💡",
28 status: "Active",
29 },
30 {
31 id: 4,
32 title: "Item 4",
33 gradient: "from-purple-500 to-pink-600",
34 description: "Item 4 description",
35 icon: "🎯",
36 status: "Pending",
37 },
38 {
39 id: 5,
40 title: "Item 5",
41 gradient: "from-teal-500 to-cyan-600",
42 description: "Item 5 description",
43 icon: "🔒",
44 status: "Active",
45 },
46 {
47 id: 6,
48 title: "Item 6",
49 gradient: "from-indigo-500 to-blue-600",
50 description: "Item 6 description",
51 icon: "⚡",
52 status: "Inactive",
53 },
54];
55
56export function Example() {
57 const [listDirection, setListDirection] = useState("vertical");
58
59 return (
60 <>
61 <button
62 onClick={() => setListDirection((prev) => prev === "vertical" ? "horizontal" : "vertical")}
63 className="mb-4 px-4 py-2 border rounded"
64 >
65 {listDirection === "vertical" ? "Grid" : "List"}
66 </button>
67 <AnimatedList
68 key={listDirection}
69 className={
70 listDirection === "horizontal"
71 ? "grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4"
72 : "flex flex-col gap-4"
73 }
74 itemClassName={listDirection === "horizontal" ? "" : "w-full"}
75 direction={listDirection}
76 >
77 {listItems.map((item) =>
78 listDirection === "horizontal" ? (
79 <div
80 key={item.id}
81 className={cn(
82 "relative group rounded-xl border border-zinc-200 dark:border-zinc-800 bg-gradient-to-br from-white/90 to-zinc-100 dark:from-zinc-900 dark:to-zinc-800 shadow-sm hover:shadow-lg transition-all duration-200 hover:-translate-y-1 hover:border-primary/60 flex flex-col justify-between p-6 h-56"
83 )}
84 >
85 <div className="flex items-start justify-between mb-3">
86 <div
87 className={cn(
88 "w-12 h-12 rounded-full flex items-center justify-center text-2xl font-bold shadow bg-gradient-to-br",
89 item.gradient
90 )}
91 >
92 <span role="img" aria-label="icon">{item.icon}</span>
93 </div>
94 </div>
95 <div className="flex-1">
96 <h3 className="text-lg font-bold text-zinc-900 dark:text-white mb-1 truncate">{item.title}</h3>
97 <p className="text-sm text-zinc-600 dark:text-zinc-300 line-clamp-2">{item.description}</p>
98 </div>
99 <div className="mt-4">
100 <span className="inline-block px-3 py-1 text-xs rounded-full bg-primary/10 text-primary font-medium">
101 {item.status}
102 </span>
103 </div>
104 </div>
105 ) : (
106 <div
107 key={item.id}
108 className={cn(
109 "relative group rounded-lg border border-zinc-200 dark:border-zinc-800 bg-white dark:bg-zinc-900 shadow-sm hover:shadow-md transition-all duration-200 hover:border-primary/60 flex items-center gap-4 px-4 py-3"
110 )}
111 >
112 <div
113 className={cn(
114 "w-10 h-10 rounded-full flex items-center justify-center text-xl font-bold shadow bg-gradient-to-br",
115 item.gradient
116 )}
117 >
118 <span role="img" aria-label="icon">{item.icon}</span>
119 </div>
120 <div className="flex-1 min-w-0">
121 <h3 className="text-base font-semibold text-zinc-900 dark:text-white truncate">{item.title}</h3>
122 <p className="text-xs text-zinc-600 dark:text-zinc-300 truncate">{item.description}</p>
123 </div>
124 <span className="inline-block px-2 py-0.5 text-xs rounded-full bg-primary/10 text-primary font-medium">
125 {item.status}
126 </span>
127 </div>
128 )
129 )}
130 </AnimatedList>
131 </>
132 );
133}

Props

PropTypeDescriptionDefault
childrenReact.ReactNodeList items-