Skip to content

Develop

<div class="tng-slider">
<div class="tng-slider-track"></div>
</div>
<div class="tng-slider">
<div class="tng-slider-labels">
<div style="--tng-slider-label-value: 0.5">50%</div>
</div>
<div class="tng-slider-bar">
<div class="tng-slider-track"></div>
<div
class="tng-slider-thumb"
style="--tng-slider-thumb-value: 0.5"
></div>
</div>
<div class="tng-slider-labels">
<div style="--tng-slider-label-value: 0">0%</div>
<div style="--tng-slider-label-value: 0.5">50%</div>
<div style="--tng-slider-label-value: 1">100%</div>
</div>
</div>
50%
0%
50%
100%
<div class="tng-slider">
<div class="tng-slider-bar">
<div class="tng-slider-track"></div>
<div
class="tng-slider-progress"
style="
--tng-slider-progress-start: 0.5;
--tng-slider-progress-end: 0.75;
"
></div>
</div>
</div>
<div class="tng-slider">
<div class="tng-slider-bar">
<div class="tng-slider-track"></div>
<div class="tng-slider-thumb"></div>
<div
class="tng-slider-thumb"
style="--tng-slider-thumb-value: 0.25"
></div>
<div
class="tng-slider-thumb"
style="--tng-slider-thumb-value: 0.5"
></div>
</div>
</div>
<div class="tng-slider">
<div class="tng-slider-bar">
<div class="tng-slider-track"></div>
<div
class="tng-slider-thumb is-active"
style="--tng-slider-thumb-value: 0.5"
></div>
</div>
</div>
<div class="tng-slider">
<div class="tng-slider-bar">
<div class="tng-slider-track"></div>
<div
class="tng-slider-thumb is-disabled"
style="--tng-slider-thumb-value: 0.5"
></div>
</div>
</div>
<div class="tng-slider">
<div class="tng-slider-track"></div>
</div>
<div class="tng-slider is-ev">
<div class="tng-slider-track"></div>
</div>
<div class="tng-slider is-range">
<div class="tng-slider-track"></div>
</div>
<div class="tng-slider is-temperature">
<div class="tng-slider-track"></div>
</div>
<div class="tng-slider">
<input style="--tng-slider-progress-value: 0.5" type="range" />
</div>

A <datalist> linked via list / id provides snap-to-step behavior on the native range input. Hide it with .sr-only since rendering is inconsistent across browsers, and use a separate .tng-slider-labels div with role="presentation" for the visual labels.

<div class="tng-slider">
<input
list="slider-options"
type="range"
min="0"
max="100"
step="25"
/>
<datalist class="sr-only" id="slider-options">
<option value="0"></option>
<option value="25"></option>
<option value="50"></option>
<option value="75"></option>
<option value="100"></option>
</datalist>
<div class="tng-slider-labels" role="presentation">
<div style="--tng-slider-label-value: 0">0%</div>
<div style="--tng-slider-label-value: 0.25">25%</div>
<div style="--tng-slider-label-value: 0.5">50%</div>
<div style="--tng-slider-label-value: 0.75">75%</div>
<div style="--tng-slider-label-value: 1">100%</div>
</div>
</div>
<div class="tng-slider">
<input disabled type="range" />
</div>

Import the Slider component from @tmedxp/react-components. For cases where you don’t need the built-in labels, use BasicSlider instead.

