Skip to content

Commit f5e0da6

Browse files
committed
合并 Claude 风格 UI 重设计到 main
2 parents 72f5de5 + 4f694b9 commit f5e0da6

File tree

9 files changed

+286
-330
lines changed

9 files changed

+286
-330
lines changed

src/components/ChatSection.tsx

Lines changed: 29 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -127,56 +127,53 @@ const ChatSection = () => {
127127
};
128128

129129
return (
130-
<section className="px-6 pb-12">
130+
<section className="px-6 pb-8">
131131
<div className="max-w-4xl mx-auto">
132-
<div className="backdrop-blur-xl bg-white/10 rounded-3xl border border-white/20 shadow-2xl overflow-hidden">
132+
<div className="bg-stone-900 rounded-2xl border border-stone-800 overflow-hidden">
133133
{/* Header */}
134-
<div className="bg-gradient-to-r from-purple-600/20 to-cyan-600/20 p-6 border-b border-white/10">
135-
<div className="flex items-center gap-4">
136-
<div className="w-11 h-11 bg-gradient-to-br from-cyan-400 to-purple-500 rounded-xl flex items-center justify-center shadow-lg shadow-cyan-900/30 shrink-0">
137-
<Bot className="text-white" size={22} />
134+
<div className="bg-stone-900 p-5 border-b border-stone-800">
135+
<div className="flex items-center gap-3">
136+
<div className="w-9 h-9 bg-stone-800 border border-stone-700 rounded-xl flex items-center justify-center shrink-0">
137+
<Bot className="text-[#cf6b47]" size={18} />
138138
</div>
139139
<div className="flex-1 min-w-0">
140-
<h2 className="text-xl font-bold text-white">Ask Anything About Me</h2>
141-
<p className="text-slate-400 text-sm">Powered by RAG · instant answers about background & projects</p>
140+
<h2 className="text-base font-semibold text-stone-100">Ask Anything About Me</h2>
141+
<p className="text-stone-500 text-xs">Powered by RAG · instant answers about background & projects</p>
142142
</div>
143143
{/* Server status pill */}
144-
<div className={`flex items-center gap-1.5 px-3 py-1.5 rounded-full text-xs font-medium border ${
144+
<div className={`flex items-center gap-1.5 px-2.5 py-1 rounded-full text-xs font-medium border ${
145145
isServerOnline
146-
? "bg-emerald-500/10 border-emerald-500/20 text-emerald-300"
147-
: "bg-red-500/10 border-red-500/20 text-red-300"
146+
? "bg-emerald-950/60 border-emerald-800/50 text-emerald-400"
147+
: "bg-red-950/60 border-red-800/50 text-red-400"
148148
}`}>
149-
{isServerOnline
150-
? <Wifi size={12} />
151-
: <WifiOff size={12} />
152-
}
149+
{isServerOnline ? <Wifi size={11} /> : <WifiOff size={11} />}
153150
{isServerOnline ? "Online" : "Offline"}
154151
</div>
155152
</div>
156153

157154
{!isServerOnline && (
158-
<div className="mt-4 bg-red-500/10 rounded-xl p-3 border border-red-500/20 flex items-center gap-3">
159-
<AlertCircle className="text-red-400 shrink-0" size={16} />
160-
<p className="text-sm text-red-300">AI server is offline. Responses may be unavailable.</p>
155+
<div className="mt-3 bg-red-950/40 rounded-xl p-3 border border-red-900/50 flex items-center gap-2.5">
156+
<AlertCircle className="text-red-400 shrink-0" size={15} />
157+
<p className="text-sm text-red-400">AI server is offline. Responses may be unavailable.</p>
161158
</div>
162159
)}
163160
</div>
164161

165162
{/* Messages */}
166163
<div
167164
ref={scrollContainerRef}
168-
className="h-96 overflow-y-auto p-6 space-y-4 scrollbar-thin scrollbar-thumb-white/20 scrollbar-track-transparent"
165+
className="h-96 overflow-y-auto p-5 space-y-4 scrollbar-thin scrollbar-thumb-stone-700 scrollbar-track-transparent"
169166
>
170167
{messages.map((message) => (
171168
<MessageBubble key={message.id} message={message} />
172169
))}
173170
{isLoading && (
174171
<div className="flex justify-start">
175-
<div className="bg-white/10 backdrop-blur-sm rounded-2xl px-5 py-3">
172+
<div className="bg-stone-800 rounded-2xl px-4 py-3 border border-stone-700/60">
176173
<div className="flex space-x-1.5 items-center">
177-
<div className="w-2 h-2 bg-cyan-400 rounded-full animate-bounce" style={{ animationDelay: '0ms' }}></div>
178-
<div className="w-2 h-2 bg-purple-400 rounded-full animate-bounce" style={{ animationDelay: '150ms' }}></div>
179-
<div className="w-2 h-2 bg-pink-400 rounded-full animate-bounce" style={{ animationDelay: '300ms' }}></div>
174+
<div className="w-1.5 h-1.5 bg-stone-400 rounded-full animate-bounce" style={{ animationDelay: '0ms' }}></div>
175+
<div className="w-1.5 h-1.5 bg-stone-400 rounded-full animate-bounce" style={{ animationDelay: '150ms' }}></div>
176+
<div className="w-1.5 h-1.5 bg-stone-400 rounded-full animate-bounce" style={{ animationDelay: '300ms' }}></div>
180177
</div>
181178
</div>
182179
</div>
@@ -185,36 +182,36 @@ const ChatSection = () => {
185182
</div>
186183

187184
{/* Input + Chips */}
188-
<div className="p-6 bg-slate-900/30 border-t border-white/10 space-y-4">
185+
<div className="p-5 bg-stone-950/50 border-t border-stone-800 space-y-3">
189186
{/* Input row */}
190-
<div className="flex gap-3">
187+
<div className="flex gap-2">
191188
<Input
192189
value={inputValue}
193190
onChange={(e) => setInputValue(e.target.value)}
194191
onKeyDown={handleKeyPress}
195192
placeholder="Ask me anything about my background..."
196-
className="bg-slate-800/60 border-white/10 text-white placeholder:text-slate-500 backdrop-blur-sm rounded-xl focus-visible:ring-cyan-500/50"
193+
className="bg-stone-800 border-stone-700 text-stone-100 placeholder:text-stone-500 rounded-xl focus-visible:ring-[#cf6b47]/40 focus-visible:border-stone-600"
197194
disabled={isLoading || !isServerOnline}
198195
/>
199196
<Button
200197
onClick={() => handleSendMessage(inputValue)}
201198
disabled={isLoading || !inputValue.trim() || !isServerOnline}
202-
className="rounded-xl px-4 bg-cyan-500/20 hover:bg-cyan-500/30 text-cyan-300 border border-cyan-500/30 transition-all duration-200 disabled:opacity-40"
199+
className="rounded-xl px-3.5 bg-[#cf6b47]/20 hover:bg-[#cf6b47]/30 text-[#cf6b47] border border-[#cf6b47]/30 hover:border-[#cf6b47]/50 transition-all duration-150 disabled:opacity-40"
203200
>
204-
<Send size={16} />
201+
<Send size={15} />
205202
</Button>
206203
</div>
207204

208-
{/* Predefined question chips — flex-wrap */}
205+
{/* Predefined question chips */}
209206
<div>
210-
<p className="text-xs text-slate-500 mb-2 font-medium uppercase tracking-wide">Try asking</p>
211-
<div className="flex flex-wrap gap-2">
207+
<p className="text-xs text-stone-600 mb-2 font-medium uppercase tracking-wider">Try asking</p>
208+
<div className="flex flex-wrap gap-1.5">
212209
{PREDEFINED_QUESTIONS.map((question, index) => (
213210
<button
214211
key={index}
215212
onClick={() => handleSendMessage(question)}
216213
disabled={isLoading || !isServerOnline}
217-
className="px-3 py-1.5 text-xs bg-white/5 hover:bg-white/10 border border-white/10 hover:border-cyan-500/30 text-slate-300 hover:text-white rounded-full transition-all duration-200 disabled:opacity-40 disabled:cursor-not-allowed"
214+
className="px-3 py-1.5 text-xs border border-stone-700 text-stone-400 hover:border-stone-600 hover:text-stone-300 rounded-full transition-all duration-150 disabled:opacity-40 disabled:cursor-not-allowed"
218215
>
219216
{question}
220217
</button>

src/components/GetInTouchSection.tsx

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -53,65 +53,70 @@ const GetInTouchSection = () => {
5353

5454
return (
5555
<section className="px-6 pt-2 pb-12">
56-
<div className="max-w-6xl mx-auto">
57-
<div className="backdrop-blur-xl bg-white/10 rounded-3xl border border-white/20 p-8 shadow-2xl">
56+
<div className="max-w-4xl mx-auto">
57+
<div className="bg-stone-900 rounded-2xl border border-stone-800 p-8">
5858
<div className="grid grid-cols-1 lg:grid-cols-2 gap-10">
5959
{/* Form side */}
6060
<div>
61-
<h2 className="text-3xl font-bold bg-gradient-to-r from-white to-cyan-400 bg-clip-text text-transparent mb-2">
61+
<h2 className="text-2xl font-bold text-stone-100 mb-1.5 tracking-tight">
6262
Get in Touch
6363
</h2>
64-
{/* mailto notice */}
65-
<p className="text-slate-400 text-sm mb-6 flex items-center gap-1.5">
66-
<ExternalLink size={13} className="shrink-0 text-slate-500" />
64+
<p className="text-stone-500 text-sm mb-6 flex items-center gap-1.5">
65+
<ExternalLink size={12} className="shrink-0" />
6766
Clicking "Send" will open your default email client with the form pre-filled.
6867
</p>
6968

70-
<form onSubmit={handleSubmit} className="space-y-5">
71-
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
69+
<form onSubmit={handleSubmit} className="space-y-4">
70+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
7271
<div>
73-
<label className="block text-slate-300 text-sm mb-1.5 font-medium">Name <span className="text-red-400">*</span></label>
72+
<label className="block text-stone-400 text-sm mb-1.5 font-medium">
73+
Name <span className="text-red-500">*</span>
74+
</label>
7475
<Input
7576
placeholder="Your name"
7677
value={form.name}
7778
onChange={(e) => setForm({ ...form, name: e.target.value })}
78-
className="bg-slate-800/60 border-white/10 text-white placeholder:text-slate-500 focus-visible:ring-cyan-500/50"
79+
className="bg-stone-800 border-stone-700 text-stone-100 placeholder:text-stone-600 focus-visible:ring-[#cf6b47]/40 focus-visible:border-stone-600"
7980
/>
8081
</div>
8182
<div>
82-
<label className="block text-slate-300 text-sm mb-1.5 font-medium">Company</label>
83+
<label className="block text-stone-400 text-sm mb-1.5 font-medium">Company</label>
8384
<Input
8485
placeholder="Company (optional)"
8586
value={form.company}
8687
onChange={(e) => setForm({ ...form, company: e.target.value })}
87-
className="bg-slate-800/60 border-white/10 text-white placeholder:text-slate-500 focus-visible:ring-cyan-500/50"
88+
className="bg-stone-800 border-stone-700 text-stone-100 placeholder:text-stone-600 focus-visible:ring-[#cf6b47]/40 focus-visible:border-stone-600"
8889
/>
8990
</div>
9091
</div>
9192
<div>
92-
<label className="block text-slate-300 text-sm mb-1.5 font-medium">Email <span className="text-red-400">*</span></label>
93+
<label className="block text-stone-400 text-sm mb-1.5 font-medium">
94+
Email <span className="text-red-500">*</span>
95+
</label>
9396
<Input
9497
type="email"
9598
placeholder="you@example.com"
9699
value={form.email}
97100
onChange={(e) => setForm({ ...form, email: e.target.value })}
98-
className="bg-slate-800/60 border-white/10 text-white placeholder:text-slate-500 focus-visible:ring-cyan-500/50"
101+
className="bg-stone-800 border-stone-700 text-stone-100 placeholder:text-stone-600 focus-visible:ring-[#cf6b47]/40 focus-visible:border-stone-600"
99102
/>
100103
</div>
101104
<div>
102-
<label className="block text-slate-300 text-sm mb-1.5 font-medium">Message <span className="text-red-400">*</span></label>
105+
<label className="block text-stone-400 text-sm mb-1.5 font-medium">
106+
Message <span className="text-red-500">*</span>
107+
</label>
103108
<Textarea
104109
placeholder="Tell me about your needs and how I can help..."
105110
rows={5}
106111
value={form.message}
107112
onChange={(e) => setForm({ ...form, message: e.target.value })}
108-
className="bg-slate-800/60 border-white/10 text-white placeholder:text-slate-500 focus-visible:ring-cyan-500/50 resize-none"
113+
className="bg-stone-800 border-stone-700 text-stone-100 placeholder:text-stone-600 focus-visible:ring-[#cf6b47]/40 focus-visible:border-stone-600 resize-none"
109114
/>
110115
</div>
111116
<Button
112117
type="submit"
113118
disabled={submitting}
114-
className="bg-cyan-600/20 hover:bg-cyan-600/30 text-cyan-300 border border-cyan-500/30 rounded-xl px-6 transition-all duration-200 hover:scale-[1.02]"
119+
className="bg-[#cf6b47]/20 hover:bg-[#cf6b47]/30 text-[#cf6b47] border border-[#cf6b47]/30 hover:border-[#cf6b47]/50 rounded-xl px-5 transition-all duration-150"
115120
>
116121
{submitting ? "Opening email client…" : "Send Message"}
117122
</Button>
@@ -121,36 +126,44 @@ const GetInTouchSection = () => {
121126
{/* Contact info side */}
122127
<div className="space-y-6">
123128
<div>
124-
<h3 className="text-2xl font-semibold text-white mb-2">Let's Start a Conversation</h3>
125-
<p className="text-slate-400 text-sm">
129+
<h3 className="text-xl font-semibold text-stone-100 mb-2">Let's Start a Conversation</h3>
130+
<p className="text-stone-500 text-sm">
126131
Happy to connect about opportunities, collaboration, or any interesting ideas.
127132
</p>
128133
</div>
129-
<div className="space-y-3">
134+
<div className="space-y-2.5">
130135
{[
131136
{
132-
icon: <Mail className="text-cyan-400" />,
133-
bg: "bg-cyan-600/20",
137+
icon: <Mail size={16} className="text-stone-400" />,
134138
label: "Email",
135-
content: <a href="mailto:baoyifei@bu.edu" className="text-white hover:text-cyan-300 transition-colors text-sm">baoyifei@bu.edu</a>,
139+
content: (
140+
<a href="mailto:baoyifei@bu.edu" className="text-stone-300 hover:text-stone-100 transition-colors text-sm">
141+
baoyifei@bu.edu
142+
</a>
143+
),
136144
},
137145
{
138-
icon: <Phone className="text-emerald-400" />,
139-
bg: "bg-emerald-600/20",
146+
icon: <Phone size={16} className="text-stone-400" />,
140147
label: "Phone",
141-
content: <a href="tel:+18573403064" className="text-white hover:text-emerald-300 transition-colors text-sm">+1 857 340 3064</a>,
148+
content: (
149+
<a href="tel:+18573403064" className="text-stone-300 hover:text-stone-100 transition-colors text-sm">
150+
+1 857 340 3064
151+
</a>
152+
),
142153
},
143154
{
144-
icon: <MapPin className="text-blue-400" />,
145-
bg: "bg-blue-600/20",
155+
icon: <MapPin size={16} className="text-stone-400" />,
146156
label: "Location",
147-
content: <span className="text-white text-sm">Boston, MA</span>,
157+
content: <span className="text-stone-300 text-sm">Boston, MA</span>,
148158
},
149-
].map(({ icon, bg, label, content }) => (
150-
<div key={label} className="flex items-center gap-4 p-4 rounded-xl bg-white/5 border border-white/10 hover:border-white/20 transition-all duration-200">
151-
<div className={`p-2.5 rounded-lg ${bg} shrink-0`}>{icon}</div>
159+
].map(({ icon, label, content }) => (
160+
<div
161+
key={label}
162+
className="flex items-center gap-3.5 p-3.5 rounded-xl bg-stone-800/60 border border-stone-700/60 hover:border-stone-700 transition-all duration-150"
163+
>
164+
<div className="shrink-0">{icon}</div>
152165
<div>
153-
<div className="text-slate-500 text-xs mb-0.5">{label}</div>
166+
<div className="text-stone-600 text-xs mb-0.5">{label}</div>
154167
{content}
155168
</div>
156169
</div>

src/components/MessageBubble.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,16 @@ const MessageBubble = ({ message }: MessageBubbleProps) => {
1515
return (
1616
<div className={`flex ${message.isUser ? "justify-end" : "justify-start"}`}>
1717
<div
18-
className={`max-w-xs lg:max-w-md px-4 py-3 rounded-2xl backdrop-blur-sm ${
18+
className={`max-w-xs lg:max-w-md px-4 py-3 rounded-2xl ${
1919
message.isUser
20-
? "bg-cyan-500/20 text-cyan-100 border border-cyan-500/30 shadow-lg"
21-
: "bg-white/10 text-slate-100 border border-white/20"
20+
? "bg-[#cf6b47]/15 text-stone-100 border border-[#cf6b47]/25"
21+
: "bg-stone-800 text-stone-200 border border-stone-700/60"
2222
}`}
2323
>
24-
<div className="prose prose-sm prose-invert max-w-none">
24+
<div className="prose prose-sm prose-invert max-w-none prose-p:text-stone-200 prose-strong:text-stone-100">
2525
<ReactMarkdown>{message.text}</ReactMarkdown>
2626
</div>
27-
<p className={`text-xs mt-2 ${message.isUser ? "text-cyan-200/80" : "text-slate-400"}`}>
27+
<p className={`text-xs mt-1.5 ${message.isUser ? "text-stone-400" : "text-stone-500"}`}>
2828
{message.timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}
2929
</p>
3030
</div>

0 commit comments

Comments
 (0)