Slider
A slider allows a user to select one or more values within a range.
Import
import { AvSliderImports } from '@avesra/angular';Usage
import { Component } from '@angular/core';
import {
AvLabelComponent,
AvSliderImports,
} from '@avesra/angular';
@Component({
selector: 'app-slider-basic-demo',
imports: [
AvSliderImports,
AvLabelComponent,
],
host: { class: 'flex w-full items-center flex-col gap-3' },
template: `<div class="w-full max-w-xs" av-slider [default-value]="30">
<label av-label>Volume</label>
<span av-slider-output></span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb></div>
</div>
</div>`,
})
export class SliderBasicDemo {}Anatomy
Import the Slider parts and compose them with attribute selectors on <div>, <span>, and <label> hosts. Pair with shared av-label for accessible labeling.
<div av-slider [default-value]="30">
<label av-label>Volume</label>
<span av-slider-output></span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb></div>
</div>
</div>Range Slider Anatomy
For a dual-thumb range, pass a number array to default-value or [(value)], and add a second av-slider-thumb with [index]="1".
<div av-slider [default-value]="[25, 75]">
<label av-label>Range</label>
<span av-slider-output></span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb [index]="0"></div>
<div av-slider-thumb [index]="1"></div>
</div>
</div>Disabled
Set the disabled attribute to prevent interaction and apply disabled styling.
import { Component } from '@angular/core';
import {
AvLabelComponent,
AvSliderImports,
} from '@avesra/angular';
@Component({
selector: 'app-slider-disabled-demo',
imports: [
AvSliderImports,
AvLabelComponent,
],
host: { class: 'flex w-full items-center flex-col gap-3' },
template: `<div class="w-full max-w-xs" av-slider disabled [default-value]="30">
<label av-label>Volume</label>
<span av-slider-output></span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb></div>
</div>
</div>`,
})
export class SliderDisabledDemo {}Vertical
Set orientation="vertical" for a vertical track layout.
import { Component } from '@angular/core';
import {
AvLabelComponent,
AvSliderImports,
} from '@avesra/angular';
@Component({
selector: 'app-slider-vertical-demo',
imports: [
AvSliderImports,
AvLabelComponent,
],
host: { class: 'flex w-full items-center flex-col gap-3' },
template: `<div class="flex h-64 items-center justify-center">
<div class="h-full" av-slider orientation="vertical" [default-value]="30" aria-label="Volume">
<label av-label>Volume</label>
<span av-slider-output></span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb></div>
</div>
</div>
</div>`,
})
export class SliderVerticalDemo {}Range
Provide two av-slider-thumb elements with [index]="0" and [index]="1", and bind a number array for the value.
import { Component } from '@angular/core';
import {
AvLabelComponent,
AvSliderImports,
} from '@avesra/angular';
@Component({
selector: 'app-slider-range-demo',
imports: [
AvSliderImports,
AvLabelComponent,
],
host: { class: 'flex w-full items-center flex-col gap-3' },
template: `<div
class="w-full max-w-xs"
av-slider
[default-value]="[100, 500]"
[format-options]="{ style: 'currency', currency: 'USD' }"
[max]="1000"
[min]="0"
[step]="50"
>
<label av-label>Price Range</label>
<span av-slider-output></span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb [index]="0"></div>
<div av-slider-thumb [index]="1"></div>
</div>
</div>`,
})
export class SliderRangeDemo {}Controlled
Drive the value from the parent with [(value)] two-way binding.
Current value: 25
import { Component, signal } from '@angular/core';
import {
AvLabelComponent,
AvSliderImports,
} from '@avesra/angular';
@Component({
selector: 'app-slider-controlled-demo',
imports: [
AvSliderImports,
AvLabelComponent,
],
host: { class: 'flex w-full items-center flex-col gap-3' },
template: `<div class="flex w-full max-w-xs flex-col gap-3">
<div av-slider [(value)]="volume">
<label av-label>Volume</label>
<span av-slider-output></span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb></div>
</div>
</div>
<p class="text-sm text-muted">Current value: {{ volume() }}</p>
</div>`,
})
export class SliderControlledDemo {
readonly volume = signal(25);
}Custom Value Formatting
Pass format-options ( Intl.NumberFormatOptions) to format the output label — for example currency.
import { Component } from '@angular/core';
import {
AvLabelComponent,
AvSliderImports,
} from '@avesra/angular';
@Component({
selector: 'app-slider-custom-formatting-demo',
imports: [
AvSliderImports,
AvLabelComponent,
],
host: { class: 'flex w-full items-center flex-col gap-3' },
template: `<div
class="w-full max-w-xs"
av-slider
[default-value]="60"
[format-options]="{ style: 'currency', currency: 'USD' }"
>
<label av-label>Price</label>
<span av-slider-output></span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb></div>
</div>
</div>`,
})
export class SliderCustomFormattingDemo {}Custom Output Display
Project custom content into av-slider-output to replace the default formatted value display.
import { Component, computed, signal } from '@angular/core';
import {
AvLabelComponent,
AvSliderImports,
} from '@avesra/angular';
@Component({
selector: 'app-slider-custom-output-demo',
imports: [
AvSliderImports,
AvLabelComponent,
],
host: { class: 'flex w-full items-center flex-col gap-3' },
template: `<div class="w-full max-w-xs" av-slider [(value)]="range">
<label av-label>Range</label>
<span av-slider-output>{{ outputLabel() }}</span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb [index]="0"></div>
<div av-slider-thumb [index]="1"></div>
</div>
</div>`,
})
export class SliderCustomOutputDemo {
readonly range = signal<number[]>([25, 75]);
readonly outputLabel = computed(() => {
const [start, end] = this.range();
return `${start}% – ${end}%`;
});
}Reactive form
Integrate with Angular reactive forms using formControlName or [formControl] on div[av-slider].
import { Component } from '@angular/core';
import { JsonPipe } from '@angular/common';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import {
AvLabelComponent,
AvSliderImports,
} from '@avesra/angular';
@Component({
selector: 'app-slider-reactive-form-demo',
imports: [
JsonPipe,
ReactiveFormsModule,
AvSliderImports,
AvLabelComponent,
],
host: { class: 'flex w-full items-center flex-col gap-3' },
template: `<form class="flex w-full max-w-xs flex-col gap-3" [formGroup]="settingsForm">
<div av-slider formControlName="brightness">
<label av-label>Brightness</label>
<span av-slider-output></span>
<div av-slider-track>
<div av-slider-fill></div>
<div av-slider-thumb></div>
</div>
</div>
<p class="text-sm text-muted">Form value: {{ settingsForm.value | json }}</p>
</form>`,
})
export class SliderReactiveFormDemo {
readonly settingsForm = new FormGroup({
brightness: new FormControl(65),
});
}Styling
Passing Tailwind CSS classes
Pass utility classes on individual Slider parts — for example av-slider-track, av-slider-fill, and av-slider-thumb.
import { Component } from '@angular/core';
import {
AvLabelComponent,
AvSliderImports,
} from '@avesra/angular';
@Component({
selector: 'app-slider-custom-styling-demo',
imports: [
AvSliderImports,
AvLabelComponent,
],
host: { class: 'flex w-full items-center flex-col gap-3' },
template: `<div class="w-full max-w-xs" av-slider [default-value]="40">
<label av-label>Volume</label>
<span av-slider-output class="text-muted text-sm"></span>
<div av-slider-track class="!bg-surface-secondary">
<div av-slider-fill class="!bg-accent"></div>
<div av-slider-thumb></div>
</div>
</div>`,
})
export class SliderCustomStylingDemo {}Customizing the component classes
To customize the Slider classes, use the @layer components directive. Learn more.
@layer components {
.av-slider {
@apply flex flex-col gap-2;
}
.av-slider__output {
@apply text-muted text-sm;
}
.av-slider__track {
@apply relative h-2 w-full rounded-full bg-surface-secondary;
}
.av-slider__fill {
@apply absolute h-full rounded-full bg-accent;
}
.av-slider__thumb {
@apply size-4 rounded-full border-2 border-background bg-accent;
}
}Avesra follows the BEM methodology so component variants and states stay reusable and easy to customize.
CSS Classes
The Slider component uses these CSS classes:
Base Classes
.av-slider— Base slider container.av-slider__output— Output element displaying current value(s).av-slider__track— Track element containing fill and thumbs.av-slider__fill— Fill element showing selected range.av-slider__thumb— Individual thumb element
Orientation Classes
.av-slider--horizontal— Horizontal orientation (default).av-slider--vertical— Vertical orientation
State Classes
.av-slider[data-disabled="true"]— Disabled slider state.av-slider[data-orientation="vertical"]— Vertical orientation.av-slider__thumb[data-dragging="true"]— Thumb being dragged.av-slider__thumb[data-focus-visible="true"]— Thumb keyboard focused.av-slider__thumb[data-disabled="true"]— Disabled thumb state.av-slider__track[data-fill-start="true"]— Fill starts at beginning.av-slider__track[data-fill-end="true"]— Fill ends at end
Interactive States
The component supports both CSS pseudo-classes and data attributes:
- Focus:
:focus-visibleor[data-focus-visible="true"]on thumb - Dragging:
[data-dragging="true"]on thumb - Disabled:
:disabled,[data-disabled="true"], or[aria-disabled="true"]on slider or thumb
Accessibility
Slider implements the ARIA slider pattern and provides:
- Full keyboard navigation support (Arrow keys, Home, End)
aria-valuenow,aria-valuemin, andaria-valuemaxon thumbs- Screen reader announcements for value changes
- Proper focus management on thumb elements
- Support for disabled states
- HTML form integration through
ControlValueAccessor(ngModel/formControlName) - Locale-aware value formatting via
format-options
Associate a visible av-label or set aria-label on div[av-slider] when no visible label is present.
API
Props for div[av-slider]. span[av-slider-output], div[av-slider-track], and div[av-slider-fill] project content / render the track and have no inputs. Compose with shared label[av-label] when a visible label is needed.
| Prop | Type | Default | Description |
|---|---|---|---|
value | number | number[] | — | The current value (controlled). Supports two-way binding with `[(value)]`. |
default-value | number | number[] | 0 | The default value (uncontrolled). Use a number array for range sliders. |
valueChange | EventEmitter<number | number[]> | — | Emits when the value changes (from `model()` two-way binding). |
min | number | 0 | The slider's minimum value. |
max | number | 100 | The slider's maximum value. |
step | number | 1 | The slider's step value. |
format-options | Intl.NumberFormatOptions | — | The display format of the value label on `av-slider-output`. |
orientation | 'horizontal' | 'vertical' | 'horizontal' | The orientation of the slider. |
disabled | boolean | false | Whether the slider is disabled. Also set by reactive forms. |
av-slider-thumb
| Prop | Type | Default | Description |
|---|---|---|---|
index | number | 0 | Index of the thumb within the slider. Use `0` and `1` for range sliders. |