Prop Type Description Required
bottomLabels [string, string, string] Three scale labels displayed below the track.
defaultValue number Initial value of the slider.
value number Controlled value of the slider.
min number Minimum value.
max number Maximum value.
step number Step increment.
steps number[] Discrete snap values (alternative to step).
disabled boolean Disables the slider.
theme 'default' | 'ev' | 'temperature' Visual theme variant.
ariaLabel string Accessible label for the thumb.
ariaLabelledby string ID of the element labelling the slider.
showProgress boolean Show the progress fill on the track.
formatValueText (value: number) => string Formats aria-valuetext for assistive technologies.
onChange (value: number) => void Callback when the value changes.
Prop Type Description Required
ariaLabels [string, string] Accessible labels for each thumb.
topLabels [string, string, string] Three scale labels displayed above the track.
defaultValue [number, number] Initial values for both thumbs.
value [number, number] Controlled values for both thumbs.
min number Minimum value.
max number Maximum value.
step number Step increment.
steps number[] Discrete snap values (alternative to step).
disabled boolean Disables the slider.
theme 'default' | 'ev' | 'temperature' Visual theme variant.
topIcons [SliderIcon?, SliderIcon?, SliderIcon?] Icons displayed alongside top labels.
showProgress boolean Show the progress fill on the track.
formatValueText (value: number) => string Formats aria-valuetext for assistive technologies.
onChange (value: [number, number]) => void Callback when either value changes.
import { Slider } from '@tmedxp/react-components';
const SliderExample = () => {
return (
<Slider
defaultValue={50}
ariaLabel="Percentage"
formatValueText={(value) => `${value}%`}
bottomLabels={['0%', '50%', '100%']}
/>
);
};
import { Slider } from '@tmedxp/react-components';
const ProgressSlider = () => {
return (
<Slider
defaultValue={60}
showProgress
ariaLabel="Percentage"
formatValueText={(value) => `${value}%`}
bottomLabels={['0%', '50%', '100%']}
/>
);
};
import { Slider } from '@tmedxp/react-components';
const EvSlider = () => {
return (
<Slider
defaultValue={80}
theme="ev"
ariaLabel="Battery charge level"
formatValueText={(value) => `${value}%`}
bottomLabels={['0%', '50%', '100%']}
/>
);
};
import { Slider } from '@tmedxp/react-components';
const TemperatureSlider = () => {
return (
<Slider
defaultValue={18}
min={-20}
max={30}
theme="temperature"
ariaLabel="Temperature"
formatValueText={(value) => `${value}°C`}
bottomLabels={['-20°C', '5°C', '30°C']}
/>
);
};
import { Slider } from '@tmedxp/react-components';
const SteppedSlider = () => {
return (
<Slider
defaultValue={50}
steps={[0, 25, 50, 75, 100]}
ariaLabel="Quality"
formatValueText={(value) => `${value}%`}
bottomLabels={['Low', 'Mid', 'High']}
/>
);
};
import { Slider } from '@tmedxp/react-components';
const DisabledSlider = () => {
return (
<Slider
defaultValue={40}
disabled
ariaLabel="Percentage"
formatValueText={(value) => `${value}%`}
bottomLabels={['0%', '50%', '100%']}
/>
);
};
import { Slider } from '@tmedxp/react-components';
const RangeSliderExample = () => {
return (
<Slider
defaultValue={[25, 75]}
ariaLabels={['Minimum', 'Maximum']}
topLabels={['Low', 'Mid', 'High']}
/>
);
};
import { Slider } from '@tmedxp/react-components';
const RangeSliderWithIcons = () => {
return (
<Slider
defaultValue={[25, 75]}
ariaLabels={['Minimum', 'Maximum']}
topLabels={['Low', 'Mid', 'High']}
topIcons={['highway', 'tree', 'check']}
/>
);
};
import { Slider } from '@tmedxp/react-components';
const TemperatureRangeSlider = () => {
return (
<Slider
defaultValue={[-5, 20]}
min={-20}
max={30}
theme="temperature"
ariaLabels={['Minimum temperature', 'Maximum temperature']}
formatValueText={(value) => `${value}°C`}
topLabels={['Cold', 'Mild', 'Hot']}
/>
);
};
import { useState } from 'react';
import { Slider } from '@tmedxp/react-components';
const ControlledSlider = () => {
const [value, setValue] = useState(50);
return (
<>
<Slider
value={value}
onChange={setValue}
ariaLabel="Volume"
formatValueText={(v) => `${v}%`}
bottomLabels={['Mute', '50%', 'Max']}
/>
<p>Current value: {value}%</p>
</>
);
};