Skip to content

Commit b3a155d

Browse files
authored
fix: scroll behavior, browser back navigation, and weather widget sizing (#1336)
1 parent e90a6ee commit b3a155d

File tree

6 files changed

+152
-116
lines changed

6 files changed

+152
-116
lines changed

components/chat.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { useChat } from "@ai-sdk/react";
44
import { DefaultChatTransport } from "ai";
5-
import { useSearchParams } from "next/navigation";
5+
import { useRouter, useSearchParams } from "next/navigation";
66
import { useEffect, useRef, useState } from "react";
77
import useSWR, { useSWRConfig } from "swr";
88
import { unstable_serialize } from "swr/infinite";
@@ -50,12 +50,25 @@ export function Chat({
5050
autoResume: boolean;
5151
initialLastContext?: AppUsage;
5252
}) {
53+
const router = useRouter();
54+
5355
const { visibilityType } = useChatVisibility({
5456
chatId: id,
5557
initialVisibilityType,
5658
});
5759

5860
const { mutate } = useSWRConfig();
61+
62+
// Handle browser back/forward navigation
63+
useEffect(() => {
64+
const handlePopState = () => {
65+
// When user navigates back/forward, refresh to sync with URL
66+
router.refresh();
67+
};
68+
69+
window.addEventListener("popstate", handlePopState);
70+
return () => window.removeEventListener("popstate", handlePopState);
71+
}, [router]);
5972
const { setDataStream } = useDataStream();
6073

6174
const [input, setInput] = useState<string>("");

components/messages.tsx

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -44,51 +44,57 @@ function PureMessages({
4444
useDataStream();
4545

4646
return (
47-
<div
48-
className="relative flex-1 touch-pan-y overflow-y-auto"
49-
ref={messagesContainerRef}
50-
>
51-
<div className="mx-auto flex min-w-0 max-w-4xl flex-col gap-4 px-2 py-4 md:gap-6 md:px-4">
52-
{messages.length === 0 && <Greeting />}
47+
<div className="relative flex-1">
48+
<div
49+
className="absolute inset-0 touch-pan-y overflow-y-auto"
50+
ref={messagesContainerRef}
51+
>
52+
<div className="mx-auto flex min-w-0 max-w-4xl flex-col gap-4 px-2 py-4 md:gap-6 md:px-4">
53+
{messages.length === 0 && <Greeting />}
5354

54-
{messages.map((message, index) => (
55-
<PreviewMessage
56-
chatId={chatId}
57-
isLoading={status === "streaming" && messages.length - 1 === index}
58-
isReadonly={isReadonly}
59-
key={message.id}
60-
message={message}
61-
regenerate={regenerate}
62-
requiresScrollPadding={
63-
hasSentMessage && index === messages.length - 1
64-
}
65-
setMessages={setMessages}
66-
vote={
67-
votes
68-
? votes.find((vote) => vote.messageId === message.id)
69-
: undefined
70-
}
71-
/>
72-
))}
55+
{messages.map((message, index) => (
56+
<PreviewMessage
57+
chatId={chatId}
58+
isLoading={
59+
status === "streaming" && messages.length - 1 === index
60+
}
61+
isReadonly={isReadonly}
62+
key={message.id}
63+
message={message}
64+
regenerate={regenerate}
65+
requiresScrollPadding={
66+
hasSentMessage && index === messages.length - 1
67+
}
68+
setMessages={setMessages}
69+
vote={
70+
votes
71+
? votes.find((vote) => vote.messageId === message.id)
72+
: undefined
73+
}
74+
/>
75+
))}
7376

74-
{status === "submitted" && <ThinkingMessage />}
77+
{status === "submitted" && <ThinkingMessage />}
7578

76-
<div
77-
className="min-h-[24px] min-w-[24px] shrink-0"
78-
ref={messagesEndRef}
79-
/>
79+
<div
80+
className="min-h-[24px] min-w-[24px] shrink-0"
81+
ref={messagesEndRef}
82+
/>
83+
</div>
8084
</div>
8185

82-
{!isAtBottom && (
83-
<button
84-
aria-label="Scroll to bottom"
85-
className="-translate-x-1/2 absolute bottom-40 left-1/2 z-10 rounded-full border bg-background p-2 shadow-lg transition-colors hover:bg-muted"
86-
onClick={() => scrollToBottom("smooth")}
87-
type="button"
88-
>
89-
<ArrowDownIcon className="size-4" />
90-
</button>
91-
)}
86+
<button
87+
aria-label="Scroll to bottom"
88+
className={`-translate-x-1/2 absolute bottom-4 left-1/2 z-10 rounded-full border bg-background p-2 shadow-lg transition-all hover:bg-muted ${
89+
isAtBottom
90+
? "pointer-events-none scale-0 opacity-0"
91+
: "pointer-events-auto scale-100 opacity-100"
92+
}`}
93+
onClick={() => scrollToBottom("smooth")}
94+
type="button"
95+
>
96+
<ArrowDownIcon className="size-4" />
97+
</button>
9298
</div>
9399
);
94100
}

components/suggested-actions.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ function PureSuggestedActions({ chatId, sendMessage }: SuggestedActionsProps) {
3737
<Suggestion
3838
className="h-auto w-full whitespace-normal p-3 text-left"
3939
onClick={(suggestion) => {
40-
window.history.replaceState({}, "", `/chat/${chatId}`);
40+
window.history.pushState({}, "", `/chat/${chatId}`);
4141
sendMessage({
4242
role: "user",
4343
parts: [{ type: "text", text: suggestion }],

components/weather.tsx

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ export function Weather({
330330
return (
331331
<div
332332
className={cx(
333-
"relative flex w-full flex-col gap-6 overflow-hidden rounded-3xl p-6 shadow-lg backdrop-blur-sm",
333+
"relative flex w-full flex-col gap-3 overflow-hidden rounded-2xl p-4 shadow-lg backdrop-blur-sm",
334334
{
335335
"bg-gradient-to-br from-sky-400 via-blue-500 to-blue-600": isDay,
336336
},
@@ -343,44 +343,44 @@ export function Weather({
343343
<div className="absolute inset-0 bg-white/10 backdrop-blur-sm" />
344344

345345
<div className="relative z-10">
346-
<div className="mb-4 flex items-center justify-between">
347-
<div className="font-medium text-sm text-white/80">{location}</div>
346+
<div className="mb-2 flex items-center justify-between">
347+
<div className="font-medium text-white/80 text-xs">{location}</div>
348348
<div className="text-white/60 text-xs">
349349
{format(new Date(weatherAtLocation.current.time), "MMM d, h:mm a")}
350350
</div>
351351
</div>
352352

353-
<div className="mb-6 flex items-center justify-between">
354-
<div className="flex items-center gap-4">
353+
<div className="mb-3 flex items-center justify-between">
354+
<div className="flex items-center gap-3">
355355
<div
356356
className={cx("text-white/90", {
357357
"text-yellow-200": isDay,
358358
"text-blue-200": !isDay,
359359
})}
360360
>
361-
{isDay ? <SunIcon size={48} /> : <MoonIcon size={48} />}
361+
{isDay ? <SunIcon size={32} /> : <MoonIcon size={32} />}
362362
</div>
363-
<div className="font-light text-5xl text-white">
363+
<div className="font-light text-3xl text-white">
364364
{n(weatherAtLocation.current.temperature_2m)}
365-
<span className="text-2xl text-white/80">
365+
<span className="text-lg text-white/80">
366366
{weatherAtLocation.current_units.temperature_2m}
367367
</span>
368368
</div>
369369
</div>
370370

371371
<div className="text-right">
372-
<div className="font-medium text-sm text-white/90">
372+
<div className="font-medium text-white/90 text-xs">
373373
H: {n(currentHigh)}°
374374
</div>
375-
<div className="text-sm text-white/70">L: {n(currentLow)}°</div>
375+
<div className="text-white/70 text-xs">L: {n(currentLow)}°</div>
376376
</div>
377377
</div>
378378

379-
<div className="rounded-2xl bg-white/10 p-4 backdrop-blur-sm">
380-
<div className="mb-3 font-medium text-sm text-white/80">
379+
<div className="rounded-xl bg-white/10 p-3 backdrop-blur-sm">
380+
<div className="mb-2 font-medium text-white/80 text-xs">
381381
Hourly Forecast
382382
</div>
383-
<div className="flex justify-between gap-2">
383+
<div className="flex justify-between gap-1">
384384
{displayTimes.map((time, index) => {
385385
const hourTime = new Date(time);
386386
const isCurrentHour =
@@ -389,7 +389,7 @@ export function Weather({
389389
return (
390390
<div
391391
className={cx(
392-
"flex min-w-0 flex-1 flex-col items-center gap-2 rounded-lg px-1 py-2",
392+
"flex min-w-0 flex-1 flex-col items-center gap-1 rounded-md px-1 py-1.5",
393393
{
394394
"bg-white/20": isCurrentHour,
395395
}
@@ -406,10 +406,10 @@ export function Weather({
406406
"text-blue-200": !isDay,
407407
})}
408408
>
409-
<CloudIcon size={20} />
409+
<CloudIcon size={16} />
410410
</div>
411411

412-
<div className="font-medium text-sm text-white">
412+
<div className="font-medium text-white text-xs">
413413
{n(displayTemperatures[index])}°
414414
</div>
415415
</div>
@@ -418,7 +418,7 @@ export function Weather({
418418
</div>
419419
</div>
420420

421-
<div className="mt-4 flex justify-between text-white/60 text-xs">
421+
<div className="mt-2 flex justify-between text-white/60 text-xs">
422422
<div>
423423
Sunrise:{" "}
424424
{format(new Date(weatherAtLocation.daily.sunrise[0]), "h:mm a")}

0 commit comments

Comments
 (0)