diff --git a/docs/pages/components/multi-range.md b/docs/pages/components/multi-range.md index f5ebed3f..b2131265 100644 --- a/docs/pages/components/multi-range.md +++ b/docs/pages/components/multi-range.md @@ -102,3 +102,17 @@ const App = () => +``` + +```jsx:react +import SlRange from '@shoelace-style/shoelace/dist/react/multi-range'; + +const App = () => ; +``` diff --git a/src/components/multi-range/multi-range.component.ts b/src/components/multi-range/multi-range.component.ts index 0d2f9db9..a2657f51 100644 --- a/src/components/multi-range/multi-range.component.ts +++ b/src/components/multi-range/multi-range.component.ts @@ -1,6 +1,9 @@ +import { classMap } from 'lit/directives/class-map.js'; +import { HasSlotController } from '../../internal/slot.js'; import { html } from 'lit'; import { ifDefined } from 'lit/directives/if-defined.js'; import { property, query, queryAll } from 'lit/decorators.js'; +import formControlStyles from '../../styles/form-control.styles.js'; import ShoelaceElement from '../../internal/shoelace-element.js'; import styles from './multi-range.styles.js'; import type { CSSResultGroup, PropertyValues } from 'lit'; @@ -25,6 +28,9 @@ const arraysDiffer = function (a: readonly number[], b: readonly number[]): bool * @status experimental * @since next * + * @slot label - The range's label. Alternatively, you can use the `label` attribute. + * @slot help-text - Text that describes how to use the input. Alternatively, you can use the `help-text` attribute. + * * @event sl-change - Emitted when an alteration to the control's value is committed by the user. * @event sl-input - Emitted when the control receives input. * @@ -34,11 +40,14 @@ const arraysDiffer = function (a: readonly number[], b: readonly number[]): bool * @cssproperty --track-height - The height of the track. */ export default class SlMultiRange extends ShoelaceElement { - static styles: CSSResultGroup = [styles]; + static styles: CSSResultGroup = [formControlStyles, styles]; - /** The range's label. */ + /** The range's label. If you need to display HTML, use the `label` slot instead. */ @property() label = ''; + /** The range's help text. If you need to display HTML, use the help-text slot instead. */ + @property({ attribute: 'help-text' }) helpText = ''; + /** Disables the range. */ @property({ type: Boolean, reflect: true }) disabled = false; @@ -70,11 +79,15 @@ export default class SlMultiRange extends ShoelaceElement { @query('.active-track') activeTrack: HTMLDivElement; @queryAll('.handle') handles: NodeListOf; + #hasSlotController = new HasSlotController(this, 'help-text', 'label'); #value: readonly number[] = [0, 100]; #sliderValues = new Map(); #nextId = 1; override render(): unknown { + const hasLabel = !!(this.label || this.#hasSlotController.test('label')); + const hasHelpText = !!(this.helpText || this.#hasSlotController.test('help-text')); + this.#sliderValues.clear(); const handles = this.#value.map(value => { const sliderId = this.#nextId++; @@ -84,7 +97,7 @@ export default class SlMultiRange extends ShoelaceElement { class="handle" tabindex="${this.disabled ? -1 : 0}" role="slider" - aria-label="${this.label}" + aria-labelledby=${ifDefined(hasLabel ? "label" : undefined)} aria-valuemin="${this.min}" aria-valuemax="${this.max}" aria-disabled=${ifDefined(this.disabled ? 'true' : undefined)} @@ -100,11 +113,23 @@ export default class SlMultiRange extends ShoelaceElement { }); return html` - -
-
-
- ${handles} +
+ +
+
+
+ ${handles} +
+
+ ${this.helpText} +
`; } diff --git a/src/components/multi-range/multi-range.styles.ts b/src/components/multi-range/multi-range.styles.ts index c005f16c..d3a8dc39 100644 --- a/src/components/multi-range/multi-range.styles.ts +++ b/src/components/multi-range/multi-range.styles.ts @@ -6,23 +6,15 @@ export default css` --track-color-active: var(--sl-color-neutral-200); --track-color-inactive: var(--sl-color-neutral-200); --track-height: 6px; + } + .form-control { display: flex; flex-direction: column; align-items: stretch; box-sizing: border-box; } - label { - display: inline-block; - color: var(--sl-input-label-color); - margin-bottom: var(--sl-spacing-3x-small); - } - - label[hidden] { - display: none; - } - .base { display: block; position: relative;