Item Carousel
tool-ui/item-carouselFreeBlock
Horizontal carousel for browsing collections.
See it running
Open the demo on tool-ui
www.tool-ui.com/components/item-carouselInstall it
npx shadcn@latest add https://www.tool-ui.com/r/item-carousel.jsonSource
1"use client";23import { useRef, useState, useEffect, useCallback } from "react";4import { cn, Button, Card, ChevronLeft, ChevronRight } from "./_adapter";5import { ItemCard } from "./item-card";6import { prefersReducedMotion } from "../shared/utils";7import type { ItemCarouselProps } from "./schema";89const SCROLL_PADDING_STYLE = { scrollPaddingInline: "1rem" };1011const SCROLL_EDGE_THRESHOLD_PX = 8;12const SNAP_EPSILON_PX = 5;13const SCROLL_ANIMATION_DURATION_MS = 300;14const PAGE_SCROLL_RATIO = 0.8;15const PAGE_SCROLL_BREAKPOINT_PX = 640;1617type ScrollDirection = "left" | "right";1819interface ScrollAnimationState {20 target: number;21 start: number;22 startTime: number;23 duration: number;24 onComplete?: () => void;25}2627function useSmoothScroll() {28 const animationRef = useRef<ScrollAnimationState | null>(null);29 const frameRef = useRef<number | null>(null);3031 const cancelAnimation = useCallback(() => {32 if (frameRef.current !== null) {33 cancelAnimationFrame(frameRef.current);34 frameRef.current = null;35 }36 animationRef.current = null;37 }, []);3839 useEffect(() => cancelAnimation, [cancelAnimation]);4041 const scrollTo = useCallback(42 (43 element: HTMLElement,44 target: number,45 duration = SCROLL_ANIMATION_DURATION_MS,46 onComplete?: () => void,47 ) => {48 if (prefersReducedMotion() || duration <= 0) {49 element.scrollLeft = target;50 onComplete?.();51 return;52 }5354 cancelAnimation();5556 animationRef.current = {57 target,58 start: element.scrollLeft,59 startTime: performance.now(),60 duration,61 onComplete,62 };6364 element.style.scrollSnapType = "none";6566 const step = () => {67 const anim = animationRef.current;68 if (!anim) return;6970 const elapsed = performance.now() - anim.startTime;71 const progress = Math.min(elapsed / anim.duration, 1);72 const eased = 1 - Math.pow(1 - progress, 3);7374 element.scrollLeft = anim.start + (anim.target - anim.start) * eased;7576 if (progress < 1) {77 frameRef.current = requestAnimationFrame(step);78 return;79 }8081 element.scrollLeft = anim.target;82 const callback = anim.onComplete;83 cancelAnimation();8485 requestAnimationFrame(() => {86 element.style.scrollSnapType = "";87 callback?.();88 });89 };9091 frameRef.current = requestAnimationFrame(step);92 },93 [cancelAnimation],94 );9596// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from tool-ui
All 27 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Approval Cardapproval-card | tool-ui | Blocks | Free | 2 deps · 11 files | |
| Audioaudio | tool-ui | Blocks | Free | 2 deps · 9 files | |
| Chartchart | tool-ui | Blocks | Free | 2 deps · 8 files | |
| Citationcitation | tool-ui | Blocks | Free | 2 deps · 15 files | |
| Code Blockcode-block | tool-ui | Blocks | Free | 3 deps · 11 files | |
| Code Diffcode-diff | tool-ui | Blocks | Free | 3 deps · 10 files | |
| Data Tabledata-table | tool-ui | Blocks | Free | 1 dep · 17 files | |
| Geo Mapgeo-map | tool-ui | Blocks | Free | 4 deps · 12 files |
