mirror of
https://github.com/material-components/material-web.git
synced 2024-10-27 06:04:44 +03:00
fix(slider): fixes label focus and ranged handle dragging on Safari
PiperOrigin-RevId: 526016986
This commit is contained in:
parent
356d1bc9f8
commit
72b48da7cc
@ -70,4 +70,11 @@ export class SliderHarness extends Harness<Slider> {
|
||||
}
|
||||
super.simulateStartHover(element, init);
|
||||
}
|
||||
|
||||
protected override simulateMousePress(
|
||||
element: HTMLElement, init: PointerEventInit = {}) {
|
||||
super.simulateMousePress(element, init);
|
||||
// advance beyond RAF, which is used by the element's pointerDown handler.
|
||||
jasmine.clock().tick(1);
|
||||
}
|
||||
}
|
||||
|
@ -266,17 +266,18 @@ $_md-sys-shape: tokens.md-sys-shape-values();
|
||||
background: var(--_disabled-handle-color);
|
||||
}
|
||||
|
||||
.input.b:focus ~ .handleContainer .handle.b > slot > .handleNub,
|
||||
.input.a:focus ~ .handleContainer .handle.a > slot > .handleNub {
|
||||
input.b:focus ~ .handleContainerPadded .handle.b > .handleNub,
|
||||
input.a:focus ~ .handleContainerPadded .handle.a > .handleNub {
|
||||
background: var(--_focus-handle-color);
|
||||
}
|
||||
|
||||
// prefix classes exist to overcome specificity of focus styling.
|
||||
.container > .handleContainer .handle.hover > slot > .handleNub {
|
||||
.container > .handleContainerPadded .handle.hover > .handleNub {
|
||||
background: var(--_hover-handle-color);
|
||||
}
|
||||
|
||||
.container > .handleContainer .handle.pressed > slot > .handleNub {
|
||||
input.b:active ~ .handleContainerPadded .handle.b > .handleNub,
|
||||
input.a:active ~ .handleContainerPadded .handle.a > .handleNub {
|
||||
background: var(--_pressed-handle-color);
|
||||
}
|
||||
|
||||
@ -312,9 +313,8 @@ $_md-sys-shape: tokens.md-sys-shape-values();
|
||||
min-inline-size: var(--_label-container-height);
|
||||
min-block-size: var(--_label-container-height);
|
||||
background: var(--_label-container-color);
|
||||
transition-property: transform;
|
||||
transition-duration: map.get($_md-sys-motion, 'duration-short2');
|
||||
transition-timing-function: map.get($_md-sys-motion, 'easing-emphasized');
|
||||
transition: transform map.get($_md-sys-motion, 'duration-short2')
|
||||
map.get($_md-sys-motion, 'easing-emphasized');
|
||||
transform-origin: center bottom;
|
||||
transform: scale(0);
|
||||
}
|
||||
@ -387,8 +387,11 @@ $_md-sys-shape: tokens.md-sys-shape-values();
|
||||
::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
// note, this is sized to align with thumb but is 0 width so that
|
||||
// fine adjustments are possible
|
||||
block-size: var(--_state-layer-size);
|
||||
inline-size: var(--_state-layer-size);
|
||||
transform: scaleX(0);
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
@ -397,6 +400,7 @@ $_md-sys-shape: tokens.md-sys-shape-values();
|
||||
appearance: none;
|
||||
block-size: var(--_state-layer-size);
|
||||
inline-size: var(--_state-layer-size);
|
||||
transform: scaleX(0);
|
||||
opacity: 0;
|
||||
z-index: 2;
|
||||
}
|
||||
|
@ -201,8 +201,6 @@ export class Slider extends LitElement {
|
||||
// interaction targets.
|
||||
@state() private handleAHover = false;
|
||||
@state() private handleBHover = false;
|
||||
@state() private handleAPressed = false;
|
||||
@state() private handleBPressed = false;
|
||||
|
||||
@state() private onTopId = 'b';
|
||||
@state() private handlesOverlapping = false;
|
||||
@ -323,7 +321,6 @@ export class Slider extends LitElement {
|
||||
focusRequested: this.focusRingARequested,
|
||||
showFocus: this.focusRingAShowing,
|
||||
hover: this.handleAHover,
|
||||
pressed: this.handleAPressed,
|
||||
label: labelA
|
||||
};
|
||||
|
||||
@ -334,7 +331,6 @@ export class Slider extends LitElement {
|
||||
focusRequested: this.focusRingBRequested,
|
||||
showFocus: this.focusRingBShowing,
|
||||
hover: this.handleBHover,
|
||||
pressed: this.handleBPressed,
|
||||
label: labelB
|
||||
};
|
||||
|
||||
@ -363,10 +359,7 @@ export class Slider extends LitElement {
|
||||
|
||||
protected renderTrack() {
|
||||
const trackClasses = {'tickMarks': this.withTickMarks};
|
||||
return html`
|
||||
<slot name="track">
|
||||
<div class="track ${classMap(trackClasses)}"></div>
|
||||
</slot>`;
|
||||
return html`<div class="track ${classMap(trackClasses)}"></div>`;
|
||||
}
|
||||
|
||||
protected renderFocusRing(visible: boolean) {
|
||||
@ -379,41 +372,27 @@ export class Slider extends LitElement {
|
||||
</div>`;
|
||||
}
|
||||
|
||||
protected renderHandle({
|
||||
id,
|
||||
lesser,
|
||||
showRipple,
|
||||
focusRequested,
|
||||
showFocus,
|
||||
hover,
|
||||
pressed,
|
||||
label
|
||||
}: {
|
||||
id: string,
|
||||
lesser: boolean,
|
||||
focusRequested: boolean,
|
||||
showRipple: boolean,
|
||||
showFocus: boolean,
|
||||
hover: boolean,
|
||||
pressed: boolean,
|
||||
label: string
|
||||
}) {
|
||||
protected renderHandle(
|
||||
{id, lesser, showRipple, focusRequested, showFocus, hover, label}: {
|
||||
id: string,
|
||||
lesser: boolean,
|
||||
focusRequested: boolean,
|
||||
showRipple: boolean,
|
||||
showFocus: boolean,
|
||||
hover: boolean,
|
||||
label: string
|
||||
}) {
|
||||
const onTop = !this.disabled && id === this.onTopId;
|
||||
const isOverlapping = !this.disabled && this.handlesOverlapping;
|
||||
return html`<div class="handle ${classMap({
|
||||
[id]: true,
|
||||
lesser,
|
||||
hover,
|
||||
pressed,
|
||||
onTop,
|
||||
isOverlapping
|
||||
})}">
|
||||
<slot name="handle${
|
||||
this.allowRange ? (lesser ? 'Lesser' : 'Greater') : ''}">
|
||||
<div class="handleNub"><md-elevation></md-elevation></div>
|
||||
${when(this.withLabel, () => this.renderLabel(label))}
|
||||
|
||||
</slot>
|
||||
${when(showRipple, () => this.renderRipple(id))}
|
||||
${when(focusRequested, () => this.renderFocusRing(showFocus))}
|
||||
</div>`;
|
||||
@ -437,7 +416,6 @@ export class Slider extends LitElement {
|
||||
@focus=${this.handleFocus}
|
||||
@blur=${this.handleBlur}
|
||||
@pointerdown=${this.handleDown}
|
||||
@pointerup=${this.handleUp}
|
||||
@pointerenter=${this.handleEnter}
|
||||
@pointermove=${this.handleMove}
|
||||
@pointerleave=${this.handleLeave}
|
||||
@ -517,18 +495,17 @@ export class Slider extends LitElement {
|
||||
pointerPress();
|
||||
this.ripplePointerId = e.pointerId;
|
||||
const isA = this.isEventOnA(e);
|
||||
const isPrimaryButton = Boolean(e.buttons & 1);
|
||||
// Since handle moves to pointer on down and there may not be a move,
|
||||
// it needs to be considered hovered..
|
||||
this.handleAHover = !this.disabled && isA && Boolean(this.handleA);
|
||||
this.handleAPressed = isPrimaryButton && this.handleAHover;
|
||||
this.handleBHover = !this.disabled && !isA && Boolean(this.handleB);
|
||||
this.handleBPressed = isPrimaryButton && this.handleBHover;
|
||||
this.updateFocusVisible(e);
|
||||
}
|
||||
|
||||
protected handleUp() {
|
||||
this.handleAPressed = this.handleBPressed = false;
|
||||
// Force Safari to focus input so the label stays displayed; note,
|
||||
// Macs don't normally focus non-text type inputs.
|
||||
const target = (e.target as HTMLElement);
|
||||
requestAnimationFrame(() => {
|
||||
target.focus();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -568,7 +545,7 @@ export class Slider extends LitElement {
|
||||
}
|
||||
this.valueB = this.inputB.valueAsNumber;
|
||||
this.updateOnTop(e);
|
||||
// update value only on interaction
|
||||
// update value only on interaction
|
||||
const lower = Math.min(this.valueA, this.valueB);
|
||||
const upper = Math.max(this.valueA, this.valueB);
|
||||
this.value = this.allowRange ? [lower, upper] : this.valueB;
|
||||
|
Loading…
Reference in New Issue
Block a user