Slider Multiple Thresholds
Assign any number of ordered values to value and customize each thumb with its one-based indexed slot and CSS part. The shared tooltip follows the thumb being dragged, while labels remain tied to their thumb when values move.
Cool Ideal Warm
Code
The following example assumes that you have imported the component and set up the theme.
<div class="threshold-example"> <div class="threshold-heading"> <label for="comfort-thresholds">Comfort thresholds</label>
<div class="threshold-values"> <span> <i class="cool" aria-hidden="true"></i> Cool <output data-value-index="0">16 °C</output> </span> <span> <i class="ideal" aria-hidden="true"></i> Ideal <output data-value-index="1">22 °C</output> </span> <span> <i class="warm" aria-hidden="true"></i> Warm <output data-value-index="2">28 °C</output> </span> </div> </div>
<sv-slider id="comfort-thresholds" class="threshold-slider" invert-tooltip max="40" value="16 22 28"> <span class="threshold-thumb" aria-hidden="true" slot="thumb-1"></span> <span class="threshold-thumb" aria-hidden="true" slot="thumb-2"></span> <span class="threshold-thumb" aria-hidden="true" slot="thumb-3"></span>
<span aria-label="Cool limit" slot="thumb-label-1"></span> <span aria-label="Ideal temperature" slot="thumb-label-2"></span> <span aria-label="Warm limit" slot="thumb-label-3"></span>
<span aria-hidden="true" slot="tooltip"> <span data-value></span> °C </span> </sv-slider></div>
<script type="module"> /** @type {HTMLElement} */ const example = document.querySelector(".threshold-example");
/** @type {Slider} */ const slider = example.querySelector(".threshold-slider");
/** @type {NodeListOf<HTMLOutputElement>} */ const outputs = example.querySelectorAll("[data-value-index]");
const descriptions = ["lower boundary", "preferred temperature", "upper boundary"];
slider.valueLabelHandler = (value, index) => { return `${value} degrees Celsius, ${descriptions[index]}`; };
updateOutputs(); slider.addEventListener("valuechange", updateOutputs);
function updateOutputs() { const values = slider.value; if (!Array.isArray(values)) return;
for (const [index, output] of outputs.entries()) { output.value = `${values[index]} °C`; } }</script>
57 collapsed lines
<style> .threshold-example { display: grid; gap: 1.75rem; max-inline-size: 42rem; padding: clamp(1rem, 4vw, 2rem); margin: auto; background: var(--sv-gray-7); border: 1px solid var(--sv-gray-5); border-radius: var(--sv-bdr-rad-lg); }
.threshold-heading { display: grid; gap: 0.8rem;
> label { font-weight: 700; } }
.threshold-values { display: flex; flex-wrap: wrap; gap: 0.75rem 1.25rem; font-size: 0.85rem; color: var(--sv-gray-3);
span { display: inline-flex; gap: 0.4rem; align-items: center; }
i { inline-size: 0.65rem; block-size: 0.65rem; background: currentcolor; border-radius: 50%; }
output { font-weight: 700; color: var(--sv-gray-1); }
.cool { color: #3b82f6; }
.ideal { color: #22c55e; }
.warm { color: #f97316; } }
.threshold-slider { --sv-thickness: 0.8rem; --sv-thumb-size: 1.65rem; --sv-tooltip-offset: 1.5rem;
inline-size: 100%;
&::part(track) { background: linear-gradient(90deg, #3b82f6, #22c55e, #f97316); }
&:dir(rtl)::part(track) { background: linear-gradient(270deg, #3b82f6, #22c55e, #f97316); }
&::part(fill) { background: rgb(255 255 255 / 35%); }
&::part(thumb-1) { color: #3b82f6; }
&::part(thumb-2) { color: #22c55e; }
&::part(thumb-3) { color: #f97316; }
&::part(tooltip) { background: transparent; border-color: currentcolor; backdrop-filter: blur(7px); }
&::part(tooltip-arrow) { fill: currentcolor; stroke: currentcolor; }9 collapsed lines
}
.threshold-thumb { inline-size: var(--sv-thumb-size); block-size: var(--sv-thumb-size); background: currentcolor; border: 3px solid var(--sv-gray-7); border-radius: 50%; box-shadow: 0 2px 5px rgb(0 0 0 / 30%); }</style>