From a4aff0b1e9b25cceeff88f341093c635a9295787 Mon Sep 17 00:00:00 2001 From: Denis Date: Thu, 30 Sep 2021 11:20:39 +0400 Subject: [PATCH 1/2] #550 added progress indicator to sl-range component --- src/components/range/range.styles.ts | 12 ++++++++-- src/components/range/range.ts | 36 +++++++++++++++++++--------- 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/src/components/range/range.styles.ts b/src/components/range/range.styles.ts index f1d6de32c..f487171d9 100644 --- a/src/components/range/range.styles.ts +++ b/src/components/range/range.styles.ts @@ -8,6 +8,7 @@ export default css` ${formControlStyles} :host { + --indicator-color: rgb(var(--sl-color-primary-600)); --thumb-size: 20px; --tooltip-offset-y: 10px; --track-color: rgb(var(--sl-color-neutral-200)); @@ -22,8 +23,9 @@ export default css` .range__control { -webkit-appearance: none; + border-radius: 3px; width: 100%; - height: var(--sl-input-height-medium); + height: var(--track-height); background: transparent; line-height: var(--sl-input-height-medium); vertical-align: middle; @@ -33,7 +35,6 @@ export default css` .range__control::-webkit-slider-runnable-track { width: 100%; height: var(--track-height); - background-color: var(--track-color); border-radius: 3px; border: none; } @@ -74,6 +75,12 @@ export default css` border: 0; } + .range__control::-moz-range-progress { + background-color: var(--indicator-color); + border-radius: 3px; + height: var(--track-height); + } + .range__control::-moz-range-track { width: 100%; height: var(--track-height); @@ -175,6 +182,7 @@ export default css` .range--tooltip-bottom .range__tooltip { bottom: calc(-1 * var(--thumb-size) - var(--tooltip-offset-y)); } + .range--tooltip-bottom .range__tooltip:after { border-bottom: var(--sl-tooltip-arrow-size) solid rgb(var(--sl-tooltip-background-color)); border-left: var(--sl-tooltip-arrow-size) solid transparent; diff --git a/src/components/range/range.ts b/src/components/range/range.ts index 918375d8b..5b7a74e55 100644 --- a/src/components/range/range.ts +++ b/src/components/range/range.ts @@ -82,7 +82,7 @@ export default class SlRange extends LitElement { connectedCallback() { super.connectedCallback(); this.handleSlotChange = this.handleSlotChange; - this.resizeObserver = new ResizeObserver(() => this.syncTooltip()); + this.resizeObserver = new ResizeObserver(() => this.syncRange()); this.shadowRoot!.addEventListener('slotchange', this.handleSlotChange); if (this.value === undefined || this.value === null) this.value = this.min; @@ -92,7 +92,7 @@ export default class SlRange extends LitElement { this.handleSlotChange(); this.updateComplete.then(() => { - this.syncTooltip(); + this.syncRange(); this.resizeObserver.observe(this.input); }); } @@ -123,7 +123,7 @@ export default class SlRange extends LitElement { this.value = Number(this.input.value); emit(this, 'sl-change'); - requestAnimationFrame(() => this.syncTooltip()); + requestAnimationFrame(() => this.syncRange()); } handleBlur() { @@ -162,18 +162,32 @@ export default class SlRange extends LitElement { this.hasTooltip = false; } - syncTooltip() { + syncRange(){ + const percent = Math.max(0, (this.value - this.min) / (this.max - this.min)); + + this.syncProgress(percent); if (this.tooltip !== 'none') { - const percent = Math.max(0, (this.value - this.min) / (this.max - this.min)); - const inputWidth = this.input.offsetWidth; - const tooltipWidth = this.output.offsetWidth; - const thumbSize = getComputedStyle(this.input).getPropertyValue('--thumb-size'); - const x = `calc(${inputWidth * percent}px - calc(calc(${percent} * ${thumbSize}) - calc(${thumbSize} / 2)))`; - this.output.style.transform = `translateX(${x})`; - this.output.style.marginLeft = `-${tooltipWidth / 2}px`; + this.syncTooltip(percent); } } + syncProgress(percent: number) { + const trackColor = getComputedStyle(this.input).getPropertyValue('--track-color'); + const indicatorColor = getComputedStyle(this.input).getPropertyValue('--indicator-color'); + + this.input.style.background = `linear-gradient(to right, ${indicatorColor} 0%, ${indicatorColor} ${percent*100}%, ${trackColor} ${percent*100}%, ${trackColor} 100%)`; + } + + syncTooltip(percent: number) { + const inputWidth = this.input.offsetWidth; + const tooltipWidth = this.output.offsetWidth; + const thumbSize = getComputedStyle(this.input).getPropertyValue('--thumb-size'); + const x = `calc(${inputWidth * percent}px - calc(calc(${percent} * ${thumbSize}) - calc(${thumbSize} / 2)))`; + + this.output.style.transform = `translateX(${x})`; + this.output.style.marginLeft = `-${tooltipWidth / 2}px`; + } + render() { // NOTE - always bind value after min/max, otherwise it will be clamped return renderFormControl( From f2a4db6291e565a8af12c2cb3fe255044a8ea07f Mon Sep 17 00:00:00 2001 From: Cory LaViska Date: Thu, 30 Sep 2021 07:51:28 -0400 Subject: [PATCH 2/2] update docs, expose custom properties, rework to not use getComputedStyle --- docs/components/range.md | 13 ++++++++++++- docs/resources/changelog.md | 2 ++ src/components/range/range.styles.ts | 14 +++++++------- src/components/range/range.ts | 18 ++++++++++++------ 4 files changed, 33 insertions(+), 14 deletions(-) diff --git a/docs/components/range.md b/docs/components/range.md index 963bcbf42..9d4f27fcd 100644 --- a/docs/components/range.md +++ b/docs/components/range.md @@ -5,7 +5,7 @@ Ranges allow the user to select a single value within a given range using a slider. ```html preview - + ``` ?> This component doesn't work with standard forms. Use [``](/components/form) instead. @@ -36,6 +36,17 @@ To disable the tooltip, set `tooltip` to `none`. ``` +### Custom Track Colors + +You can customize the active and inactive portions of the track using the `--track-color-active` and `--track-color-inactive` custom properties. + +```html preview + +``` + ### Custom Tooltip Formatter You can change the tooltip's content by setting the `tooltipFormatter` property to a function that accepts the range's value as an argument. diff --git a/docs/resources/changelog.md b/docs/resources/changelog.md index dc0f40e32..446e8e9c6 100644 --- a/docs/resources/changelog.md +++ b/docs/resources/changelog.md @@ -17,6 +17,8 @@ _During the beta period, these restrictions may be relaxed in the event of a mis - Added the `filled` variation to ``, ``, and `` and supporting design tokens - Added the `control` part to `` so you can target the main control with CSS [#538](https://github.com/shoelace-style/shoelace/issues/538) - Added a border to `` to improve contrast when drawn on various background colors +- Added `--track-color-active` and `--track-color-inactive` custom properties to `` [#550](https://github.com/shoelace-style/shoelace/issues/550) +- Added the undocumented custom properties `--thumb-size`, `--tooltip-offset`, `--track-height` on `` - Changed the default `distance` in `` from `2` to `0` [#538](https://github.com/shoelace-style/shoelace/issues/538) - Fixed a bug where `` would be larger than the viewport when it had lots of options [#544](https://github.com/shoelace-style/shoelace/issues/544) - Updated the default height of `` from `16px` to `1rem` and added a subtle shadow to indicate depth diff --git a/src/components/range/range.styles.ts b/src/components/range/range.styles.ts index f487171d9..b095372e9 100644 --- a/src/components/range/range.styles.ts +++ b/src/components/range/range.styles.ts @@ -8,10 +8,10 @@ export default css` ${formControlStyles} :host { - --indicator-color: rgb(var(--sl-color-primary-600)); --thumb-size: 20px; - --tooltip-offset-y: 10px; - --track-color: rgb(var(--sl-color-neutral-200)); + --tooltip-offset: 10px; + --track-color-active: rgb(var(--sl-color-neutral-200)); + --track-color-inactive: rgb(var(--sl-color-neutral-200)); --track-height: 6px; display: block; @@ -76,7 +76,7 @@ export default css` } .range__control::-moz-range-progress { - background-color: var(--indicator-color); + background-color: var(--track-color-active); border-radius: 3px; height: var(--track-height); } @@ -84,7 +84,7 @@ export default css` .range__control::-moz-range-track { width: 100%; height: var(--track-height); - background-color: var(--track-color); + background-color: var(--track-color-inactive); border-radius: 3px; border: none; } @@ -168,7 +168,7 @@ export default css` /* Tooltip on top */ .range--tooltip-top .range__tooltip { - top: calc(-1 * var(--thumb-size) - var(--tooltip-offset-y)); + top: calc(-1 * var(--thumb-size) - var(--tooltip-offset)); } .range--tooltip-top .range__tooltip:after { @@ -180,7 +180,7 @@ export default css` /* Tooltip on bottom */ .range--tooltip-bottom .range__tooltip { - bottom: calc(-1 * var(--thumb-size) - var(--tooltip-offset-y)); + bottom: calc(-1 * var(--thumb-size) - var(--tooltip-offset)); } .range--tooltip-bottom .range__tooltip:after { diff --git a/src/components/range/range.ts b/src/components/range/range.ts index 5b7a74e55..a9fdc6ddf 100644 --- a/src/components/range/range.ts +++ b/src/components/range/range.ts @@ -25,6 +25,12 @@ let id = 0; * @csspart base - The component's base wrapper. * @csspart input - The native range input. * @csspart tooltip - The range tooltip. + * + * @cssproperty --thumb-size - The size of the thumb. + * @cssproperty --tooltip-offset - The vertical distance the tooltip is offset from the track. + * @cssproperty --track-color-active - The color of the portion of the track that represents the current value. + * @cssproperty --track-color-inactive: The of the portion of the track that represents the remaining value. + * @cssproperty --track-height: The height of the track. */ @customElement('sl-range') export default class SlRange extends LitElement { @@ -162,20 +168,20 @@ export default class SlRange extends LitElement { this.hasTooltip = false; } - syncRange(){ + syncRange() { const percent = Math.max(0, (this.value - this.min) / (this.max - this.min)); this.syncProgress(percent); + if (this.tooltip !== 'none') { this.syncTooltip(percent); } } syncProgress(percent: number) { - const trackColor = getComputedStyle(this.input).getPropertyValue('--track-color'); - const indicatorColor = getComputedStyle(this.input).getPropertyValue('--indicator-color'); - - this.input.style.background = `linear-gradient(to right, ${indicatorColor} 0%, ${indicatorColor} ${percent*100}%, ${trackColor} ${percent*100}%, ${trackColor} 100%)`; + this.input.style.background = `linear-gradient(to right, var(--track-color-active) 0%, var(--track-color-active) ${ + percent * 100 + }%, var(--track-color-inactive) ${percent * 100}%, var(--track-color-inactive) 100%)`; } syncTooltip(percent: number) { @@ -183,7 +189,7 @@ export default class SlRange extends LitElement { const tooltipWidth = this.output.offsetWidth; const thumbSize = getComputedStyle(this.input).getPropertyValue('--thumb-size'); const x = `calc(${inputWidth * percent}px - calc(calc(${percent} * ${thumbSize}) - calc(${thumbSize} / 2)))`; - + this.output.style.transform = `translateX(${x})`; this.output.style.marginLeft = `-${tooltipWidth / 2}px`; }