Loom Slider
loomui/loom-sliderFreeComponent
A row of dashes where the one you are holding stands tallest, with the rise travelling the track as you drag.
Live preview
live · rendered by the registry
Rendered by loomui on their own page — this is the component running, not a screenshot of it.Install it
npx shadcn@latest add https://loomui.design/r/loom-slider.jsonSource
1"use client"23import * as React from "react"45import { cn } from "@/lib/utils"67export interface LoomSliderProps extends Omit<8 React.ComponentProps<"div">,9 "onChange" | "defaultValue"10> {11 /** The current value. Leave it out to let the slider own it. */12 value?: number13 /** Starting value when the slider owns it. */14 defaultValue?: number15 /** Called with the value the slider moved to. */16 onValueChange?: (value: number) => void17 /** Low end of the range. */18 min?: number19 /** High end of the range. */20 max?: number21 /** Smallest movement the value can make. */22 step?: number23 /** How many dashes are strung across the track. */24 tickCount?: number25 /** How many dashes either side of the value the rise reaches across. */26 reach?: number27 /** Show the value above the dash it belongs to. */28 showValue?: boolean29 /** Turns the value into the text shown above the track. */30 formatValue?: (value: number) => string31 /** Name for the slider. */32 label?: string33 /** Render at the current value, but refuse input. */34 disabled?: boolean35}3637/**38 * Dash lengths as a share of the track's height, measured from its middle. The39 * row is close to even on purpose: the rise only has to say where the value is,40 * and a dash that towers over its neighbours turns the track into a chart.41 */42const BASE_LENGTH = 3043const PEAK_LENGTH = 3644const WAVE_LENGTH = 84546const clamp = (value: number, min: number, max: number) =>47 Math.min(Math.max(value, min), max)4849/** Nearest step from `min`, so a range like 0 to 7 in 0.5s never lands off-grid. */50function snap(value: number, min: number, max: number, step: number) {51 if (step <= 0) return clamp(value, min, max)52 return clamp(min + Math.round((value - min) / step) * step, min, max)53}5455/**56 * A bell centred on the value: 1 at the dash being held, 0 once `reach` dashes57 * away. Cosine rather than linear, so the rise has no corner at either end.58 */59function bell(distance: number, reach: number) {60 if (distance >= reach) return 061 return (1 + Math.cos((distance / reach) * Math.PI)) / 262}6364interface Motion {65 /** Where the value is now, on its way to the target. */66 value: number67 /** Units per millisecond, which is how hard the wave is driven. */68 velocity: number69 /** Milliseconds the slider has been in motion, used as the wave's phase. */70 elapsed: number71}7273/**74 * Every dash is drawn from this each frame. A CSS transition restarted on every75// … truncated
What it pulls in
Other registry items
Files it writes
More from loomui
All 91 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Aurora Backdropaurora-backdrop | loomui | Components | Free | no deps | |
| Bento Gridbento-grid | loomui | Components | Free | no deps | |
| Card Stackcard-stack | loomui | Components | Free | no deps | |
| Compare Slidercompare-slider | loomui | Components | Free | no deps | |
| Confetti Buttonconfetti-button | loomui | Components | Free | no deps | |
| Count Upcount-up | loomui | Components | Free | no deps | |
| Credit Cardcredit-card | loomui | Components | Free | no deps | |
| Drawerdrawer | loomui | Components | Free | 1 dep |
