A compact multi-range filter. One toggle summarises several numeric range
filters inline (Age / Salary / Children) and expands into a
floating panel with one slider per dimension — instead of spreading three
separate sliders across a filter bar. Each row is dual-thumb (min–max) or
single-thumb (a ≥ / ≤ threshold), configured
per-row via slot attributes.
In a filter bar
The range group drops into a .pa-filter-card__filters row
as a single control standing in for three sliders. Open it, drag, and Apply.
Emitted values
The group dispatches pa-range-group:change live and
pa-range-group:apply / :reset on the buttons.
Payload is keyed by data-key; a bound at its extent reports
null (i.e. "Any").
// interact with the filter above…
Single-thumb thresholds
Set mode="single" for a one-handle threshold.
bound="gte" reads as "value+",
bound="lte" as "≤ value".
Handle shapes
Add a handle attr to any row to restyle its handles.
Purely cosmetic (no JS), so you can mix shapes per row —
circle (default), rect, bar,
arrow, and needle.
Ticks & click-to-seek
Add ticks (major interval) and optionally
ticks_minor to draw tick marks; add is_tick_labels
to print the major values beneath. Every track is click-to-seek:
press anywhere off the handles and the nearest thumb jumps there. Add
is_snap_ticks to make the thumbs settle on the nearest tick —
drag the Level row and it snaps to 0, 10, 20…
<.range key="age" label="Age"
min={0} max={80}
ticks={20} ticks_minor={10} is_tick_labels />
Theming with --pa-range-* tokens
Every colour and key dimension is a runtime token, so a theme or a
per-instance panel_style can retint/resize a slider with no
recompile. This group overrides the fill, thumb, track thickness, and handle
size — set via panel_style (the panel reparents to
<body> when open, so tokens on the group root wouldn't
reach the sliders).
<.range_group
id="themed-filters"
panel_style="--pa-range-fill: #8b5cf6;
--pa-range-thumb-border: #8b5cf6;
--pa-range-track-height: 0.8rem;
--pa-range-thumb-size: 2rem;"
>
<:range key="budget" label="Budget"
min={0} max={5000} step={50}
value_min={1000} value_max={3500}
prefix="$" is_thousands />
</.range_group>
Markup
One :range slot per dimension. Positioning is driven in
0–100% via CSS custom properties on logical inset properties, so RTL
mirrors automatically.
<.range_group id="my-filters">
<:range key="age" label="Age"
min={18} max={80}
value_min={25} value_max={60} />
<:range key="salary" label="Salary"
min={0} max={200_000} step={5000}
value_min={40_000} value_max={200_000}
prefix="$" is_thousands />
<:range key="children" label="Children"
min={0} max={8}
mode="single" bound="gte" value={2} />
</.range_group>