Range histogram slider
A price range over a live histogram of the data, lighting the bars inside the range and settling on bar edges.
pnpm dlx shadcn@latest add @uiarc/range-histogram-slider- Marketplace and search filters for price, size, or distance where the distribution guides the choice.
- Analytics filters that trim outliers from a numeric column.
- Any min and max choice where people benefit from seeing how many results fall inside.
- Use slider for a plain range without data behind it.
- Use elastic-slider or slider for a single value.
- Use number-field pairs when people type exact bounds more often than they drag.
Installation
Add Range histogram slider with the shadcn CLI, or copy the source by hand.
pnpm dlx shadcn@latest add @uiarc/range-histogram-sliderAdds the component and its local dependencies, and installs motion. First time? Add the @uiarc registry to components.json, or use the full URL:
import { RangeHistogramSlider } from "@/components/arc/range-histogram-slider/range-histogram-slider"; export function PriceFilter({ prices }: { prices: number[] }) { const [range, setRange] = useState<[number, number]>([80, 320]); return ( <RangeHistogramSlider label="Price per night" data={prices} min={0} max={500} step={5} bins={25} value={range} onValueChange={setRange} onValueCommit={range => refetchListings(range)} format={value => `$${value}`} /> );}API reference
2 parts. The first is the root.
RangeHistogramSlider
A two thumb range over a histogram of the data it filters. Bars inside the range light up, thumbs never cross, rubber-band at the ends, and settle on bar edges when released.
labelRequiredstring–Visible label. The thumbs are named from it unless thumbLabels is set.dataRequirednumber[]–Raw values the histogram counts, such as every listing's price.value[number, number]–Controlled range. Leave it out for uncontrolled use.defaultValue[number, number][min, max]Initial range when uncontrolled.onValueChange(value: [number, number]) => void–Called on every change while dragging or pressing keys.onValueCommit(value: [number, number]) => void–Called once a drag is released or a key changes the range.minnumber–Lower bound. Defaults to the smallest data value (or 0).maxnumber–Upper bound. Defaults to the largest data value.stepnumber1Value increment.binsnumber32How many bars the histogram draws.snapToBinsbooleantrueA released thumb near a bar edge settles on it, so the range never cuts a bar in half.minStepsBetweenThumbsnumber1Closest the two thumbs may sit, in steps.format(value: number) => string–Formats the readout and aria-valuetext.thumbLabels[string, string]–Accessible names for the two thumbs. Defaults to "<label>, minimum" and "<label>, maximum".namestring–Submits the range with a form, one hidden input per thumb.disabledbooleanfalseBlocks input and removes the thumbs from the tab order.classNamestring–Extra class on the root.histogram
Helper that counts values into equal bars between min and max. The last bar keeps max itself.
(data, min, max, bins)(number[], number, number, number) => number[]–Returns one count per bar.- Tab
- Moves between the minimum and maximum thumbs.
- ArrowRightorArrowUp
- Increases the focused thumb by one step.
- ArrowLeftorArrowDown
- Decreases the focused thumb by one step.
- Shift+ArroworPageUporPageDown
- Moves the focused thumb to the next bar edge in that direction.
- HomeorEnd
- Moves the focused thumb to its lowest or highest allowed value.
- Each thumb is role="slider" with its own name, aria-valuetext, and aria-valuemin/max that reflect the other thumb, so the pair never reads as crossing.
- The histogram and the readout are aria-hidden; the thumbs carry the values.
- Pass thumbLabels in the product's language when the defaults do not fit.
- Lit bars and the track fill are clipped by one path, so both cut exactly at each thumb on the same frame.
- Thumbs follow the pointer 1:1, rubber-band a few pixels past their limit, and settle with the release velocity; momentum can carry them at most one bar.
- Pressing the histogram or track springs the nearest thumb to that spot.
- Reduced motion removes the stretch and springs; thumbs jump to their values.
- Chart and track fill the container width; bars shrink with it, so lower bins on narrow screens.
- Touch drags use pointer capture; thumbs keep a large hit area.
- The readout sits on the label row and uses tabular numbers.
- Histogram counts are computed once per data, min, max, and bins change.
- Thumbs and clipping are motion values, so dragging does not re-render the bars.
- Bars render twice (base and lit copy); keep bins under about 60.
Notes for AI
Give your coding assistant the Markdown reference instead of screenshots.
- Choose it for price, size, or duration filters where showing the data distribution helps people pick a sensible range.
- Pass the unfiltered values as data and filter your list on onValueCommit to avoid refetching on every frame.
- Keep data to the values the filter applies to; histogram counts are memoized on data, min, max, and bins.
- When the two thumbs sit together, the first drag direction decides which one moves.
The full library index for assistants is at /llms.txt.