ข้ามไปเนื้อหา
WhereUI

ค้นหาในเอกสาร

ค้นหาชื่อ component หรือหน้าเอกสาร

Message Scroller

จาก shadcn

พื้นที่บทสนทนาที่เลื่อนตามข้อความใหม่อัตโนมัติ พร้อมปุ่มเลื่อนลงล่าสุดเมื่อผู้ใช้อ่านย้อนหลัง เหมาะกับห้องแชดงาน HR

น้ำ
น้ำใจ
สวัสดีครับ ต้องการยื่นคำขอกู้ครับ
ปี่
ปี่
รับทราบค่ะ กรอกแบบฟอร์มก่อนนะคะ
น้ำ
น้ำใจ
แนบสลิปเงินเดือนครบแล้วครับ
ปี่
ปี่
ตรวจเอกสารแล้ว ขาดสำเนาบัตรประชาชนอีก 1 ฉบับค่ะ
น้ำ
น้ำใจ
ส่งเพิ่มให้แล้วครับ
ปี่
ปี่
ครบแล้วค่ะ ส่งให้ผู้อนุมัติ (กู้) พิจารณา
กู้
กู้
รับเรื่องแล้ว ผลภายใน 3 วันทำการ
น้ำ
น้ำใจ
ขอบคุณครับ

ติดตั้ง

Terminal
pnpm dlx shadcn@latest add @whereui/message-scroller

ต้องผูก registry และติดตั้ง @whereui/theme นำหน้าเสมอเมื่อติดตั้งครั้งแรก

การใช้งาน

import {  MessageScroller,  MessageScrollerButton,  MessageScrollerContent,  MessageScrollerItem,  MessageScrollerProvider,  MessageScrollerViewport,} from "@/components/ui/message-scroller"<MessageScrollerProvider>  <MessageScroller>    <MessageScrollerViewport>      <MessageScrollerContent>        <MessageScrollerItem scrollAnchor>{/* ข้อความ */}</MessageScrollerItem>      </MessageScrollerContent>    </MessageScrollerViewport>    <MessageScrollerButton />  </MessageScroller></MessageScrollerProvider>

ข้อควรรู้

  • ต้องครอบด้วย MessageScrollerProvider เสมอ และกำหนด scrollAnchor ที่ข้อความรายการสุดท้ายเพื่อเลื่อนตามอัตโนมัติ
  • พื้นที่ viewport ต้องมีความสูงจำกัด (เช่น h-72) ไม่เช่นนั้นจะไม่เกิดการเลื่อน

ซอร์สโค้ด

components/ui/message-scroller.tsx
"use client"import * as React from "react"import {  MessageScroller as MessageScrollerPrimitive,  useMessageScroller,  useMessageScrollerScrollable,  useMessageScrollerVisibility,} from "@shadcn/react/message-scroller"import { cn } from "cn"import { Button } from "@/components/ui/button"import { ArrowDownIcon } from "lucide-react"function MessageScrollerProvider(  props: React.ComponentProps<typeof MessageScrollerPrimitive.Provider>) {  return <MessageScrollerPrimitive.Provider {...props} />}function MessageScroller({  className,  ...props}: React.ComponentProps<typeof MessageScrollerPrimitive.Root>) {  return (    <MessageScrollerPrimitive.Root      data-slot="message-scroller"      className={cn(        "group/message-scroller relative flex size-full min-h-0 flex-col overflow-hidden",        className      )}      {...props}    />  )}function MessageScrollerViewport({  className,  ...props}: React.ComponentProps<typeof MessageScrollerPrimitive.Viewport>) {  return (    <MessageScrollerPrimitive.Viewport      data-slot="message-scroller-viewport"      className={cn(        "size-full min-h-0 min-w-0 scroll-fade-b scrollbar-thin scrollbar-gutter-stable overflow-y-auto overscroll-contain contain-content data-autoscrolling:scrollbar-thumb-transparent data-autoscrolling:scrollbar-track-transparent data-pending-scroll:invisible",        className      )}      {...props}    />  )}function MessageScrollerContent({  className,  ...props}: React.ComponentProps<typeof MessageScrollerPrimitive.Content>) {  return (    <MessageScrollerPrimitive.Content      data-slot="message-scroller-content"      className={cn("flex h-max min-h-full flex-col gap-6", className)}      {...props}    />  )}function MessageScrollerItem({  className,  scrollAnchor = false,  ...props}: React.ComponentProps<typeof MessageScrollerPrimitive.Item>) {  return (    <MessageScrollerPrimitive.Item      data-slot="message-scroller-item"      scrollAnchor={scrollAnchor}      className={cn(        "min-w-0 shrink-0 [contain-intrinsic-size:auto_10rem] [content-visibility:auto]",        className      )}      {...props}    />  )}function MessageScrollerButton({  direction = "end",  className,  children,  render,  variant = "secondary",  size = "icon-sm",  ...props}: React.ComponentProps<typeof MessageScrollerPrimitive.Button> &  Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {  return (    <MessageScrollerPrimitive.Button      data-slot="message-scroller-button"      data-direction={direction}      data-variant={variant}      data-size={size}      direction={direction}      className={cn(        "absolute inset-s-1/2 -translate-x-1/2 border-border bg-background text-foreground transition-[translate,scale,opacity] duration-200 hover:bg-muted hover:text-foreground data-[active=false]:pointer-events-none data-[active=false]:scale-95 data-[active=false]:opacity-0 data-[active=false]:duration-400 data-[active=false]:ease-[cubic-bezier(0.7,0,0.84,0)] data-[active=true]:translate-y-0 data-[active=true]:scale-100 data-[active=true]:opacity-100 data-[active=true]:ease-[cubic-bezier(0.23,1,0.32,1)] data-[direction=end]:bottom-4 data-[direction=end]:data-[active=false]:translate-y-full data-[direction=start]:top-4 data-[direction=start]:data-[active=false]:-translate-y-full rtl:translate-x-1/2 data-[direction=start]:[&_svg]:rotate-180",        className      )}      render={render ?? <Button variant={variant} size={size} />}      {...props}    >      {children ?? (        <>          <ArrowDownIcon          />          <span className="sr-only">            {direction === "end" ? "Scroll to end" : "Scroll to start"}          </span>        </>      )}    </MessageScrollerPrimitive.Button>  )}export {  MessageScrollerProvider,  MessageScroller,  MessageScrollerViewport,  MessageScrollerContent,  MessageScrollerItem,  MessageScrollerButton,  useMessageScroller,  useMessageScrollerScrollable,  useMessageScrollerVisibility,}