diff --git a/docs/docs/components/range.md b/docs/docs/components/range.md index bc7cc25b3..c3db10ce8 100644 --- a/docs/docs/components/range.md +++ b/docs/docs/components/range.md @@ -103,3 +103,14 @@ You can change the tooltip's content by setting the `tooltipFormatter` property range.tooltipFormatter = value => `Total - ${value}%`; ``` + +### Right-to-Left languages + +The component adapts to right-to-left (RTL) languages as you would expect. + +```html {.example} + +``` diff --git a/src/components/range/range.css b/src/components/range/range.css index b0a617692..cf623e6d3 100644 --- a/src/components/range/range.css +++ b/src/components/range/range.css @@ -3,23 +3,21 @@ --thumb-gap: calc(var(--thumb-size) * 0.125); --thumb-shadow: initial; --thumb-size: calc(1rem * var(--wa-form-control-value-line-height)); + --tooltip-offset: calc(var(--wa-tooltip-arrow-size) * 1.375); + --track-color-active: var(--wa-color-neutral-fill-normal); --track-color-inactive: var(--wa-color-neutral-fill-normal); --track-active-offset: 0%; --track-height: calc(var(--thumb-size) * 0.25); - display: block; -} - -.range { - position: relative; display: flex; - align-items: center; - height: max(var(--thumb-size), var(--track-height)); + flex-direction: column; + position: relative; + min-height: max(var(--thumb-size), var(--track-height)); } -.control { +input[type='range'] { --percent: 0%; -webkit-appearance: none; border-radius: calc(var(--track-height) / 2); @@ -29,126 +27,113 @@ line-height: var(--wa-form-control-height-m); vertical-align: middle; margin: 0; + --dir: right; background-image: linear-gradient( - to right, - var(--track-color-inactive) 0%, + to var(--dir), var(--track-color-inactive) min(var(--percent), var(--track-active-offset)), var(--track-color-active) min(var(--percent), var(--track-active-offset)), var(--track-color-active) max(var(--percent), var(--track-active-offset)), - var(--track-color-inactive) max(var(--percent), var(--track-active-offset)), - var(--track-color-inactive) 100% + var(--track-color-inactive) max(var(--percent), var(--track-active-offset)) ); -} -.range--rtl .control { - background-image: linear-gradient( - to left, - var(--track-color-inactive) 0%, - var(--track-color-inactive) min(var(--percent), var(--track-active-offset)), - var(--track-color-active) min(var(--percent), var(--track-active-offset)), - var(--track-color-active) max(var(--percent), var(--track-active-offset)), - var(--track-color-inactive) max(var(--percent), var(--track-active-offset)), - var(--track-color-inactive) 100% - ); -} + &:dir(rtl) { + --dir: left; + } -/* Webkit */ -.control::-webkit-slider-runnable-track { - width: 100%; - height: var(--track-height); - border-radius: 3px; - border: none; -} + &::-webkit-slider-runnable-track { + width: 100%; + height: var(--track-height); + border-radius: 3px; + border: none; + } -.control::-webkit-slider-thumb { - width: var(--thumb-size); - height: var(--thumb-size); - border-radius: 50%; - background-color: var(--thumb-color); - box-shadow: - var(--thumb-shadow, 0 0 transparent), - 0 0 0 var(--thumb-gap) var(--wa-color-surface-default); - -webkit-appearance: none; - margin-top: calc(var(--thumb-size) / -2 + var(--track-height) / 2); - cursor: pointer; -} + &::-webkit-slider-thumb { + width: var(--thumb-size); + height: var(--thumb-size); + border-radius: 50%; + background-color: var(--thumb-color); + box-shadow: + var(--thumb-shadow, 0 0 transparent), + 0 0 0 var(--thumb-gap) var(--wa-color-surface-default); + -webkit-appearance: none; + margin-top: calc(var(--thumb-size) / -2 + var(--track-height) / 2); + cursor: pointer; + } -.control:enabled:focus-visible::-webkit-slider-thumb { - outline: var(--wa-focus-ring); - outline-offset: var(--wa-focus-ring-offset); -} + &:enabled { + &:focus-visible::-webkit-slider-thumb { + outline: var(--wa-focus-ring); + outline-offset: var(--wa-focus-ring-offset); + } -.control:enabled::-webkit-slider-thumb:active { - cursor: grabbing; -} + &::-webkit-slider-thumb:active { + cursor: grabbing; + } + } -/* Firefox */ -.control::-moz-focus-outer { - border: 0; -} + &::-moz-focus-outer { + border: 0; + } -.control::-moz-range-progress { - background-color: var(--track-color-active); - border-radius: 3px; - height: var(--track-height); -} + &::-moz-range-progress { + background-color: var(--track-color-active); + border-radius: 3px; + height: var(--track-height); + } -.control::-moz-range-track { - width: 100%; - height: var(--track-height); - background-color: var(--track-color-inactive); - border-radius: 3px; - border: none; -} + &::-moz-range-track { + width: 100%; + height: var(--track-height); + background-color: var(--track-color-inactive); + border-radius: 3px; + border: none; + } -.control::-moz-range-thumb { - height: var(--thumb-size); - width: var(--thumb-size); - border-radius: 50%; - background-color: var(--thumb-color); - box-shadow: - var(--thumb-shadow), - 0 0 0 var(--thumb-gap) var(--wa-color-surface-default); - transition: - background-color var(--wa-transition-normal) var(--wa-transition-easing), - border-color var(--wa-transition-normal) var(--wa-transition-easing), - box-shadow var(--wa-transition-normal) var(--wa-transition-easing), - color var(--wa-transition-normal) var(--wa-transition-easing); - cursor: pointer; -} + &::-moz-range-thumb { + height: var(--thumb-size); + width: var(--thumb-size); + border-radius: 50%; + background-color: var(--thumb-color); + box-shadow: + var(--thumb-shadow), + 0 0 0 var(--thumb-gap) var(--wa-color-surface-default); + transition-property: background-color, border-color, box-shadow, color; + transition-duration: var(--wa-transition-normal); + transition-timing-function: var(--wa-transition-easing); + cursor: pointer; + } -.control:enabled:focus-visible::-moz-range-thumb { - outline: var(--wa-focus-ring); - outline-offset: var(--wa-focus-ring-offset); -} + &:enabled { + &:focus-visible::-moz-range-thumb { + outline: var(--wa-focus-ring); + outline-offset: var(--wa-focus-ring-offset); + } -.control:enabled::-moz-range-thumb:active { - cursor: grabbing; -} + &::-moz-range-thumb:active { + cursor: grabbing; + } + } -/* States */ -.control:focus-visible { - outline: none; -} + /* States */ -.control:disabled { - opacity: 0.5; -} + &:focus-visible { + outline: none; + } -.control:disabled::-webkit-slider-thumb { - cursor: not-allowed; -} - -.control:disabled::-moz-range-thumb { - cursor: not-allowed; + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } } /* Tooltip output */ .tooltip { position: absolute; z-index: 1000; - left: 0; + inset-inline-start: 0; + + inset-block-end: calc(50% + (var(--thumb-size) / 2) + var(--tooltip-offset)); border-radius: var(--wa-tooltip-border-radius); background-color: var(--wa-tooltip-background-color); font-family: inherit; @@ -159,60 +144,43 @@ padding: var(--wa-space-2xs) var(--wa-space-xs); transition: var(--wa-transition-normal) opacity; pointer-events: none; -} -.tooltip:after { - content: ''; - position: absolute; - width: 0; - height: 0; - left: 50%; - translate: calc(-1 * var(--wa-tooltip-arrow-size)); -} + &:after { + content: ''; + position: absolute; + width: 0; + height: 0; + inset-inline-start: 50%; + inset-block-start: 100%; + translate: calc(-1 * var(--wa-tooltip-arrow-size)); + border-inline: var(--wa-tooltip-arrow-size) solid transparent; + border-block-start: var(--border-block); + } -.range--tooltip-visible .tooltip { - opacity: 1; -} + &.visible { + opacity: 1; + } -/* Tooltip on top */ -.range--tooltip-top .tooltip { - bottom: calc(50% + (var(--thumb-size) / 2) + var(--tooltip-offset)); -} + --inset-block: calc(50% + (var(--thumb-size) / 2) + var(--tooltip-offset)); + --border-block: var(--wa-tooltip-arrow-size) solid var(--wa-color-neutral-fill-loud); -.range--tooltip-top .tooltip:after { - border-top: var(--wa-tooltip-arrow-size) solid var(--wa-color-neutral-fill-loud); - border-left: var(--wa-tooltip-arrow-size) solid transparent; - border-right: var(--wa-tooltip-arrow-size) solid transparent; - top: 100%; + @media (forced-colors: active) { + border: solid 1px transparent; + + &:after { + display: none; + } + } } /* Tooltip on bottom */ -.range--tooltip-bottom .tooltip { - top: calc(50% + (var(--thumb-size) / 2) + var(--tooltip-offset)); -} +:host([tooltip='bottom']) .tooltip { + inset-block-end: auto; + inset-block-start: calc(50% + (var(--thumb-size) / 2) + var(--tooltip-offset)); -.range--tooltip-bottom .tooltip:after { - border-bottom: var(--wa-tooltip-arrow-size) solid var(--wa-color-neutral-fill-loud); - border-left: var(--wa-tooltip-arrow-size) solid transparent; - border-right: var(--wa-tooltip-arrow-size) solid transparent; - bottom: 100%; -} - -@media (forced-colors: active) { - .control, - .tooltip { - border: solid 1px transparent; - } - - .control::-webkit-slider-thumb { - border: solid 1px transparent; - } - - .control::-moz-range-thumb { - border: solid 1px transparent; - } - - .tooltip:after { - display: none; + &:after { + border-block-end: var(--border-block); + inset-block-start: auto; + inset-block-end: 100%; } } diff --git a/src/components/range/range.ts b/src/components/range/range.ts index 949c43eaf..b3f9c71e8 100644 --- a/src/components/range/range.ts +++ b/src/components/range/range.ts @@ -31,11 +31,10 @@ import styles from './range.css'; * @event wa-invalid - Emitted when the form control has been checked for validity and its constraints aren't satisfied. * * @csspart form-control - The form control that wraps the label, input, and hint. - * @csspart form-control-label - The label's wrapper. - * @csspart form-control-input - The range's wrapper. + * @csspart form-control-label - The input's label. + * @csspart form-control-input - The input's wrapper. * @csspart hint - The hint's wrapper. - * @csspart base - The component's base wrapper. - * @csspart input - The internal `` element. + * @csspart base - The internal `` element. * @csspart tooltip - The range's tooltip. * * @cssproperty --thumb-color - The color of the thumb. @@ -280,73 +279,53 @@ export default class WaRange extends WebAwesomeFormAssociatedElement { // NOTE - always bind value after min/max, otherwise it will be clamped return html` -
- + ${hasLabel + ? html`` + : ''} -
-
- - ${this.tooltip !== 'none' && !this.disabled - ? html` - - ${typeof this.tooltipFormatter === 'function' ? this.tooltipFormatter(this.value) : this.value} - - ` - : ''} -
-
- - ${this.hint} +
+ + ${this.tooltip !== 'none' && !this.disabled + ? html` + + ${typeof this.tooltipFormatter === 'function' ? this.tooltipFormatter(this.value) : this.value} + + ` + : ''}
+ + ${this.hint} `; } } diff --git a/src/styles/shadow/form-control.css b/src/styles/shadow/form-control.css index d4c649d40..c81b8689f 100644 --- a/src/styles/shadow/form-control.css +++ b/src/styles/shadow/form-control.css @@ -1,32 +1,25 @@ -.form-control .label { - display: none; -} - /* Label */ -.form-control--has-label .label { +[part~='form-control-label'] { display: block; color: var(--wa-form-control-label-color); font-weight: var(--wa-form-control-label-font-weight); line-height: var(--wa-form-control-label-line-height); margin-block-end: var(--wa-space-xs); + font-size: var(--wa-font-size-m); &:is(.form-control--small *) { font-size: var(--wa-font-size-s); } - &:is(.form-control--medium *) { - font-size: var(--wa-font-size-m); - } - &:is(.form-control--large *) { font-size: var(--wa-font-size-l); } -} -:host([required]) .form-control--has-label .label::after { - content: var(--wa-form-control-required-content); - margin-inline-start: var(--wa-form-control-required-content-offset); - color: var(--wa-form-control-required-content-color); + :host([required]) &::after { + content: var(--wa-form-control-required-content); + margin-inline-start: var(--wa-form-control-required-content-offset); + color: var(--wa-form-control-required-content-color); + } } /* Help text */