Skip to content

Commit b5a6100

Browse files
authored
feat: implement disabled property in slider and range-slider (#10980)
1 parent 08b0cf3 commit b5a6100

13 files changed

+164
-22
lines changed

packages/slider/src/styles/vaadin-slider-base-styles.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ export const sliderStyles = css`
2525
display: none !important;
2626
}
2727
28+
:host([disabled]) {
29+
cursor: var(--vaadin-disabled-cursor);
30+
/* TODO which color should we use ? */
31+
--vaadin-slider-fill-background: color-mix(in oklab, var(--vaadin-text-color) 50%, var(--vaadin-background-color));
32+
}
33+
2834
[part='track'] {
2935
box-sizing: border-box;
3036
position: absolute;

packages/slider/src/vaadin-range-slider.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ class RangeSlider extends SliderMixin(
132132
.max="${max}"
133133
.step="${step}"
134134
.value="${startValue}"
135-
tabindex="0"
135+
.disabled="${this.disabled}"
136+
tabindex="${this.disabled ? -1 : 0}"
136137
@keydown="${this.__onKeyDown}"
137138
@input="${this.__onInput}"
138139
@change="${this.__onChange}"
@@ -145,7 +146,8 @@ class RangeSlider extends SliderMixin(
145146
.max="${max}"
146147
.step="${step}"
147148
.value="${endValue}"
148-
tabindex="0"
149+
.disabled="${this.disabled}"
150+
tabindex="${this.disabled ? -1 : 0}"
149151
@keydown="${this.__onKeyDown}"
150152
@input="${this.__onInput}"
151153
@change="${this.__onChange}"
@@ -174,6 +176,10 @@ class RangeSlider extends SliderMixin(
174176
* @override
175177
*/
176178
focus(options) {
179+
if (this.disabled) {
180+
return;
181+
}
182+
177183
if (this._inputElements) {
178184
this._inputElements[0].focus();
179185
}

packages/slider/src/vaadin-slider-mixin.d.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@
44
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
55
*/
66
import type { Constructor } from '@open-wc/dedupe-mixin';
7+
import type { DisabledMixinClass } from '@vaadin/a11y-base/src/disabled-mixin.js';
78

8-
export declare function SliderMixin<T extends Constructor<HTMLElement>>(base: T): Constructor<SliderMixinClass> & T;
9+
export declare function SliderMixin<T extends Constructor<HTMLElement>>(
10+
base: T,
11+
): Constructor<DisabledMixinClass> & Constructor<SliderMixinClass> & T;
912

1013
export declare class SliderMixinClass {
1114
/**

packages/slider/src/vaadin-slider-mixin.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
* Copyright (c) 2026 - 2026 Vaadin Ltd.
44
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
55
*/
6+
import { DisabledMixin } from '@vaadin/a11y-base/src/disabled-mixin.js';
67

78
/**
89
* @polymerMixin
10+
* @mixes DisabledMixin
911
*/
1012
export const SliderMixin = (superClass) =>
11-
class SliderMixinClass extends superClass {
13+
class SliderMixinClass extends DisabledMixin(superClass) {
1214
static get properties() {
1315
return {
1416
/**
@@ -169,10 +171,11 @@ export const SliderMixin = (superClass) =>
169171
* @private
170172
*/
171173
__onPointerDown(event) {
172-
if (event.button !== 0) {
174+
if (this.disabled || event.button !== 0) {
173175
return;
174176
}
175177

178+
// Only handle pointerdown on the thumb, track or track-fill
176179
const part = event.composedPath()[0].getAttribute('part');
177180
if (!part || (!part.startsWith('track') && !part.startsWith('thumb'))) {
178181
return;

packages/slider/src/vaadin-slider.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ class Slider extends SliderMixin(
126126
.max="${max}"
127127
.value="${value}"
128128
.step="${step}"
129-
tabindex="0"
129+
.disabled="${this.disabled}"
130+
tabindex="${this.disabled ? -1 : 0}"
130131
@input="${this.__onInput}"
131132
@change="${this.__onChange}"
132133
/>
@@ -151,6 +152,10 @@ class Slider extends SliderMixin(
151152
* @override
152153
*/
153154
focus(options) {
155+
if (this.disabled) {
156+
return;
157+
}
158+
154159
if (this._inputElement) {
155160
this._inputElement.focus();
156161
}

packages/slider/test/dom/__snapshots__/range-slider.test.snap.js

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ snapshots["vaadin-range-slider host default"] =
2828
snapshots["vaadin-range-slider host value"] =
2929
`<vaadin-range-slider>
3030
<input
31-
id="slider-2"
31+
id="slider-0"
3232
max="100"
3333
min="0"
3434
slot="input"
@@ -37,7 +37,7 @@ snapshots["vaadin-range-slider host value"] =
3737
type="range"
3838
>
3939
<input
40-
id="slider-3"
40+
id="slider-1"
4141
max="100"
4242
min="0"
4343
slot="input"
@@ -52,7 +52,7 @@ snapshots["vaadin-range-slider host value"] =
5252
snapshots["vaadin-range-slider host min"] =
5353
`<vaadin-range-slider>
5454
<input
55-
id="slider-4"
55+
id="slider-0"
5656
max="100"
5757
min="20"
5858
slot="input"
@@ -61,7 +61,7 @@ snapshots["vaadin-range-slider host min"] =
6161
type="range"
6262
>
6363
<input
64-
id="slider-5"
64+
id="slider-1"
6565
max="100"
6666
min="20"
6767
slot="input"
@@ -76,7 +76,7 @@ snapshots["vaadin-range-slider host min"] =
7676
snapshots["vaadin-range-slider host max"] =
7777
`<vaadin-range-slider>
7878
<input
79-
id="slider-6"
79+
id="slider-0"
8080
max="80"
8181
min="0"
8282
slot="input"
@@ -85,7 +85,7 @@ snapshots["vaadin-range-slider host max"] =
8585
type="range"
8686
>
8787
<input
88-
id="slider-7"
88+
id="slider-1"
8989
max="80"
9090
min="0"
9191
slot="input"
@@ -100,7 +100,7 @@ snapshots["vaadin-range-slider host max"] =
100100
snapshots["vaadin-range-slider host step"] =
101101
`<vaadin-range-slider>
102102
<input
103-
id="slider-8"
103+
id="slider-0"
104104
max="100"
105105
min="0"
106106
slot="input"
@@ -109,7 +109,7 @@ snapshots["vaadin-range-slider host step"] =
109109
type="range"
110110
>
111111
<input
112-
id="slider-9"
112+
id="slider-1"
113113
max="100"
114114
min="0"
115115
slot="input"
@@ -121,6 +121,35 @@ snapshots["vaadin-range-slider host step"] =
121121
`;
122122
/* end snapshot vaadin-range-slider host step */
123123

124+
snapshots["vaadin-range-slider host disabled"] =
125+
`<vaadin-range-slider
126+
aria-disabled="true"
127+
disabled=""
128+
>
129+
<input
130+
disabled=""
131+
id="slider-0"
132+
max="100"
133+
min="0"
134+
slot="input"
135+
step="1"
136+
tabindex="-1"
137+
type="range"
138+
>
139+
<input
140+
disabled=""
141+
id="slider-1"
142+
max="100"
143+
min="0"
144+
slot="input"
145+
step="1"
146+
tabindex="-1"
147+
type="range"
148+
>
149+
</vaadin-range-slider>
150+
`;
151+
/* end snapshot vaadin-range-slider host disabled */
152+
124153
snapshots["vaadin-range-slider shadow default"] =
125154
`<div part="track">
126155
<div

packages/slider/test/dom/__snapshots__/slider.test.snap.js

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ snapshots["vaadin-slider host default"] =
1919
snapshots["vaadin-slider host value"] =
2020
`<vaadin-slider>
2121
<input
22-
id="slider-1"
22+
id="slider-0"
2323
max="100"
2424
min="0"
2525
slot="input"
@@ -34,7 +34,7 @@ snapshots["vaadin-slider host value"] =
3434
snapshots["vaadin-slider host min"] =
3535
`<vaadin-slider>
3636
<input
37-
id="slider-2"
37+
id="slider-0"
3838
max="100"
3939
min="20"
4040
slot="input"
@@ -49,7 +49,7 @@ snapshots["vaadin-slider host min"] =
4949
snapshots["vaadin-slider host max"] =
5050
`<vaadin-slider>
5151
<input
52-
id="slider-3"
52+
id="slider-0"
5353
max="80"
5454
min="0"
5555
slot="input"
@@ -64,7 +64,7 @@ snapshots["vaadin-slider host max"] =
6464
snapshots["vaadin-slider host step"] =
6565
`<vaadin-slider>
6666
<input
67-
id="slider-4"
67+
id="slider-0"
6868
max="100"
6969
min="0"
7070
slot="input"
@@ -76,6 +76,25 @@ snapshots["vaadin-slider host step"] =
7676
`;
7777
/* end snapshot vaadin-slider host step */
7878

79+
snapshots["vaadin-slider host disabled"] =
80+
`<vaadin-slider
81+
aria-disabled="true"
82+
disabled=""
83+
>
84+
<input
85+
disabled=""
86+
id="slider-0"
87+
max="100"
88+
min="0"
89+
slot="input"
90+
step="1"
91+
tabindex="-1"
92+
type="range"
93+
>
94+
</vaadin-slider>
95+
`;
96+
/* end snapshot vaadin-slider host disabled */
97+
7998
snapshots["vaadin-slider shadow default"] =
8099
`<div part="track">
81100
<div

packages/slider/test/dom/range-slider.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { expect } from '@vaadin/chai-plugins';
22
import { fixtureSync } from '@vaadin/testing-helpers';
33
import '../../src/vaadin-range-slider.js';
4+
import { resetUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
45
import type { RangeSlider } from '../../src/vaadin-range-slider.js';
56

67
window.Vaadin ??= {};
@@ -11,6 +12,7 @@ describe('vaadin-range-slider', () => {
1112
let slider: RangeSlider;
1213

1314
beforeEach(async () => {
15+
resetUniqueId();
1416
slider = fixtureSync('<vaadin-range-slider></vaadin-range-slider>');
1517
});
1618

@@ -41,6 +43,11 @@ describe('vaadin-range-slider', () => {
4143
slider.value = [20, 60];
4244
await expect(slider).dom.to.equalSnapshot();
4345
});
46+
47+
it('disabled', async () => {
48+
slider.disabled = true;
49+
await expect(slider).dom.to.equalSnapshot();
50+
});
4451
});
4552

4653
describe('shadow', async () => {

packages/slider/test/dom/slider.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { expect } from '@vaadin/chai-plugins';
22
import { fixtureSync } from '@vaadin/testing-helpers';
33
import '../../src/vaadin-slider.js';
4+
import { resetUniqueId } from '@vaadin/component-base/src/unique-id-utils.js';
45
import type { Slider } from '../../src/vaadin-slider.js';
56

67
window.Vaadin ??= {};
@@ -11,6 +12,7 @@ describe('vaadin-slider', () => {
1112
let slider: Slider;
1213

1314
beforeEach(async () => {
15+
resetUniqueId();
1416
slider = fixtureSync('<vaadin-slider></vaadin-slider>');
1517
});
1618

@@ -41,6 +43,11 @@ describe('vaadin-slider', () => {
4143
slider.value = 50;
4244
await expect(slider).dom.to.equalSnapshot();
4345
});
46+
47+
it('disabled', async () => {
48+
slider.disabled = true;
49+
await expect(slider).dom.to.equalSnapshot();
50+
});
4451
});
4552

4653
describe('shadow', async () => {

packages/slider/test/range-slider.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ describe('vaadin-range-slider', () => {
9999
expect(slider.hasAttribute('end-focused')).to.be.false;
100100
});
101101

102+
it('should not focus any of the inputs on focus() when disabled', () => {
103+
slider.disabled = true;
104+
slider.focus();
105+
expect(document.activeElement).to.not.equal(inputs[0]);
106+
expect(document.activeElement).to.not.equal(inputs[1]);
107+
});
108+
102109
it('should not throw when calling focus() before adding to the DOM', () => {
103110
expect(() => document.createElement('vaadin-range-slider').focus()).to.not.throw(Error);
104111
});
@@ -338,6 +345,18 @@ describe('vaadin-range-slider', () => {
338345

339346
expect(spy).to.be.not.called;
340347
});
348+
349+
it('should not update value property on thumb pointermove when disabled', async () => {
350+
slider.disabled = true;
351+
352+
const { x, y } = middleOfThumb(0);
353+
354+
await sendMouseToElement({ type: 'move', element: thumbs[0] });
355+
await sendMouse({ type: 'down' });
356+
await sendMouse({ type: 'move', position: [x + 20, y] });
357+
358+
expect(slider.value).to.deep.equal([0, 100]);
359+
});
341360
});
342361

343362
describe('track', () => {
@@ -409,6 +428,17 @@ describe('vaadin-range-slider', () => {
409428

410429
expect(spy).to.be.calledOnce;
411430
});
431+
432+
it('should not update value property on track pointerdown when disabled', async () => {
433+
slider.disabled = true;
434+
435+
const { x, y } = middleOfThumb(0);
436+
437+
await sendMouse({ type: 'move', position: [x - 20, y] });
438+
await sendMouse({ type: 'down' });
439+
440+
expect(slider.value).to.deep.equal([20, 80]);
441+
});
412442
});
413443

414444
describe('thumbs limits', () => {

0 commit comments

Comments
 (0)