conversation.tsx
styles.css
prompt.md
Collapse
Reset
Copy Code
Download
Run
1
"use client";
2
3
import React, { useEffect, useState } from "react";
4
import { motion, AnimatePresence } from "framer-motion";
5
import { cn } from "@/lib/utils";
6
import { Triangle } from "lucide-react";
7
8
const text1 = "What changed in the gallery this week?";
9
const text2 = "Checking every preview for the states that were still missing";
10
const text3 = "Found 3 without previews";
11
const text4 = "Fill those in and ship it.";
12
13
export function Conversation() {
14
const [step, setStep] = useState(0);
15
16
useEffect(() => {
17
let timeout: NodeJS.Timeout;
18
19
if (step === 0) {
20
timeout = setTimeout(() => setStep(1), 500); // Wait, then start
21
} else if (step === 1) {
22
timeout = setTimeout(() => setStep(2), 800); // Show typing
23
} else if (step === 2) {
24
timeout = setTimeout(() => setStep(3), 1200); // Show first system msg
25
} else if (step === 3) {
26
// It takes some time for the text to unblur. Give it 2s.
27
timeout = setTimeout(() => setStep(4), 2500); // Show second system msg
28
} else if (step === 4) {
29
timeout = setTimeout(() => setStep(5), 1500); // Show second user msg
30
} else if (step === 5) {
31
timeout = setTimeout(() => setStep(0), 4000); // Reset after 4s
32
}
33
34
return () => clearTimeout(timeout);
35
}, [step]);
36
37
return (
38
<div className="flex flex-col items-center justify-center w-full min-h-[500px] p-6 bg-transparent font-matter">
39
<div className="w-full max-w-[420px] flex flex-col gap-4">
40
<AnimatePresence>
41
{step >= 1 && (
42
<motion.div
43
layout
44
initial={{ opacity: 0, y: 10, scale: 0.95 }}
45
animate={{ opacity: 1, y: 0, scale: 1 }}
46
exit={{ opacity: 0, scale: 0.95 }}
47
transition={{ type: "spring", stiffness: 400, damping: 30 }}
48
className="self-end"
49
>
50
<div className="bg-[#007AFF] text-white px-4 py-2.5 rounded-[20px] rounded-br-[4px] max-w-[280px] text-[14.5px] leading-relaxed shadow-sm">
51
{text1}
52
</div>
53
</motion.div>
54
)}
55
56
{step === 2 && (
57
<motion.div
58
layout
59
initial={{ opacity: 0, y: 10, scale: 0.95 }}
60
animate={{ opacity: 1, y: 0, scale: 1 }}
61
exit={{ opacity: 0, scale: 0.95 }}
62
transition={{ type: "spring", stiffness: 400, damping: 30 }}
63
className="self-start"
64
>
65
<div className="bg-black/5 dark:bg-white/10 px-4 py-3 rounded-[20px] rounded-bl-[4px] shadow-sm flex items-center gap-1.5 h-[42px]">
66
<motion.div
67
className="w-1.5 h-1.5 rounded-full bg-black/40 dark:bg-white/40"
68
animate={{ y: [0, -3, 0] }}
69
transition={{ duration: 0.6, repeat: Infinity, delay: 0 }}
70
/>
71
<motion.div
72
className="w-1.5 h-1.5 rounded-full bg-black/40 dark:bg-white/40"
73
animate={{ y: [0, -3, 0] }}
74
transition={{ duration: 0.6, repeat: Infinity, delay: 0.2 }}
75
/>
76
<motion.div
77
className="w-1.5 h-1.5 rounded-full bg-black/40 dark:bg-white/40"
78
animate={{ y: [0, -3, 0] }}
79
transition={{ duration: 0.6, repeat: Infinity, delay: 0.4 }}
80
/>
81
</div>
82
</motion.div>
83
)}
84
85
{step >= 3 && (
86
<motion.div
87
layout
88
initial={{ opacity: 0, y: 10, scale: 0.95 }}
89
animate={{ opacity: 1, y: 0, scale: 1 }}
90
exit={{ opacity: 0, scale: 0.95 }}
91
transition={{ type: "spring", stiffness: 400, damping: 30 }}
92
className="self-start flex flex-col gap-2"
93
>
94
<div className="bg-black/5 dark:bg-white/10 text-black/90 dark:text-white/90 px-4 py-2.5 rounded-[20px] max-w-[280px] text-[14.5px] leading-relaxed shadow-sm">
95
{text2.split(" ").map((word, i) => (
96
<motion.span
97
key={i}
98
initial={{ filter: "blur(4px)", opacity: 0 }}
99
animate={{ filter: "blur(0px)", opacity: 1 }}
100
transition={{
101
duration: 0.4,
102
delay: i * 0.08, // Stagger words
103
}}
104
className="inline-block mr-1"
105
>
106
{word}
107
</motion.span>
108
))}
109
</div>
110
</motion.div>
111
)}
112
113
{step === 3 && (
114
<motion.div
115
layout
116
initial={{ opacity: 0, y: 10, scale: 0.95 }}
117
animate={{ opacity: 1, y: 0, scale: 1 }}
118
exit={{ opacity: 0, scale: 0.95 }}
119
transition={{ type: "spring", stiffness: 400, damping: 30 }}
120
className="self-start"
121
>
122
<div className="bg-black/5 dark:bg-white/10 px-3 py-2 rounded-[20px] rounded-bl-[4px] shadow-sm flex items-center justify-center w-[46px] h-[40px]">
123
<div className="relative flex items-center justify-center w-6 h-6">
124
{/* Spinning Ring */}
125
<motion.div
126
className="absolute inset-0 rounded-full border-[2px] border-transparent border-t-black dark:border-t-white opacity-50"
127
animate={{ rotate: 360 }}
128
transition={{ duration: 1, repeat: Infinity, ease: "linear" }}
129
/>
130
{/* Inner Icon */}
131
<div className="w-[18px] h-[18px] bg-black dark:bg-white rounded-full flex items-center justify-center">
132
<Triangle size={8} className="text-white dark:text-black fill-current translate-y-[-0.5px]" />
133
</div>
134
</div>
135
</div>
136
</motion.div>
137
)}
138
139
{step >= 4 && (
140
<motion.div
141
layout
142
initial={{ opacity: 0, y: 10, scale: 0.95 }}
143
animate={{ opacity: 1, y: 0, scale: 1 }}
144
exit={{ opacity: 0, scale: 0.95 }}
145
transition={{ type: "spring", stiffness: 400, damping: 30 }}
146
className="self-start"
147
>
148
<div className="bg-black/5 dark:bg-white/10 text-black/90 dark:text-white/90 px-3 py-2 rounded-[20px] rounded-bl-[4px] shadow-sm flex items-center gap-2.5 h-[40px] overflow-hidden whitespace-nowrap">
149
<div className="relative flex items-center justify-center w-6 h-6 shrink-0">
150
<div className="w-[18px] h-[18px] bg-black dark:bg-white rounded-full flex items-center justify-center">
151
<Triangle size={8} className="text-white dark:text-black fill-current translate-y-[-0.5px]" />
152
</div>
153
</div>
154
<motion.span
155
initial={{ opacity: 0, x: -5 }}
156
animate={{ opacity: 1, x: 0 }}
157
transition={{ duration: 0.3, delay: 0.1 }}
158
className="text-[14.5px] pr-2 font-medium"
159
>
160
{text3}
161
</motion.span>
162
</div>
163
</motion.div>
164
)}
165
166
{step >= 5 && (
167
<motion.div
168
layout
169
initial={{ opacity: 0, y: 10, scale: 0.95 }}
170
animate={{ opacity: 1, y: 0, scale: 1 }}
171
exit={{ opacity: 0, scale: 0.95 }}
172
transition={{ type: "spring", stiffness: 400, damping: 30 }}
173
className="self-end"
174
>
175
<div className="bg-[#007AFF] text-white px-4 py-2.5 rounded-[20px] rounded-br-[4px] max-w-[280px] text-[14.5px] leading-relaxed shadow-sm">
176
{text4}
177
</div>
178
</motion.div>
179
)}
180
</AnimatePresence>
181
</div>
182
</div>
183
);
184
}
185

