Carousel
glasswave/carouselFreeComponent
Embla-powered horizontal slider with prev/next controls.
Live preview
live · rendered by the registry
Rendered by glasswave on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://glasswave.denizisik.com/r/carousel.jsonSource
1"use client";23import useEmblaCarousel, {4 type UseEmblaCarouselType,5} from "embla-carousel-react";6import { ArrowLeft, ArrowRight } from "lucide-react";7import {8 createContext,9 forwardRef,10 useCallback,11 useContext,12 useEffect,13 useState,14} from "react";15import { cn } from "@/lib/utils";16import { buttonVariants } from "@/components/ui/button";1718export type CarouselApi = UseEmblaCarouselType[1];19type CarouselOptions = NonNullable<Parameters<typeof useEmblaCarousel>[0]>;20type CarouselPlugins = NonNullable<Parameters<typeof useEmblaCarousel>[1]>;2122type CarouselContextValue = {23 carouselRef: UseEmblaCarouselType[0];24 api: CarouselApi;25 scrollPrev: () => void;26 scrollNext: () => void;27 canScrollPrev: boolean;28 canScrollNext: boolean;29};3031const CarouselCtx = createContext<CarouselContextValue | null>(null);3233export function useCarousel() {34 const ctx = useContext(CarouselCtx);35 if (!ctx) {36 throw new Error("useCarousel must be used within <Carousel>");37 }38 return ctx;39}4041export function Carousel({42 orientation = "horizontal",43 opts,44 setApi,45 plugins,46 className,47 children,48 ...props49}: React.HTMLAttributes<HTMLDivElement> & {50 opts?: CarouselOptions;51 plugins?: CarouselPlugins;52 orientation?: "horizontal" | "vertical";53 setApi?: (api: CarouselApi) => void;54}) {55 const [carouselRef, api] = useEmblaCarousel(56 { ...opts, axis: orientation === "horizontal" ? "x" : "y" },57 plugins,58 );59 const [canScrollPrev, setCanScrollPrev] = useState(false);60 const [canScrollNext, setCanScrollNext] = useState(false);6162 const onSelect = useCallback((emblaApi: CarouselApi) => {63 if (!emblaApi) return;64 setCanScrollPrev(emblaApi.canScrollPrev());65 setCanScrollNext(emblaApi.canScrollNext());66 }, []);6768 useEffect(() => {69 if (!api) return;70 setApi?.(api);71 onSelect(api);72 api.on("reInit", onSelect);73 api.on("select", onSelect);74 return () => {75 api.off("select", onSelect);76 };77 }, [api, onSelect, setApi]);7879 const scrollPrev = useCallback(() => api?.scrollPrev(), [api]);80 const scrollNext = useCallback(() => api?.scrollNext(), [api]);8182 return (83 <CarouselCtx.Provider84 value={{85 carouselRef,86 api,87 scrollPrev,88 scrollNext,89 canScrollPrev,90 canScrollNext,91 }}92 >93 <div94 className={cn("relative", className)}95 role="region"96 aria-roledescription="carousel"97 {...props}98 >99 {children}100 </div>101// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from glasswave
All 60 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | glasswave | Components | Free | 2 deps | |
| Alertalert | glasswave | Components | Free | 1 dep | |
| Alert Dialogalert-dialog | glasswave | Components | Free | 1 dep | |
| Aspect Ratioaspect-ratio | glasswave | Components | Free | 1 dep | |
| Avataravatar | glasswave | Components | Free | 1 dep | |
| Badgebadge | glasswave | Components | Free | 1 dep | |
| Breadcrumbbreadcrumb | glasswave | Components | Free | 2 deps | |
| Buttonbutton | glasswave | Components | Free | 2 deps |
