Carousel
roi-ui/carouselFreeItem
A slideshow component for cycling through content.
Install it
npx shadcn@latest add https://roiui.com/r/carousel.jsonSource
1"use client";23import { useControlled } from "@base-ui/utils/useControlled";4import { createContext, useCallback, useContext, useEffect, useId, useRef, useState } from "react";5import { cn } from "@/lib/utils";6import styles from "./carousel.module.css";78type CarouselContextValue = {9 currentIndex: number;10 setCurrentIndex: (index: number) => void;11 totalItems: number;12 gap: number;13 variant: "default" | "inset";14 goToIndex: (index: number) => void;15 nextSlide: () => void;16 prevSlide: () => void;17 canGoNext: boolean;18 canGoPrev: boolean;19 viewportRef: React.RefObject<HTMLDivElement | null>;20 slidesId: string;21};2223const CarouselContext = createContext<CarouselContextValue | null>(null);2425function useCarousel() {26 const context = useContext(CarouselContext);27 if (!context) {28 throw new Error("Carousel components must be used within Carousel.Root");29 }30 return context;31}3233export type CarouselRootProps = React.ComponentProps<"div"> & {34 totalItems: number;35 gap?: number;36 index?: number;37 defaultIndex?: number;38 onIndexChange?: (index: number) => void;39 align?: "start" | "center";40 variant?: "default" | "inset";41};4243export function Root({44 children,45 totalItems,46 gap = 16,47 index: indexProp,48 defaultIndex = 0,49 onIndexChange,50 align = "start",51 variant = "default",52 className,53 ...props54}: CarouselRootProps) {55 const [currentIndex, setCurrentIndexInternal] = useControlled({56 controlled: indexProp,57 default: defaultIndex,58 name: "Carousel",59 state: "index",60 });6162 const viewportRef = useRef<HTMLDivElement>(null);63 const bleedRefFromContext = useBleedRef();64 const [insetPaddingLeft, setInsetPaddingLeft] = useState(0);65 const [insetPaddingRight, setInsetPaddingRight] = useState(0);66 const slidesId = `${useId()}-slides`;6768 const maxIndex = totalItems - 1;6970 const setCurrentIndex = useCallback(71 (index: number) => {72 setCurrentIndexInternal(index);73 onIndexChange?.(index);74 },75 [setCurrentIndexInternal, onIndexChange]76 );7778 const goToIndex = useCallback(79 (index: number) => {80 const viewport = viewportRef.current;81 if (!viewport) {82 return;83 }8485 const slides = viewport.querySelectorAll('[role="group"]');86 const targetSlide = slides[index] as HTMLElement;8788 if (targetSlide) {89 let targetScroll = targetSlide.offsetLeft;9091 if (variant === "inset" && bleedRefFromContext?.current) {92// … truncated
Files it writes
More from Roi UI
All 123 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | Roi UI | Other | Free | no deps · 2 files | |
| Accordion (Tailwind)accordion-tailwind | Roi UI | Other | Free | no deps | |
| AI Chatai-chat | Roi UI | Other | Free | no deps · 2 files | |
| AI Chat (Tailwind)ai-chat-tailwind | Roi UI | Other | Free | no deps | |
| Alertalert | Roi UI | Other | Free | 1 dep · 2 files | |
| Alert Dialogalert-dialog | Roi UI | Other | Free | no deps · 2 files | |
| Alert Dialog (Tailwind)alert-dialog-tailwind | Roi UI | Other | Free | no deps | |
| Alert (Tailwind)alert-tailwind | Roi UI | Other | Free | 1 dep |
