Message scroller
对话的滚动区域:停留在底部时自动跟随最新发言,向上翻阅历史时位置保持不动。
安装
# once per project: where @zzzui items come frompnpm dlx shadcn@latest registry add @zzzui=https://zzzui.catforest.dev/r/{name}.jsonpnpm dlx shadcn@latest add @zzzui/message-scroller示例
自动跟随最新发言的对话
import { useState } from "react";import { Bubble, BubbleContent } from "@/components/zero/bubble";import { Button } from "@/components/zero/button";import { Marker, MarkerContent } from "@/components/zero/marker";import { Message, MessageContent, MessageHeader,} from "@/components/zero/message";import { MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport,} from "@/components/zero/message-scroller";const lines = [ "Leaving the yards now.", "Gate 4 is shut.", "Taking the canal.", "Passing Tower 9.", "Two minutes out.", "At the north gate.",];export default function MessageScrollerChat() { const [turns, setTurns] = useState(lines.slice(0, 4)); return ( <div className="grid w-full max-w-md gap-3"> <div className="h-72 border-(length:--zero-stroke-thin) border-zero-line bg-zero-void"> <MessageScrollerProvider> <MessageScroller> <MessageScrollerViewport> <MessageScrollerContent className="gap-4 p-4"> <MessageScrollerItem> <Marker variant="separator"> <MarkerContent>Tonight</MarkerContent> </Marker> </MessageScrollerItem> {turns.map((line, index) => ( <MessageScrollerItem key={line} scrollAnchor={index === turns.length - 1} > <Message align={index % 2 ? "end" : "start"}> <MessageContent> <MessageHeader> <strong>{index % 2 ? "You" : "Mara"}</strong> 21:{String(4 + index).padStart(2, "0")} </MessageHeader> <Bubble variant={index % 2 ? "default" : "secondary"}> <BubbleContent>{line}</BubbleContent> </Bubble> </MessageContent> </Message> </MessageScrollerItem> ))} </MessageScrollerContent> </MessageScrollerViewport> <MessageScrollerButton /> </MessageScroller> </MessageScrollerProvider> </div> <Button variant="secondary" size="sm" disabled={turns.length === lines.length} onClick={() => setTurns(lines.slice(0, turns.length + 1))} > Next message </Button> </div> );}行为
滚动位置离开底部时,会出现一个带箭头的浮起色斜切块,点击即可返回底部。用 scrollAnchor 标记最新一轮发言。底层是 @shadcn/react 的 message scroller;通过 useMessageScroller 可获取其控制方法。
属性
MessageScrollerItem
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| scrollAnchor | boolean | false | 有新发言进入时,保持在视野内的那一轮发言。 |
MessageScrollerButton
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| direction | "end" | "start" | "end" | 返回最新一轮发言,或跳至第一轮。 |
| label | string | "Scroll to the newest" | 读屏软件为箭头读出的文字;direction="start" 时默认为 "Scroll to the start"。 |