DocsWheel Carousel

Wheel Carousel

A cinematic, rotating-wheel picker with inertial drag and scroll controls, curved fading labels, and a crossfading image for the active item.

Installation

pnpm dlx shadcn@latest add @componentry/wheel-carousel

Dependencies: framer-motion next-themes clsx tailwind-merge

Usage

API Reference

PropTypeDefault
itemsWheelCarouselItem[]

Your own option names and photos. Each entry takes a label and an image URL, plus an optional imageAlt.

Built-in demo set
mode"system" | "light" | "dark" | "custom"

Use automatic, fixed, or custom color behavior.

"system"
photoSide"left" | "right"

Side of the wheel used for the active image.

"left"
photoWidthnumber

Image column width as a percentage.

24
photoAspect"3/4" | "1/1" | "4/3" | "3/2"

Aspect ratio of the active image.

"3/4"
photoRadiusnumber

Corner radius of the active image in pixels.

14
contentWidthnumber

Maximum inner content width in pixels.

900
gapnumber

Space between the image column and the wheel in pixels.

0
radiusnumber

Radius of the label wheel in pixels.

320
spacingnumber

Angular spacing between labels in degrees.

14
visibleItemsnumber

Number of labels visible on either side of the selection.

7
apexInsetnumber

Horizontal position of the wheel's selection point.

34
snapboolean

Settles the wheel on the nearest whole item.

true
momentumboolean

Preserves drag and wheel velocity after input ends.

true
appearboolean

Plays an entrance animation on mount.

true
crossfadeDurationnumber

Duration in seconds of the active image crossfade.

0.5
scrollSpeednumber

Rotation per wheel delta pixel.

0.008
dragSpeednumber

Rotation per pointer pixel dragged.

0.02
backgroundstring

Canvas color in "custom" mode.

"rgb(255, 246, 236)"
panelColorstring

Image placeholder color in "custom" mode. Defaults to background.

—
textColorstring

Inactive label color in "custom" mode.

"rgba(180, 90, 20, 0.45)"
selectedColorstring

Active label color in "custom" mode.

"rgb(180, 84, 30)"
showMarkerboolean

Shows the dot marking the selection point.

true
markerColorstring

Selection dot color in "custom" mode.

"rgb(232, 121, 46)"
markerSizenumber

Selection dot diameter in pixels.

16
markerGapnumber

Distance between the selection dot and the labels.

20
edgeFadeboolean

Fades labels at the top and bottom edges.

true
edgeFadeSizenumber

Size of the edge fade as a percentage.

30
activeIndexnumber

Controlled active item index.

—
initialIndexnumber

Initially selected item in uncontrolled usage.

0
onActiveChange(item: WheelCarouselItem, index: number) => void

Runs whenever the active item changes.

—
classNamestring

Additional classes for the outer carousel.

—
photoClassNamestring

Additional classes for the active image frame.

—
itemClassNamestring

Additional classes for each wheel label.

—

Keep in mind

This component is inspired by various open-source projects and patterns. Please verify licenses and implementation details before using in production.

Need a custom component?

I build bespoke UI components & websites tailored to your brand.

DM me on X
PreviousSticky Scroll CardsNextAnimated Gradient
Halcyon Fields
Halcyon Fields
Meridian House
Norlight Pavilion
Aperture Studio
Solene Tower
Verdant Mile
Cobalt Works
Lumen Atrium
Palladium Hall
Cirrus Offices
Bramble Cottage
Vellum Library
Halden Bridge
Ember & Ash
Slate Meridian
Halcyon Fields, item 1 of 24
import {
  WheelCarousel,
  type WheelCarouselItem,
} from "@/components/ui/wheel-carousel"
 
const projects: WheelCarouselItem[] = [
  {
    label: "Canyon House",
    image: "/images/projects/canyon-house.jpg",
    imageAlt: "Modern concrete home built into a desert canyon",
  },
  {
    label: "Harbor Loft",
    image: "/images/projects/harbor-loft.jpg",
    imageAlt: "Bright coastal loft with large windows",
  },
  {
    label: "Glass Pavilion",
    image: "/images/projects/glass-pavilion.jpg",
    imageAlt: "Minimal glass pavilion surrounded by trees",
  },
]
 
<div className="h-[680px] w-full">
  <WheelCarousel items={projects} />
</div>