Image Comparison Slider
amarjay-ui/image-comparison-sliderFreeBlock
Draggable before-and-after image comparison control.
Live preview
live · rendered by the registry
Rendered by amarjay-ui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.amarjay.com/r/image-comparison-slider.jsonSource
1"use client"23import * as React from "react"4import { GripVertical } from "lucide-react"56import { cn } from "@/lib/utils"78export type ImageComparisonSliderProps = {9 beforeImage: string10 afterImage: string11 alt: string12 position?: number13 defaultPosition?: number14 onPositionChange?: (position: number) => void15 beforeLabel?: string16 afterLabel?: string17 className?: string18}1920export function ImageComparisonSlider({21 beforeImage,22 afterImage,23 alt,24 position: positionProp,25 defaultPosition = 50,26 onPositionChange,27 beforeLabel = "Before",28 afterLabel = "After",29 className,30}: ImageComparisonSliderProps) {31 const [uncontrolledPosition, setUncontrolledPosition] = React.useState(() => clamp(defaultPosition))32 const position = clamp(positionProp ?? uncontrolledPosition)3334 const setPosition = (nextPosition: number) => {35 const next = clamp(nextPosition)36 if (positionProp === undefined) setUncontrolledPosition(next)37 onPositionChange?.(next)38 }3940 return (41 <div className={cn("group relative aspect-[3/2] w-full max-w-3xl touch-none select-none overflow-hidden rounded-xl bg-muted has-[input:focus-visible]:ring-2 has-[input:focus-visible]:ring-ring", className)}>42 <img src={afterImage} alt={alt} className="absolute inset-0 size-full object-cover" draggable={false} />43 <div className="pointer-events-none absolute inset-0 overflow-hidden" style={{ clipPath: `inset(0 ${100 - position}% 0 0)` }}>44 <img src={beforeImage} alt="" className="size-full object-cover" draggable={false} />45 </div>46 <span className="pointer-events-none absolute left-3 top-3 rounded-full bg-background/85 px-2.5 py-1 text-[0.625rem] font-medium text-foreground backdrop-blur">{beforeLabel}</span>47 <span className="pointer-events-none absolute right-3 top-3 rounded-full bg-background/85 px-2.5 py-1 text-[0.625rem] font-medium text-foreground backdrop-blur">{afterLabel}</span>48 <div aria-hidden className="pointer-events-none absolute inset-y-0 z-10 w-px bg-background" style={{ left: `${position}%` }} />49 <div aria-hidden className="pointer-events-none absolute top-1/2 z-20 grid size-9 -translate-x-1/2 -translate-y-1/2 place-items-center rounded-full border bg-background text-foreground shadow-sm" style={{ left: `${position}%` }}>50 <GripVertical className="size-4" />51 </div>52 <input53 aria-label="Adjust image comparison"54 aria-valuetext={`${position}% ${beforeLabel.toLowerCase()}`}55// … truncated
What it pulls in
npm packages
Other registry items
Files it writes
More from amarjay-ui
All 18 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Audio Playeraudio-player | amarjay-ui | Blocks | Free | 1 dep | |
| Chart Exampleschart-examples | amarjay-ui | Blocks | Free | 1 dep | |
| Settings Dialogsettings-dialog | amarjay-ui | Blocks | Free | 2 deps |
