Fader
nexvyn/faderFreeComponent
A mixing-console-style parameter fader where the control IS the display, with continuous and detent value grammars, elastic overdrag, and spring-animated settle.
Live preview
live · rendered by the registry
Rendered by nexvyn on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://ui.nexvyn.dev/r/fader.jsonSource
1'use client'23import { Slider as BaseSlider } from '@base-ui/react/slider'4import { type MotionValue, motion, useTransform } from 'motion/react'5import type { Ref } from 'react'6import { cn } from '@/lib/utils'7import { springs } from '@/lib/motion-tokens'8import { BAR_BOX, barCenterFor, fillEdgePx } from './geometry'9import { type UseFaderOptions, useFader } from './use-fader'10import { playHoverSound, playClickSound, playTickSound } from '@/lib/sound'1112const MARK_HIDE_RADIUS = 1013const MARK_HIDE_FADE = 61415const sizeVariants = {16 sm: {17 control: 'h-8',18 overlay: 'px-3',19 text: 'text-xs',20 bar: 'h-4',21 mark: 'size-1',22 },23 md: {24 control: 'h-10',25 overlay: 'px-3.5',26 text: 'text-sm',27 bar: 'h-5',28 mark: 'size-1',29 },30 lg: {31 control: 'h-12',32 overlay: 'px-4',33 text: 'text-sm',34 bar: 'h-6',35 mark: 'size-1.5',36 },37} as const3839const toneVariants = {40 accent: {41 fill: 'border border-muted-foreground/30 bg-muted-foreground/40 pointer-fine:group-hover/fader:bg-muted-foreground/50 group-data-dragging/control:bg-muted-foreground/55',42 bar: 'bg-muted-foreground',43 },44 neutral: {45 fill: 'border border-muted-foreground/25 bg-muted-foreground/35 pointer-fine:group-hover/fader:bg-muted-foreground/45 group-data-dragging/control:bg-muted-foreground/50',46 bar: 'bg-muted-foreground/90',47 },48} as const4950function DetentMark({51 pct,52 fill,53 trackWidth,54 className,55}: {56 pct: number57 fill: MotionValue<number>58 trackWidth: MotionValue<number>59 className: string60}) {61 const filledOpacity = useTransform(() => {62 const tw = trackWidth.get()63 if (!tw) return fill.get() >= pct ? 1 : 064 const covered = fillEdgePx(fill.get(), tw) - (pct / 100) * tw65 return Math.min(1, Math.max(0, covered / 8))66 })67 const visibility = useTransform(() => {68 const tw = trackWidth.get()69 if (!tw) {70 return Math.abs(fill.get() - pct) < 0.001 ? 0 : 171 }72 const markPx = (pct / 100) * tw73 const barCenter = barCenterFor(fillEdgePx(fill.get(), tw))74 const distance = Math.abs(markPx - barCenter)75 return Math.min(1, Math.max(0, (distance - MARK_HIDE_RADIUS) / MARK_HIDE_FADE))76 })77 return (78 <motion.span79 aria-hidden80 className={cn('-translate-x-1/2 -translate-y-1/2 absolute top-1/2', className)}81 style={{ left: `${pct}%`, opacity: visibility }}82 >83 <span className="absolute inset-0 round bg-foreground/25" />84 <motion.span85// … truncated
What it pulls in
npm packages
Files it writes
More from nexvyn
All 40 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | nexvyn | Components | Free | 1 dep | |
| Action Buttonaction-button | nexvyn | Components | Free | 3 deps · 4 files | |
| Adaptive Actionsadaptive-actions | nexvyn | Components | Free | 1 dep | |
| AI Inputai-input | nexvyn | Components | Free | 1 dep · 2 files | |
| Badgebadge | nexvyn | Components | Free | 2 deps · 2 files | |
| Bars Themebars-theme | nexvyn | Components | Free | 1 dep · 3 files | |
| Bounce Sidebarbounce-sidebar | nexvyn | Components | Free | 1 dep · 2 files | |
| Breadcrumbsbreadcrumbs | nexvyn | Components | Free | 1 dep · 2 files |
