Skip to content

Commit f89fdab

Browse files
committed
feat(RangeSlider): allow to disable track filling; improve tooltips position handling
1 parent 51f2dfd commit f89fdab

File tree

4 files changed

+78
-14
lines changed

4 files changed

+78
-14
lines changed

docs/content/forms/range-slider.md

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ Create a simple range slider with default settings.
4040
Enable multiple handles to allow the selection of a range or/and multiple values.
4141

4242
{{< example >}}
43-
<div data-coreui-toggle="range-slider" data-coreui-value="20,40"></div>
44-
<div data-coreui-toggle="range-slider" data-coreui-value="20,40,60"></div>
43+
<div class="mb-3" data-coreui-toggle="range-slider" data-coreui-value="20,40"></div>
44+
<div class="mb-3" data-coreui-toggle="range-slider" data-coreui-value="20,40,60"></div>
4545
<div data-coreui-toggle="range-slider" data-coreui-value="20,40,60,80"></div>
4646
{{< /example >}}
4747

@@ -51,8 +51,9 @@ Rotate the slider to a vertical orientation.
5151

5252
{{< example >}}
5353
<div class="d-flex">
54-
<div data-coreui-toggle="range-slider" data-coreui-value="20" data-coreui-vertical="true"></div>
55-
<div data-coreui-toggle="range-slider" data-coreui-value="20,80" data-coreui-vertical="true"></div>
54+
<div class="me-3" data-coreui-toggle="range-slider" data-coreui-value="20" data-coreui-vertical="true"></div>
55+
<div class="me-3" data-coreui-toggle="range-slider" data-coreui-value="20,80" data-coreui-vertical="true"></div>
56+
<div data-coreui-toggle="range-slider" data-coreui-value="20,80,100" data-coreui-vertical="true"></div>
5657
</div>
5758
{{< /example >}}
5859

@@ -61,7 +62,7 @@ Rotate the slider to a vertical orientation.
6162
Disable the slider to prevent user interaction.
6263

6364
{{< example >}}
64-
<div data-coreui-toggle="range-slider" data-coreui-value="50" data-coreui-disabled="true"></div>
65+
<div class="mb-3" data-coreui-toggle="range-slider" data-coreui-value="50" data-coreui-disabled="true"></div>
6566
<div data-coreui-toggle="range-slider" data-coreui-value="50, 75" data-coreui-disabled="true"></div>
6667
{{< /example >}}
6768

@@ -70,7 +71,7 @@ Disable the slider to prevent user interaction.
7071
Range Slider has implicit values for `min` and `max``0` and `100`, respectively. You may specify new values for those using the `min` and `max` attributes.
7172

7273
{{< example >}}
73-
<div data-coreui-toggle="range-slider" data-coreui-min="-50" data-coreui-max="150" data-coreui-value="50"></div>
74+
<div class="mb-3" data-coreui-toggle="range-slider" data-coreui-min="-50" data-coreui-max="150" data-coreui-value="50"></div>
7475
<div data-coreui-toggle="range-slider" data-coreui-min="-50" data-coreui-max="150" data-coreui-value="50, 75"></div>
7576
{{< /example >}}
7677

@@ -79,7 +80,7 @@ Range Slider has implicit values for `min` and `max`—`0` and `100`, respective
7980
Range Slider inputs automatically "snap" to whole numbers. To modify this behavior, set a `step` value. In the example below, we increase the number of steps by specifying `step="0.25"`.
8081

8182
{{< example >}}
82-
<div data-coreui-toggle="range-slider" data-coreui-step="0.25" data-coreui-value="50" ></div>
83+
<div class="mb-3" data-coreui-toggle="range-slider" data-coreui-step="0.25" data-coreui-value="50" ></div>
8384
<div data-coreui-toggle="range-slider" data-coreui-step="0.25" data-coreui-value="50, 75"></div>
8485
{{< /example >}}
8586

@@ -135,6 +136,20 @@ Customize the content of tooltips using the `tooltipsFormat` option. This can be
135136

136137
{{< js-docs name="range-slider-custom-tooltips" file="docs/assets/js/snippets.js" >}}
137138

