Cylinder Carousel
beui/cylinder-carouselFreeComponent
A carousel whose items line the inside of a cylinder, receding into the center and growing toward the edges. Drag, scroll or arrow-key to roll it, with a springy glide and snap. Reduced-motion drops the glide.
Install it
npx shadcn@latest add https://beui.dev/r/cylinder-carousel.jsonSource
1"use client";2// beui.dev/components/motion/cylinder-carousel34import {5 animate,6 type AnimationPlaybackControls,7 motion,8 type MotionValue,9 useMotionValue,10 useReducedMotion,11 useTransform,12} from "motion/react";13import {14 Children,15 type PointerEvent as ReactPointerEvent,16 type ReactNode,17 useCallback,18 useEffect,19 useRef,20 useState,21 type WheelEvent as ReactWheelEvent,22} from "react";23import { cn } from "@/lib/utils";2425// Carousel-specific: a soft spring that receives the release velocity, so a26// flick keeps rolling freely, drifts past the snap point and eases back.27const GLIDE_SPRING = { stiffness: 40, damping: 20, mass: 3 };2829// How far a flick keeps rolling: projected items = release velocity * momentum.30const FLICK_MOMENTUM = 0.45;31const MAX_FLICK_ITEMS = 6;3233export interface CylinderCarouselProps {34 children: ReactNode;35 /** Max item box size in px (square) at full size, i.e. at the container36 * edge. Balls shrink below this automatically so the row keeps breathing37 * room in narrow containers. */38 itemSize?: number;39 /** How many item slots span the container width. */40 visibleItems?: number;41 /** "concave" (default): inside of the cylinder — center ball smallest and42 * dipped, growing toward the edges. "convex": outside of the cylinder —43 * center ball biggest and raised, shrinking toward the edges. */44 variant?: "concave" | "convex";45 /** Scale of the smallest ball (center for concave, edges for convex);46 * the biggest reaches 1. */47 minScale?: number;48 /** Items rolled per item-width dragged — above 1 the wall outruns the49 * pointer, which reads as a lighter, freer roll. */50 dragSpeed?: number;51 /** Curve depth in px: for concave, how far the edge balls ride above the52 * center one (valley); for convex, how far below (arch). 0 = flat line.53 * Defaults to 35% of the item size. */54 arc?: number;55 /** Snap to the nearest item when the roll settles. */56 snap?: boolean;57 /** Roll on its own until interacted with. */58 autoRotate?: boolean;59 /** Auto-roll speed in items per second. */60 autoRotateSpeed?: number;61 defaultIndex?: number;62 onIndexChange?: (index: number) => void;63 /** Stage height in px. Defaults to `itemSize`. */64 height?: number;65 className?: string;66}6768// The frame edge sits at this wall angle; how far the wall curves in frame.69const THETA_EDGE = (72 * Math.PI) / 180;70// Wall angle past which a ball is parked far off-stage (always hidden there).71// … truncated
What it pulls in
npm packages
Files it writes
More from beui
All 104 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Action Swap Bluraction-swap-blur | beui | Components | Free | 3 deps · 4 files | |
| Action Swap Cascadeaction-swap-cascade | beui | Components | Free | 3 deps · 4 files | |
| Action Swap Rollaction-swap-roll | beui | Components | Free | 3 deps · 4 files | |
| Agent Activityagent-activity | beui | Components | Free | 4 deps · 9 files | |
| Agent Loading States Agent Progressagent-progress | beui | Components | Free | 3 deps · 3 files | |
| AI Sidebarai-sidebar | beui | Components | Free | 4 deps · 5 files | |
| Animated Badgeanimated-badge | beui | Components | Free | 4 deps · 3 files | |
| Number Animation Animated Numberanimated-number | beui | Components | Free | 3 deps · 3 files |
