Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions etc/lime-elements.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -663,8 +663,10 @@ export namespace Components {
"disabled": boolean;
"factor": number;
"helperText": string;
"invalid": boolean;
"label": string;
"readonly": boolean;
"required": boolean;
"step": number;
"unit": string;
"value": number;
Expand Down Expand Up @@ -1784,9 +1786,11 @@ export namespace JSX {
"disabled"?: boolean;
"factor"?: number;
"helperText"?: string;
"invalid"?: boolean;
"label"?: string;
"onChange"?: (event: LimelSliderCustomEvent<number>) => void;
"readonly"?: boolean;
"required"?: boolean;
"step"?: number;
"unit"?: string;
"value"?: number;
Expand Down
29 changes: 17 additions & 12 deletions src/components/slider/slider.scss
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,37 @@
@use '../../style/internal/lime-theme';

@use '@material/slider/styles';
@use '@material/floating-label/mdc-floating-label';

:host(limel-slider) {
isolation: isolate;
position: relative;
display: flex;
flex-direction: column;
}

:host(limel-slider:not([invalid]):not([invalid='true'])),
// We don't want the gray notched outlines around the slider by default
:host(limel-slider[disabled]:not([disabled='false'])) {
.limel-notched-outline {
--limel-notched-outline-border-color: transparent;
--limel-notched-outline-background-color: transparent;
}
// and we don't want the `disabled` but `invalid` slider to show any
// red lines. Since users cannot do anything to fix a disabled but invalid slider
}

div[slot='content'] {
display: flex;
flex-direction: column;
width: 100%;
padding: 0 0.25rem;
}

.mdc-slider {
height: shared_input-select-picker.$height-of-mdc-text-field;
margin: 0 0.75rem;
}

.mdc-floating-label,
.mdc-slider .mdc-slider__value-indicator-text {
// As long as this component is depended on MDC,
// we need to force it to be font-agnostic.
Expand All @@ -31,16 +46,6 @@
font-family: inherit;
}

.slider__label {
padding-left: functions.pxToRem(20);
top: 0.75rem; // To place its label on the same height as other `floating-label`s in a form

color: shared_input-select-picker.$label-color;
:host(limel-slider.disabled:not(.readonly)) & {
color: shared_input-select-picker.$label-color-disabled;
}
}

.slider__content-range-container {
display: flex;
order: 2;
Expand Down
154 changes: 102 additions & 52 deletions src/components/slider/slider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ export class Slider {
@Prop({ reflect: true })
public helperText: string;

/**
* Set to `true` to indicate that the slider is required.
*/
@Prop({ reflect: true })
public required = false;

/**
* Set to `true` to indicate that the current value of the slider is invalid.
*/
@Prop({ reflect: true })
public invalid = false;

/**
* Unit to display next to the value
*/
Expand Down Expand Up @@ -150,60 +162,21 @@ export class Slider {

return (
<Host class={this.getContainerClassList()}>
<label
class="slider__label mdc-floating-label mdc-floating-label--float-above"
id={this.labelId}
>
{this.label}
</label>
<div class="slider__content-range-container">
<span class="slider__content-min-label">
{this.multiplyByFactor(this.valuemin)}
{this.unit}
</span>
<span class="slider__content-max-label">
{this.multiplyByFactor(this.valuemax)}
{this.unit}
</span>
</div>
<div
class={{
'mdc-slider': true,
'mdc-slider--discrete': true,
'mdc-slider--disabled': this.disabled || this.readonly,
}}
<limel-notched-outline
labelId={this.labelId}
label={this.label}
required={this.required}
invalid={this.invalid}
disabled={this.disabled}
readonly={this.readonly}
hasValue={!!this.value}
hasFloatingLabel={true}
>
<input
class="mdc-slider__input"
type="range"
min={this.multiplyByFactor(this.valuemin)}
max={this.multiplyByFactor(this.valuemax)}
value={this.multiplyByFactor(this.value)}
name="volume"
aria-labelledby={this.labelId}
aria-controls={this.helperTextId}
{...inputProps}
/>
<div class="mdc-slider__track">
<div class="mdc-slider__track--inactive"></div>
<div class="mdc-slider__track--active">
<div class="mdc-slider__track--active_fill"></div>
</div>
</div>
<div class="mdc-slider__thumb">
<div
class="mdc-slider__value-indicator-container"
aria-hidden="true"
>
<div class="mdc-slider__value-indicator">
<span class="mdc-slider__value-indicator-text">
{this.multiplyByFactor(this.value)}
</span>
</div>
</div>
<div class="mdc-slider__thumb-knob"></div>
<div slot="content">
{this.renderRangeContainer()}
{this.renderSliderContainer(inputProps)}
</div>
</div>
</limel-notched-outline>
{this.renderHelperLine()}
</Host>
);
Expand Down Expand Up @@ -240,6 +213,82 @@ export class Slider {
this.reCreateSliderWithStep();
}

private renderRangeContainer = () => {
return (
<div class="slider__content-range-container">
<span class="slider__content-min-label">
{this.multiplyByFactor(this.valuemin)}
{this.unit}
</span>
<span class="slider__content-max-label">
{this.multiplyByFactor(this.valuemax)}
{this.unit}
</span>
</div>
);
};

private renderSliderContainer = (inputProps: any) => {
return (
<div
class={{
'mdc-slider': true,
'mdc-slider--discrete': true,
'mdc-slider--disabled': this.disabled || this.readonly,
}}
>
{this.renderSliderInput(inputProps)}
{this.renderTrack()}
{this.renderThumb()}
</div>
);
};

private renderSliderInput = (inputProps: any) => {
return (
<input
class="mdc-slider__input"
type="range"
min={this.multiplyByFactor(this.valuemin)}
max={this.multiplyByFactor(this.valuemax)}
value={this.multiplyByFactor(this.value)}
name="volume"
aria-labelledby={this.labelId}
aria-controls={this.helperTextId}
{...inputProps}
/>
);
};

private renderTrack = () => {
return (
<div class="mdc-slider__track">
<div class="mdc-slider__track--inactive" />
<div class="mdc-slider__track--active">
<div class="mdc-slider__track--active_fill" />
</div>
</div>
);
};

private renderThumb = () => {
return (
<div class="mdc-slider__thumb">
<div
class="mdc-slider__value-indicator-container"
aria-hidden="true"
>
<div class="mdc-slider__value-indicator">
<span class="mdc-slider__value-indicator-text">
{this.multiplyByFactor(this.value)}
</span>
</div>
</div>
<div class="mdc-slider__thumb-knob" />
</div>
);
};

private renderHelperLine = () => {
if (!this.helperText) {
return;
Expand All @@ -249,6 +298,7 @@ export class Slider {
<limel-helper-line
helperText={this.helperText}
helperTextId={this.helperTextId}
invalid={this.invalid}
/>
);
};
Expand Down