Image Comparison
motion-primitives/image-comparisonFreeComponent
A component for comparing two images with an interactive slider.
Install it
npx shadcn@latest add https://raw.githubusercontent.com/ibelick/motion-primitives/HEAD/public/c/image-comparison.jsonSource
1'use client';2import { cn } from '@/lib/utils';3import { useState, createContext, useContext } from 'react';4import {5 motion,6 MotionValue,7 SpringOptions,8 useMotionValue,9 useSpring,10 useTransform,11} from 'motion/react';1213const ImageComparisonContext = createContext<14 | {15 sliderPosition: number;16 setSliderPosition: (pos: number) => void;17 motionSliderPosition: MotionValue<number>;18 }19 | undefined20>(undefined);2122export type ImageComparisonProps = {23 children: React.ReactNode;24 className?: string;25 enableHover?: boolean;26 springOptions?: SpringOptions;27};2829const DEFAULT_SPRING_OPTIONS = {30 bounce: 0,31 duration: 0,32};3334function ImageComparison({35 children,36 className,37 enableHover,38 springOptions,39}: ImageComparisonProps) {40 const [isDragging, setIsDragging] = useState(false);41 const motionValue = useMotionValue(50);42 const motionSliderPosition = useSpring(43 motionValue,44 springOptions ?? DEFAULT_SPRING_OPTIONS45 );46 const [sliderPosition, setSliderPosition] = useState(50);4748 const handleDrag = (event: React.MouseEvent | React.TouchEvent) => {49 if (!isDragging && !enableHover) return;5051 const containerRect = (52 event.currentTarget as HTMLElement53 ).getBoundingClientRect();54 const x =55 'touches' in event56 ? event.touches[0].clientX - containerRect.left57 : (event as React.MouseEvent).clientX - containerRect.left;5859 const percentage = Math.min(60 Math.max((x / containerRect.width) * 100, 0),61 10062 );63 motionValue.set(percentage);64 setSliderPosition(percentage);65 };6667 return (68 <ImageComparisonContext.Provider69 value={{ sliderPosition, setSliderPosition, motionSliderPosition }}70 >71 <div72 className={cn(73 'relative select-none overflow-hidden',74 enableHover && 'cursor-ew-resize',75 className76 )}77 onMouseMove={handleDrag}78 onMouseDown={() => !enableHover && setIsDragging(true)}79 onMouseUp={() => !enableHover && setIsDragging(false)}80 onMouseLeave={() => !enableHover && setIsDragging(false)}81 onTouchMove={handleDrag}82 onTouchStart={() => !enableHover && setIsDragging(true)}83 onTouchEnd={() => !enableHover && setIsDragging(false)}84 >85 {children}86 </div>87 </ImageComparisonContext.Provider>88 );89}9091const ImageComparisonImage = ({92 className,93 alt,94 src,95 position,96}: {97 className?: string;98 alt: string;99 src: string;100// … truncated
What it pulls in
npm packages
Files it writes
More from motion-primitives
All 33 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | motion-primitives | Components | Free | 1 dep | |
| Animated Backgroundanimated-background | motion-primitives | Components | Free | 1 dep | |
| Animated Groupanimated-group | motion-primitives | Components | Free | 1 dep | |
| Animated Numberanimated-number | motion-primitives | Components | Free | 1 dep | |
| Border Trailborder-trail | motion-primitives | Components | Free | 1 dep | |
| Carouselcarousel | motion-primitives | Components | Free | 1 dep | |
| Cursorcursor | motion-primitives | Components | Free | 1 dep | |
| Dialogdialog | motion-primitives | Components | Free | 1 dep · 2 files |
