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

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

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

Carousel

จาก shadcn

แถบเลื่อนดูการ์ดหรือรายการแบบมีปุ่มควบคุมทิศทาง รองรับแนวนอนและแนวตั้ง เหมาะกับคำขอกู้ล่าสุดหรือแกลเลอรีเอกสาร

คำขอ ก-2542
ผู้ยื่น: น้ำใจ
วงเงิน 150,000 บาท
คำขอ ก-2543
ผู้ยื่น: ปี่
วงเงิน 200,000 บาท
คำขอ ก-2544
ผู้ยื่น: กู้
วงเงิน 80,000 บาท
คำขอ ก-2545
ผู้ยื่น: ปี่น้อย
วงเงิน 50,000 บาท

ติดตั้ง

Terminal
pnpm dlx shadcn@latest add @whereui/carousel

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

การใช้งาน

import {  Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious,} from "@/components/ui/carousel"<Carousel>  <CarouselContent>    <CarouselItem>รายการที่ 1</CarouselItem>    <CarouselItem>รายการที่ 2</CarouselItem>  </CarouselContent>  <CarouselPrevious />  <CarouselNext /></Carousel>

ตัวอย่างเพิ่มเติม

แนวตั้ง
1ยื่นคำขอที่สำนักงาน
2ตรวจเอกสารโดย กู้
3อนุมัติโดย น้ำใจ
4โอนเงินเข้าบัญชี

ข้อควรรู้

  • คุมความกว้างรายการด้วย class basis ที่ CarouselItem เช่น basis-3/4 หรือ basis-full
  • ปุ่มลูกศรซ่อนอัตโนมัติเมื่อเลื่อนถึงปลาย และใช้คีย์บอร์ดลูกศรได้

ซอร์สโค้ด

components/ui/carousel.tsx
"use client"import * as React from "react"import { cn } from "cn"import useEmblaCarousel, {  type UseEmblaCarouselType,} from "embla-carousel-react"import { Button } from "@/components/ui/button"import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react"type CarouselApi = UseEmblaCarouselType[1]type UseCarouselParameters = Parameters<typeof useEmblaCarousel>type CarouselOptions = UseCarouselParameters[0]type CarouselPlugin = UseCarouselParameters[1]type CarouselProps = {  opts?: CarouselOptions  plugins?: CarouselPlugin  orientation?: "horizontal" | "vertical"  setApi?: (api: CarouselApi) => void}type CarouselContextProps = {  carouselRef: ReturnType<typeof useEmblaCarousel>[0]  api: ReturnType<typeof useEmblaCarousel>[1]  scrollPrev: () => void  scrollNext: () => void  canScrollPrev: boolean  canScrollNext: boolean} & CarouselPropsconst CarouselContext = React.createContext<CarouselContextProps | null>(null)function useCarousel() {  const context = React.useContext(CarouselContext)  if (!context) {    throw new Error("useCarousel must be used within a <Carousel />")  }  return context}function Carousel({  orientation = "horizontal",  opts,  setApi,  plugins,  className,  children,  ...props}: React.ComponentProps<"div"> & CarouselProps) {  const [carouselRef, api] = useEmblaCarousel(    {      ...opts,      axis: orientation === "horizontal" ? "x" : "y",    },    plugins  )  const [canScrollPrev, setCanScrollPrev] = React.useState(false)  const [canScrollNext, setCanScrollNext] = React.useState(false)  const onSelect = React.useCallback((api: CarouselApi) => {    if (!api) return    setCanScrollPrev(api.canScrollPrev())    setCanScrollNext(api.canScrollNext())  }, [])  const scrollPrev = React.useCallback(() => {    api?.scrollPrev()  }, [api])  const scrollNext = React.useCallback(() => {    api?.scrollNext()  }, [api])  const handleKeyDown = React.useCallback(    (event: React.KeyboardEvent<HTMLDivElement>) => {      if (event.key === "ArrowLeft") {        event.preventDefault()        scrollPrev()      } else if (event.key === "ArrowRight") {        event.preventDefault()        scrollNext()      }    },    [scrollPrev, scrollNext]  )  React.useEffect(() => {    if (!api || !setApi) return    setApi(api)  }, [api, setApi])  React.useEffect(() => {    if (!api) return    onSelect(api)    api.on("reInit", onSelect)    api.on("select", onSelect)    return () => {      api?.off("select", onSelect)    }  }, [api, onSelect])  return (    <CarouselContext.Provider      value={{        carouselRef,        api: api,        opts,        orientation:          orientation || (opts?.axis === "y" ? "vertical" : "horizontal"),        scrollPrev,        scrollNext,        canScrollPrev,        canScrollNext,      }}    >      <div        onKeyDownCapture={handleKeyDown}        className={cn("relative", className)}        role="region"        aria-roledescription="carousel"        data-slot="carousel"        {...props}      >        {children}      </div>    </CarouselContext.Provider>  )}function CarouselContent({ className, ...props }: React.ComponentProps<"div">) {  const { carouselRef, orientation } = useCarousel()  return (    <div      ref={carouselRef}      className="overflow-hidden"      data-slot="carousel-content"    >      <div        className={cn(          "flex",          orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",          className        )}        {...props}      />    </div>  )}function CarouselItem({ className, ...props }: React.ComponentProps<"div">) {  const { orientation } = useCarousel()  return (    <div      role="group"      aria-roledescription="slide"      data-slot="carousel-item"      className={cn(        "min-w-0 shrink-0 grow-0 basis-full",        orientation === "horizontal" ? "pl-4" : "pt-4",        className      )}      {...props}    />  )}function CarouselPrevious({  className,  variant = "outline",  size = "icon-sm",  ...props}: React.ComponentProps<typeof Button>) {  const { orientation, scrollPrev, canScrollPrev } = useCarousel()  return (    <Button      data-slot="carousel-previous"      variant={variant}      size={size}      className={cn(        "absolute touch-manipulation rounded-full",        orientation === "horizontal"          ? "inset-y-0 -left-12 my-auto"          : "-top-12 left-1/2 -translate-x-1/2 rotate-90",        className      )}      disabled={!canScrollPrev}      onClick={scrollPrev}      {...props}    >      <ChevronLeftIcon />      <span className="sr-only">Previous slide</span>    </Button>  )}function CarouselNext({  className,  variant = "outline",  size = "icon-sm",  ...props}: React.ComponentProps<typeof Button>) {  const { orientation, scrollNext, canScrollNext } = useCarousel()  return (    <Button      data-slot="carousel-next"      variant={variant}      size={size}      className={cn(        "absolute touch-manipulation rounded-full",        orientation === "horizontal"          ? "inset-y-0 -right-12 my-auto"          : "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",        className      )}      disabled={!canScrollNext}      onClick={scrollNext}      {...props}    >      <ChevronRightIcon />      <span className="sr-only">Next slide</span>    </Button>  )}export {  type CarouselApi,  Carousel,  CarouselContent,  CarouselItem,  CarouselPrevious,  CarouselNext,  useCarousel,}