139+
## Track
140+
141+
The `data-coreui-track` option allows you to customize how the slider's track is displayed. By default, the `data-coreui-track` option is set to `'fill'` enabling dynamic filling of the track based on the slider's current value(s). This means the filled portion of the track will adjust automatically as the slider handle(s) move, offering a responsive visual representation of the selected range.
142+
143+
### Disable filling
144+
145+
If you set `data-coreui-track` to `false`, the slider's track will not display any fill. Only the default track background will be visible, which can be useful for minimalist designs or when you use more then two handles.
146+
147+
{{< example >}}
148+
<div class="mb-3" data-coreui-toggle="range-slider" data-coreui-track="false" data-coreui-value="50" ></div>
149+
<div class="mb-3" data-coreui-toggle="range-slider" data-coreui-track="false" data-coreui-value="50, 75"></div>
150+
<div data-coreui-toggle="range-slider" data-coreui-track="false" data-coreui-value="25, 50, 75"></div>
151+
{{< /example >}}
152+
138153
## Usage
139154

140155
### Via data attributes
@@ -191,6 +206,7 @@ const rangeSlider = new RangeSlider(rangeSliderElement, {
191206
| `step` | number, string | `1` | Specifies the increment step for slider values. |
192207
| `tooltips` | boolean | `true` | Enables or disables tooltips that display current slider values. |
193208
| `tooltipsFormat` | function, null | `null` | Provides a custom formatting function for tooltip values. |
209+
| `track` | boolean, 'fill' | `'fill'` | Controls the visual representation of the slider's track. When set to `'fill'`, the track is dynamically filled based on the slider's value(s). Setting it to `false` disables the filled track. |
194210
| `value` | array, number | `0` | Sets the initial value(s) of the slider. |
195211
| `vertical` | boolean | `false` | Rotates the slider to a vertical orientation. |
196212
{{< /bs-table >}}
@@ -222,6 +238,18 @@ myRangeSlider.addEventListener('change.coreui.range-slider', event => {
222238
})
223239
```
224240

241+
## Accessibility
242+
243+
The Range Slider component is built with accessibility in mind. Each slider handle includes the following ARIA attributes:
244+
245+
- `role="slider"`
246+
- `aria-valuemin`: Minimum value
247+
- `aria-valuemax`: Maximum value
248+
- `aria-valuenow`: Current value
249+
- `aria-orientation`: horizontal or vertical
250+
251+
Additionally, ensure that labels and tooltips are clear and descriptive to provide the best experience for all users.
252+
225253
## Customizing
226254

227255
### CSS variables

js/src/range-slider.js

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ const Default = {
5858
step: 1,
5959
tooltips: true,
6060
tooltipsFormat: null,
61+
track: 'fill',
6162
value: 0,
6263
vertical: false
6364
}
@@ -73,6 +74,7 @@ const DefaultType = {
7374
step: '(number|string)',
7475
tooltips: 'boolean',
7576
tooltipsFormat: '(function|null)',
77+
track: '(boolean|string)',
7678
value: '(array|number)',
7779
vertical: 'boolean'
7880
}
@@ -86,12 +88,14 @@ class RangeSlider extends BaseComponent {
8688
super(element)
8789

8890
this._config = this._getConfig(config)
91+
8992
this._currentValue = this._config.value
93+
this._dragIndex = 0
9094
this._inputs = []
95+
this._isDragging = false
9196
this._sliderTrack = null
97+
this._thumbSize = null
9298
this._tooltips = []
93-
this._isDragging = false
94-
this._dragIndex = 0
9599

96100
this._initializeRangeSlider()
97101
}
@@ -312,6 +316,7 @@ class RangeSlider extends BaseComponent {
312316
}
313317

314318
const inputs = SelectorEngine.find(SELECTOR_RANGE_SLIDER_INPUT, this._element)
319+
this._thumbSize = this._getThumbSize()
315320

316321
for (const input of inputs) {
317322
const tooltipElement = this._createElement('div', CLASS_NAME_RANGE_SLIDER_TOOLTIP)
@@ -327,9 +332,32 @@ class RangeSlider extends BaseComponent {
327332
}
328333
}
329334

335+
_getThumbSize() {
336+
const value = window
337+
.getComputedStyle(this._element, null)
338+
.getPropertyValue(
339+
this._config.vertical ? '--cui-range-slider-thumb-height' : '--cui-range-slider-thumb-width'
340+
)
341+
342+
const regex = /^(\d+\.?\d*)([%a-z]*)$/i
343+
const match = value.match(regex)
344+
345+
if (match) {
346+
return {
347+
value: Number.parseFloat(match[1]),
348+
unit: match[2] || null
349+
}
350+
}
351+
352+
return null
353+
}
354+
330355
_positionTooltip(tooltip, input) {
356+
const thumbSize = this._thumbSize
331357
const percent = (input.value - this._config.min) / (this._config.max - this._config.min)
332-
const margin = percent > 0.5 ? `-${percent - 0.5}rem` : `${0.5 - percent}rem`
358+
const margin = percent > 0.5 ?
359+
`-${(percent - 0.5) * thumbSize.value}${thumbSize.unit}` :
360+
`${(0.5 - percent) * thumbSize.value}${thumbSize.unit}`
333361

334362
if (this._config.vertical) {
335363
Object.assign(tooltip.style, {
@@ -442,6 +470,10 @@ class RangeSlider extends BaseComponent {
442470
}
443471

444472
_updateGradient() {
473+
if (!this._config.track) {
474+
return
475+
}
476+
445477
const [min, max] = [Math.min(...this._currentValue), Math.max(...this._currentValue)]
446478
const from = ((min - this._config.min) / (this._config.max - this._config.min)) * 100
447479
const to = ((max - this._config.min) / (this._config.max - this._config.min)) * 100

scss/_range-slider.scss

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
--#{$prefix}range-slider-tooltip-zindex: #{$zindex-tooltip};
2929
--#{$prefix}range-slider-tooltip-padding-y: #{$range-slider-tooltip-padding-y};
3030
--#{$prefix}range-slider-tooltip-padding-x: #{$range-slider-tooltip-padding-x};
31+
--#{$prefix}range-slider-tooltip-margin-end: #{$range-slider-tooltip-margin-end};
32+
--#{$prefix}range-slider-tooltip-margin-bottom: #{$range-slider-tooltip-margin-bottom};
3133
--#{$prefix}range-slider-tooltip-font-size: #{$range-slider-tooltip-font-size};
3234
--#{$prefix}range-slider-tooltip-color: #{$range-slider-tooltip-color};
3335
--#{$prefix}range-slider-tooltip-bg: #{$range-slider-tooltip-bg};
@@ -57,7 +59,7 @@
5759
position: relative;
5860
display: flex;
5961
align-items: center;
60-
height: add($form-range-thumb-height, $form-range-thumb-focus-box-shadow-width * 2);
62+
height: max(var(--#{$prefix}range-slider-thumb-height), var(--#{$prefix}range-slider-track-height));
6163
}
6264

6365
.range-slider-track {
@@ -208,7 +210,7 @@
208210
}
209211

210212
.range-slider-tooltip {
211-
bottom: calc(1.5 * var(--#{$prefix}range-slider-thumb-height)); // stylelint-disable-line function-disallowed-list
213+
bottom: calc(var(--#{$prefix}range-slider-tooltip-margin-bottom) + var(--#{$prefix}range-slider-thumb-height)); // stylelint-disable-line function-disallowed-list
212214
}
213215

214216
.range-slider-tooltip-arrow {
@@ -233,7 +235,7 @@
233235

234236
.range-slider-inputs-container {
235237
justify-content: center;
236-
width: add($form-range-thumb-width, $form-range-thumb-focus-box-shadow-width * 2);
238+
width: max(var(--#{$prefix}range-slider-thumb-width), var(--#{$prefix}range-slider-vertical-track-width));
237239
height: 100%;
238240
}
239241

@@ -249,7 +251,7 @@
249251
}
250252

251253
.range-slider-tooltip {
252-
@include ltr-rtl("right", calc(1.5 * var(--#{$prefix}range-slider-thumb-width)));
254+
@include ltr-rtl("right", calc(var(--#{$prefix}range-slider-tooltip-margin-end) + var(--#{$prefix}range-slider-thumb-width)));
253255
flex-direction: row;
254256
transform: translateY(50%);
255257
}

scss/_variables.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2547,6 +2547,8 @@ $range-slider-thumb-transition: background-color .15s ease-in-out, bo
25472547

25482548
$range-slider-tooltip-padding-y: $spacer * .25 !default;
25492549
$range-slider-tooltip-padding-x: $spacer * .5 !default;
2550+
$range-slider-tooltip-margin-end: .25rem !default;
2551+
$range-slider-tooltip-margin-bottom: .25rem !default;
25502552
$range-slider-tooltip-font-size: $font-size-sm !default;
25512553
$range-slider-tooltip-color: var(--#{$prefix}body-color) !default;
25522554
$range-slider-tooltip-bg: var(--#{$prefix}secondary-bg) !default;

0 commit comments

Comments
 (0)