Compare Slider
more-shadcn-noair/compare-sliderFreeComponent
A slider to compare two overlapping elements, usually images.
Live preview
live · rendered by the registry
Rendered by more-shadcn-noair on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://more-shadcn.noair.fun/r/compare-slider.jsonSource
1<script lang="ts">2 import { cn } from '$UTILS$';3 import { setCompareContext } from './ctx';4 import type { Snippet } from 'svelte';56 let {7 value = $bindable(50),8 orientation = 'horizontal',9 class: className,10 children11 }: {12 value?: number;13 orientation?: 'horizontal' | 'vertical';14 class?: string;15 children: Snippet;16 } = $props();1718 let container: HTMLDivElement | undefined = $state();19 let isDragging = $state(false);2021 function handleDown(e: PointerEvent) {22 if (e.button !== 0 && e.pointerType === 'mouse') return;2324 isDragging = true;25 updatePosition(e.clientX, e.clientY);2627 (e.target as Element).setPointerCapture(e.pointerId);28 }2930 function handleMove(e: PointerEvent) {31 if (!isDragging) return;32 updatePosition(e.clientX, e.clientY);33 }3435 function handleUp(e: PointerEvent) {36 isDragging = false;37 (e.target as Element).releasePointerCapture(e.pointerId);38 }3940 function updatePosition(clientX: number, clientY: number) {41 if (!container) return;4243 const rect = container.getBoundingClientRect();4445 if (orientation === 'horizontal') {46 const x = Math.min(Math.max(0, clientX - rect.left), rect.width);47 value = (x / rect.width) * 100;48 } else {49 const y = Math.min(Math.max(0, clientY - rect.top), rect.height);50 value = (y / rect.height) * 100;51 }52 }5354 function handleKeyDown(e: KeyboardEvent) {55 const step = e.shiftKey ? 10 : 1;56 if (e.key === 'ArrowLeft' || e.key === 'ArrowUp') {57 e.preventDefault();58 value = Math.max(0, value - step);59 } else if (e.key === 'ArrowRight' || e.key === 'ArrowDown') {60 e.preventDefault();61 value = Math.min(100, value + step);62 } else if (e.key === 'Home') {63 e.preventDefault();64 value = 0;65 } else if (e.key === 'End') {66 e.preventDefault();67 value = 100;68 }69 }7071 setCompareContext({72 position: () => value,73 orientation: () => orientation,74 isDragging: () => isDragging75 });76</script>7778<div79 bind:this={container}80 role="slider"81 aria-valuenow={value}82 aria-valuemin={0}83 aria-valuemax={100}84 tabindex="0"85 onpointerdown={handleDown}86 onpointermove={handleMove}87 onpointerup={handleUp}88 onkeydown={handleKeyDown}89 class={cn(90 'group relative select-none overflow-hidden touch-none',91 orientation === 'horizontal' ? 'cursor-ew-resize' : 'cursor-ns-resize',92 className93 )}94 style="--pos: {value}%"95>96 {@render children()}97</div>
More from more-shadcn-noair
All 43 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Audioaudio | more-shadcn-noair | Components | Free | no deps | |
| Audio Waveaudio-wave | more-shadcn-noair | Components | Free | no deps | |
| Autocompleteautocomplete | more-shadcn-noair | Components | Free | no deps | |
| Bannerbanner | more-shadcn-noair | Components | Free | no deps | |
| Big Calendarbig-calendar | more-shadcn-noair | Components | Free | no deps | |
| Bottom Navigationbottom-nav | more-shadcn-noair | Components | Free | no deps | |
| Canvascanvas | more-shadcn-noair | Components | Free | no deps | |
| Chipchip | more-shadcn-noair | Components | Free | no deps |
