Usage
Slider lets people select a numeric value from a range along a track by dragging the handle, clicking the track, or using the keyboard. Use defaultValue for uncontrolled usage; the component owns its value from then on and only notifies changes.
Value: 30
import { useState } from 'react';
import { Slider } from '@udixio/ui-react';
export default function SliderBasicReact() {
const [value, setValue] = useState(30);
return (
<div className="flex w-72 flex-col gap-4">
<Slider
name="volume"
defaultValue={30}
step={10}
onChange={setValue}
aria-label="Volume"
/>
<p className="text-body-medium">Value: {value}</p>
</div>
);
}Value: 30
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Slider } from '@udixio/ui-angular';
@Component({
selector: 'slider-basic-angular-example',
standalone: true,
imports: [Slider],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex w-72 flex-col gap-4">
<udx-slider
name="volume"
[defaultValue]="30"
[step]="10"
(valueChange)="value = $event"
aria-label="Volume"
/>
<p class="text-body-medium">Value: {{ value }}</p>
</div>
`,
})
export class SliderBasicAngular {
protected value = 30;
}Value: 30
<script lang="ts">
import { Slider } from '@udixio/ui-svelte';
let value = $state(30);
</script>
<div class="flex w-72 flex-col gap-4">
<Slider
name="volume"
defaultValue={30}
step={10}
onChange={(next) => (value = next)}
aria-label="Volume"
/>
<p class="text-body-medium">Value: {value}</p>
</div>Controlled usage
Use value with onChange in React, [(value)] in Angular, or bind:value in Svelte. A controlled Slider requests a transition but does not change until its owner supplies the new value. Choose one mode (controlled or uncontrolled) for the component’s lifetime.
Value: 50
import { useState } from 'react';
import { Slider } from '@udixio/ui-react';
export default function SliderControlledReact() {
const [value, setValue] = useState(50);
return (
<div className="flex w-72 flex-col gap-4">
<Slider
name="brightness"
value={value}
step={10}
onChange={setValue}
aria-label="Brightness"
/>
<p className="text-body-medium">Value: {value}</p>
</div>
);
}Value: 50
import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Slider } from '@udixio/ui-angular';
@Component({
selector: 'slider-controlled-angular-example',
standalone: true,
imports: [Slider],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="flex w-72 flex-col gap-4">
<udx-slider
name="brightness"
[(value)]="value"
[step]="10"
aria-label="Brightness"
/>
<p class="text-body-medium">Value: {{ value }}</p>
</div>
`,
})
export class SliderControlledAngular {
protected value = 50;
}Value: 50
<script lang="ts">
import { Slider } from '@udixio/ui-svelte';
let value = $state(50);
</script>
<div class="flex w-72 flex-col gap-4">
<Slider
name="brightness"
bind:value
step={10}
aria-label="Brightness"
/>
<p class="text-body-medium">Value: {value}</p>
</div>Marks
Provide marks to snap to labeled positions instead of a fixed increment; omitting step alongside marks uses the marks as the only valid stops. When both are provided, step wins and marks are shown for reference only. With neither, the slider defaults to a step of 10.
import { Slider } from '@udixio/ui-react';
const marks = [
{ value: 0, label: '0' },
{ value: 25, label: '25' },
{ value: 50, label: '50' },
{ value: 75, label: '75' },
{ value: 100, label: '100' },
];
export default function SliderMarksReact() {
return (
<div className="w-72">
<Slider name="percent" defaultValue={50} marks={marks} aria-label="Percent" />
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Slider } from '@udixio/ui-angular';
const marks = [
{ value: 0, label: '0' },
{ value: 25, label: '25' },
{ value: 50, label: '50' },
{ value: 75, label: '75' },
{ value: 100, label: '100' },
];
@Component({
selector: 'slider-marks-angular-example',
standalone: true,
imports: [Slider],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="w-72">
<udx-slider
name="percent"
[defaultValue]="50"
[marks]="marks"
aria-label="Percent"
/>
</div>
`,
})
export class SliderMarksAngular {
protected readonly marks = marks;
}<script lang="ts">
import { Slider } from '@udixio/ui-svelte';
const marks = [
{ value: 0, label: '0' },
{ value: 25, label: '25' },
{ value: 50, label: '50' },
{ value: 75, label: '75' },
{ value: 100, label: '100' },
];
</script>
<div class="w-72">
<Slider name="percent" defaultValue={50} {marks} aria-label="Percent" />
</div>Open-ended range
min/max accept -Infinity/Infinity for an open-ended range. Pair the open end with a matching marks entry (also -Infinity/Infinity) so it has a label and a reachable position; the nearest finite marks resolve the interpolation range under the hood.
import { Slider } from '@udixio/ui-react';
const marks = [
{ value: -Infinity, label: 'Min' },
{ value: 0, label: '0' },
{ value: 100, label: '100' },
{ value: Infinity, label: 'Max' },
];
export default function SliderOpenEndedReact() {
return (
<div className="w-72">
<Slider
name="range"
defaultValue={0}
min={-Infinity}
max={Infinity}
marks={marks}
aria-label="Open-ended range"
/>
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Slider } from '@udixio/ui-angular';
const marks = [
{ value: -Infinity, label: 'Min' },
{ value: 0, label: '0' },
{ value: 100, label: '100' },
{ value: Infinity, label: 'Max' },
];
@Component({
selector: 'slider-open-ended-angular-example',
standalone: true,
imports: [Slider],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="w-72">
<udx-slider
name="range"
[defaultValue]="0"
[min]="minValue"
[max]="maxValue"
[marks]="marks"
aria-label="Open-ended range"
/>
</div>
`,
})
export class SliderOpenEndedAngular {
protected readonly marks = marks;
protected readonly minValue = -Infinity;
protected readonly maxValue = Infinity;
}<script lang="ts">
import { Slider } from '@udixio/ui-svelte';
const marks = [
{ value: -Infinity, label: 'Min' },
{ value: 0, label: '0' },
{ value: 100, label: '100' },
{ value: Infinity, label: 'Max' },
];
</script>
<div class="w-72">
<Slider
name="range"
defaultValue={0}
min={-Infinity}
max={Infinity}
{marks}
aria-label="Open-ended range"
/>
</div>Disabled
disabled prevents interaction, removes the slider from the tab order, and excludes its value from form submission.
import { Slider } from '@udixio/ui-react';
export default function SliderDisabledReact() {
return (
<div className="w-72">
<Slider
name="volume"
defaultValue={40}
step={10}
disabled
aria-label="Volume (disabled)"
/>
</div>
);
}import { ChangeDetectionStrategy, Component } from '@angular/core';
import { Slider } from '@udixio/ui-angular';
@Component({
selector: 'slider-disabled-angular-example',
standalone: true,
imports: [Slider],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="w-72">
<udx-slider
name="volume"
[defaultValue]="40"
[step]="10"
[disabled]="true"
aria-label="Volume (disabled)"
/>
</div>
`,
})
export class SliderDisabledAngular {}<script lang="ts">
import { Slider } from '@udixio/ui-svelte';
</script>
<div class="w-72">
<Slider
name="volume"
defaultValue={40}
step={10}
disabled
aria-label="Volume (disabled)"
/>
</div>Accessibility
The track renders role="slider" with aria-valuemin/aria-valuemax (omitted on an open end) and aria-valuenow/aria-valuetext. It is focusable and responds to ArrowLeft/ArrowRight/ArrowUp/ArrowDown (one step, or one mark when using marks without step) and Home/End (jump to the bounds). disabled sets aria-disabled and removes it from the tab order. Provide aria-label or aria-labelledby; this component does not render label text.