Files
upstream-shadcn-ui/apps/v4/examples/radix/message-scroller-load-history.tsx
upstream-mirror 1416db152c
All checks were successful
Release / Create Version PR or Publish Stable Release (push) Has been skipped
Release / Publish Prerelease to NPM (push) Has been skipped
Monitor Registries / Monitor registry health (push) Has been skipped
snapshot of https://github.com/shadcn-ui/ui.git (main, 2026-09-15; blobs > 131072B omitted)
2026-09-15 22:44:43 +05:00

170 lines
7.0 KiB
TypeScript

"use client"
import * as React from "react"
import { RotateCwIcon } from "lucide-react"
import { toast } from "sonner"
import { createChat, getMessageText } from "@/lib/ai"
import { Bubble, BubbleContent } from "@/styles/radix-rhea/ui/bubble"
import { Button } from "@/styles/radix-rhea/ui/button"
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/styles/radix-rhea/ui/card"
import { Marker, MarkerContent } from "@/styles/radix-rhea/ui/marker"
import { Message, MessageContent } from "@/styles/radix-rhea/ui/message"
import {
MessageScroller,
MessageScrollerButton,
MessageScrollerContent,
MessageScrollerItem,
MessageScrollerProvider,
MessageScrollerViewport,
} from "@/styles/radix-rhea/ui/message-scroller"
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/styles/radix-rhea/ui/tooltip"
const chat = createChat()
.user("Can you summarize the incident channel?")
.assistant(
"The first alert was a delayed export job. It started backing up around 09:42 UTC and triggered the warning once the retry queue crossed the threshold.\n\nNo customer-facing checkout paths were affected, but exports for larger workspaces were running about 12 minutes behind."
)
.user("Was checkout affected?")
.assistant(
"No checkout errors were reported. Payment authorization, order creation, and confirmation emails stayed inside their normal latency bands.\n\nThe only elevated metric was export queue depth, which maps to analytics downloads instead of checkout."
)
.user("What changed in the last deploy?")
.assistant(
"Only the export queue worker changed. The deploy moved large CSV jobs onto the shared retry policy, which made each failed attempt hold a worker slot longer than before.\n\nThe app deploy did not include checkout, pricing, or billing API changes."
)
.user("Do we need to roll back?")
.assistant(
"Not yet. Queue depth is recovering after we reduced retry concurrency, and the oldest pending job is now under five minutes old.\n\nKeep rollback ready if the queue starts climbing again, but the current trend points toward recovery."
)
.user("Keep watching for customer-visible issues.")
.assistant(
"I will watch the queue and support tags for another 15 minutes. I am tracking export failures, delayed download requests, and any support thread that mentions missing reports.\n\nIf those stay quiet through the next batch window, we can close this as an internal degradation."
)
const history = chat.get()
const INITIAL_VISIBLE_COUNT = 5
export function MessageScrollerLoadHistory() {
const [demoKey, setDemoKey] = React.useState(0)
const [visibleCount, setVisibleCount] = React.useState(INITIAL_VISIBLE_COUNT)
const visibleMessages = history.slice(-visibleCount)
const canLoadHistory = visibleCount < history.length
return (
<MessageScrollerProvider>
<div className="relative flex flex-col gap-4">
<Card className="mx-auto h-140 w-full max-w-sm gap-0">
<CardHeader className="gap-1 border-b">
<CardTitle>Load History</CardTitle>
<CardDescription>
Prepended messages keep your place.
</CardDescription>
<CardAction>
<Tooltip>
<TooltipTrigger asChild>
<Button
type="button"
variant="outline"
size="icon"
aria-label="Reset loaded messages"
disabled={visibleCount === INITIAL_VISIBLE_COUNT}
onClick={() => {
setVisibleCount(INITIAL_VISIBLE_COUNT)
setDemoKey((key) => key + 1)
}}
>
<RotateCwIcon />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Reset</p>
</TooltipContent>
</Tooltip>
</CardAction>
</CardHeader>
<CardContent className="flex-1 overflow-hidden p-0">
<MessageScroller key={demoKey}>
<MessageScrollerViewport>
<MessageScrollerContent className="p-(--card-spacing)">
{visibleMessages.map((message) => {
const isUserMessage = message.role === "user"
return (
<MessageScrollerItem
key={message.id}
messageId={message.id}
>
<Message align={isUserMessage ? "end" : "start"}>
<MessageContent>
<Bubble variant={isUserMessage ? "muted" : "ghost"}>
<BubbleContent className="space-y-2">
{getMessageText(message)
.split(/\n\s*\n/)
.map((paragraph) => paragraph.trim())
.filter(Boolean)
.map((paragraph, index) => (
<p
key={index}
className="whitespace-pre-wrap"
>
{paragraph}
</p>
))}
</BubbleContent>
</Bubble>
</MessageContent>
</Message>
</MessageScrollerItem>
)
})}
<MessageScrollerItem scrollAnchor={false}>
<Marker variant="separator">
<MarkerContent>End of Conversation</MarkerContent>
</Marker>
</MessageScrollerItem>
</MessageScrollerContent>
</MessageScrollerViewport>
<MessageScrollerButton />
</MessageScroller>
</CardContent>
<CardFooter className="flex flex-col items-center gap-2 border-t">
<Button
type="button"
disabled={!canLoadHistory}
onClick={() => {
setVisibleCount(history.length)
toast("History loaded", {
description: "Scroll up to see earlier messages.",
})
}}
className="w-full"
variant="secondary"
>
{canLoadHistory ? "Load History" : "History Loaded"}
</Button>
<p className="text-xs text-muted-foreground">
Restore earlier messages while keeping your place.
</p>
</CardFooter>
</Card>
<div className="mx-auto max-w-sm px-0.5 text-center text-xs text-balance text-muted-foreground">
Click Load History to load the entire conversation
</div>
</div>
</MessageScrollerProvider>
)
}