Image Compare
godui/image-compareFreeComponent
A draggable before/after slider with clip-path reveal, keyboard support, and a pulsing handle hint.
Install it
npx shadcn@latest add https://godui.design/r/image-compare.jsonSource
1"use client";23import * as React from "react";45export type ImageCompareProps = Omit<6 React.HTMLAttributes<HTMLDivElement>,7 "onChange"8> & {9 /** Content revealed on the left / top (the "before" state). */10 before: React.ReactNode;11 /** Content underneath, revealed as the handle moves (the "after" state). */12 after: React.ReactNode;13 /** Starting handle position, 0–100. */14 initial?: number;15 orientation?: "horizontal" | "vertical";16 beforeLabel?: string;17 afterLabel?: string;18 onChange?: (position: number) => void;19};2021const clamp = (n: number) => Math.min(100, Math.max(0, n));2223const ImageCompare = React.forwardRef<HTMLDivElement, ImageCompareProps>(24 (25 {26 before,27 after,28 initial = 50,29 orientation = "horizontal",30 beforeLabel,31 afterLabel,32 onChange,33 className,34 ...props35 },36 ref,37 ) => {38 const containerRef = React.useRef<HTMLDivElement>(null);39 React.useImperativeHandle(40 ref,41 () => containerRef.current as HTMLDivElement,42 );43 const [pos, setPos] = React.useState(clamp(initial));44 const [dragging, setDragging] = React.useState(false);45 const horizontal = orientation === "horizontal";4647 const updateFromPointer = React.useCallback(48 (clientX: number, clientY: number) => {49 const el = containerRef.current;50 if (!el) return;51 const rect = el.getBoundingClientRect();52 const next = horizontal53 ? ((clientX - rect.left) / rect.width) * 10054 : ((clientY - rect.top) / rect.height) * 100;55 const clamped = clamp(next);56 setPos(clamped);57 onChange?.(clamped);58 },59 [horizontal, onChange],60 );6162 const handlePointerDown = (e: React.PointerEvent) => {63 e.currentTarget.setPointerCapture(e.pointerId);64 setDragging(true);65 updateFromPointer(e.clientX, e.clientY);66 };67 const handlePointerMove = (e: React.PointerEvent) => {68 if (!dragging) return;69 updateFromPointer(e.clientX, e.clientY);70 };71 const stop = () => setDragging(false);7273 const handleKeyDown = (e: React.KeyboardEvent) => {74 const step = e.shiftKey ? 10 : 2;75 const dec = horizontal ? "ArrowLeft" : "ArrowUp";76 const inc = horizontal ? "ArrowRight" : "ArrowDown";77 if (e.key === dec) {78 e.preventDefault();79 setPos((p) => {80 const n = clamp(p - step);81 onChange?.(n);82 return n;83 });84 } else if (e.key === inc) {85// … truncated
What it pulls in
Other registry items
Files it writes
More from godui
All 105 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | godui | Components | Free | 1 dep | |
| Agent Flowagent-flow | godui | Components | Free | 1 dep | |
| Agent Timelineagent-timeline | godui | Components | Free | 1 dep | |
| Animated Beamanimated-beam | godui | Components | Free | 1 dep | |
| Animated Testimonialsanimated-testimonials | godui | Components | Free | 1 dep | |
| Animated Tooltipanimated-tooltip | godui | Components | Free | 1 dep | |
| App Showcaseapp-showcase | godui | Components | Free | 1 dep | |
| Aurora Textaurora-text | godui | Components | Free | no deps |
