Skip to content

Commit

Permalink
feat(switch): add required and form validity
Browse files Browse the repository at this point in the history
Swapped switch's interactive element back to an `<input>` to more easily support platform validation messages.

PiperOrigin-RevId: 559671594
  • Loading branch information
asyncLiz authored and copybara-github committed Aug 24, 2023
1 parent b542d2a commit 9694191
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 120 deletions.
2 changes: 1 addition & 1 deletion switch/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ import {Switch} from './internal/switch.js';
export class SwitchHarness extends Harness<Switch> {
protected override async getInteractiveElement() {
await this.element.updateComplete;
return this.element.renderRoot.querySelector<HTMLElement>('.switch')!;
return this.element.renderRoot.querySelector('input')!;
}
}
40 changes: 20 additions & 20 deletions switch/internal/_handle.scss
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ $_easing-standard: map.get($_md-sys-motion, 'easing-standard');

$margin: calc(var(--_track-width) - var(--_track-height));

.switch--selected .handle-container {
.selected .handle-container {
margin-inline-start: $margin;
}

.switch--unselected .handle-container {
.unselected .handle-container {
margin-inline-end: $margin;
}

.switch:disabled .handle-container {
.disabled .handle-container {
transition: none;
}

Expand Down Expand Up @@ -63,12 +63,12 @@ $_easing-standard: map.get($_md-sys-motion, 'easing-standard');
transition: background-color 67ms linear;
}

.switch:disabled .handle,
.switch:disabled .handle::before {
.disabled .handle,
.disabled .handle::before {
transition: none;
}

.switch--selected .handle {
.selected .handle {
height: var(--_selected-handle-height);
width: var(--_selected-handle-width);
}
Expand All @@ -78,52 +78,52 @@ $_easing-standard: map.get($_md-sys-motion, 'easing-standard');
width: var(--_with-icon-handle-width);
}

.switch--selected:enabled:active .handle,
.switch--unselected:enabled:active .handle {
.selected:not(.disabled):active .handle,
.unselected:not(.disabled):active .handle {
height: var(--_pressed-handle-height);
width: var(--_pressed-handle-width);
transition-timing-function: linear;
transition-duration: 100ms;
}

.switch--selected .handle::before {
.selected .handle::before {
background-color: var(--_selected-handle-color);
}

.switch--selected:hover .handle::before {
.selected:hover .handle::before {
background-color: var(--_selected-hover-handle-color);
}

.switch--selected:focus-within .handle::before {
.selected:focus-within .handle::before {
background-color: var(--_selected-focus-handle-color);
}

.switch--selected:active .handle::before {
.selected:active .handle::before {
background-color: var(--_selected-pressed-handle-color);
}

.switch--selected:disabled .handle::before {
.selected.disabled .handle::before {
background-color: var(--_disabled-selected-handle-color);
opacity: var(--_disabled-selected-handle-opacity);
}

.switch--unselected .handle::before {
.unselected .handle::before {
background-color: var(--_handle-color);
}

.switch--unselected:hover .handle::before {
.unselected:hover .handle::before {
background-color: var(--_hover-handle-color);
}

.switch--unselected:focus-within .handle::before {
.unselected:focus-within .handle::before {
background-color: var(--_focus-handle-color);
}

.switch--unselected:active .handle::before {
.unselected:active .handle::before {
background-color: var(--_pressed-handle-color);
}

.switch--unselected:disabled .handle::before {
.unselected.disabled .handle::before {
background-color: var(--_disabled-handle-color);
opacity: var(--_disabled-handle-opacity);
}
Expand All @@ -135,7 +135,7 @@ $_easing-standard: map.get($_md-sys-motion, 'easing-standard');
width: var(--_state-layer-size);
}

.switch--selected md-ripple {
.selected md-ripple {
@include ripple.theme(
(
'hover-color': var(--_selected-hover-state-layer-color),
Expand All @@ -146,7 +146,7 @@ $_easing-standard: map.get($_md-sys-motion, 'easing-standard');
);
}

.switch--unselected md-ripple {
.unselected md-ripple {
@include ripple.theme(
(
'hover-color': var(--_hover-state-layer-color),
Expand Down
24 changes: 12 additions & 12 deletions switch/internal/_icon.scss
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,17 @@ $_easing-standard: map.get($_md-sys-motion, 'easing-standard');
opacity: 0;
}

.switch:disabled .icon {
.disabled .icon {
transition: none;
}

.switch--selected .icon--on,
.switch--unselected .icon--off {
.selected .icon--on,
.unselected .icon--off {
opacity: 1;
}

// rotate selected icon into view when there is no unselected icon
.switch--unselected .handle:not(.with-icon) .icon--on {
.unselected .handle:not(.with-icon) .icon--on {
transform: rotate(-45deg);
}

Expand All @@ -50,19 +50,19 @@ $_easing-standard: map.get($_md-sys-motion, 'easing-standard');
fill: var(--_icon-color);
}

.switch--unselected:hover .icon--off {
.unselected:hover .icon--off {
fill: var(--_hover-icon-color);
}

.switch--unselected:focus-within .icon--off {
.unselected:focus-within .icon--off {
fill: var(--_focus-icon-color);
}

.switch--unselected:active .icon--off {
.unselected:active .icon--off {
fill: var(--_pressed-icon-color);
}

.switch--unselected:disabled .icon--off {
.unselected.disabled .icon--off {
fill: var(--_disabled-icon-color);
opacity: var(--_disabled-icon-opacity);
}
Expand All @@ -73,19 +73,19 @@ $_easing-standard: map.get($_md-sys-motion, 'easing-standard');
fill: var(--_selected-icon-color);
}

.switch--selected:hover .icon--on {
.selected:hover .icon--on {
fill: var(--_selected-hover-icon-color);
}

.switch--selected:focus-within .icon--on {
.selected:focus-within .icon--on {
fill: var(--_selected-focus-icon-color);
}

.switch--selected:active .icon--on {
.selected:active .icon--on {
fill: var(--_selected-pressed-icon-color);
}

.switch--selected:disabled .icon--on {
.selected.disabled .icon--on {
fill: var(--_disabled-selected-icon-color);
opacity: var(--_disabled-selected-icon-opacity);
}
Expand Down
30 changes: 11 additions & 19 deletions switch/internal/_switch.scss
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,8 @@

.switch {
align-items: center;
background: none;
border: none;
cursor: pointer;
display: inline-flex;
flex-shrink: 0; // Stop from collapsing in flex containers
margin: 0;
outline: none;
padding: 0;
position: relative;
width: var(--_track-width);
height: var(--_track-height);
Expand All @@ -125,34 +119,32 @@
border-end-start-radius: var(--_track-shape-end-start);
}

// Touch target
.touch {
position: absolute;
// Input is also touch target
input {
appearance: none;
height: 48px;
outline: none;
margin: 0;
position: absolute;
width: 100%;
z-index: 1;
}

:host([touch-target='none']) .touch {
:host([touch-target='none']) input {
display: none;
}

// Disabled
.switch:disabled {
cursor: default;
pointer-events: none;
}

// Disabled - Track
.switch:disabled .track {
.disabled .track {
background-color: transparent;
border-color: transparent;
}

.switch:disabled .track::before {
.disabled .track::before {
background-clip: content-box;
}

.switch--selected:disabled .track {
.selected.disabled .track {
background-clip: border-box;
}

Expand Down
24 changes: 12 additions & 12 deletions switch/internal/_track.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,55 +36,55 @@
transition-duration: 67ms;
}

.switch:disabled .track::before,
.switch:disabled .track::after {
.disabled .track::before,
.disabled .track::after {
transition: none;
opacity: var(--_disabled-track-opacity);
}

.switch--selected .track::before {
.selected .track::before {
background-color: var(--_selected-track-color);
}

.switch--selected:hover .track::before {
.selected:hover .track::before {
background-color: var(--_selected-hover-track-color);
}

.switch--selected:focus-within .track::before {
.selected:focus-within .track::before {
background-color: var(--_selected-focus-track-color);
}

.switch--selected:active .track::before {
.selected:active .track::before {
background-color: var(--_selected-pressed-track-color);
}

.switch--selected:disabled .track::before {
.selected.disabled .track::before {
background-color: var(--_disabled-selected-track-color);
}

.switch--unselected .track::before {
.unselected .track::before {
background-color: var(--_track-color);
border-color: var(--_track-outline-color);
border-style: solid;
border-width: var(--_track-outline-width);
}

.switch--unselected:hover .track::before {
.unselected:hover .track::before {
background-color: var(--_hover-track-color);
border-color: var(--_hover-track-outline-color);
}

.switch--unselected:focus-visible .track::before {
.unselected:focus-visible .track::before {
background-color: var(--_focus-track-color);
border-color: var(--_focus-track-outline-color);
}

.switch--unselected:active .track::before {
.unselected:active .track::before {
background-color: var(--_pressed-track-color);
border-color: var(--_pressed-track-outline-color);
}

.switch--unselected:disabled .track::before {
.unselected.disabled .track::before {
background-color: var(--_disabled-track-color);
border-color: var(--_disabled-track-outline-color);
}
Expand Down
1 change: 1 addition & 0 deletions switch/internal/forced-colors-styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
'disabled-selected-icon-color': GrayText,
'disabled-selected-icon-opacity': 1,
'disabled-selected-track-color': GrayText,
'disabled-track-outline-color': GrayText,
'disabled-track-opacity': 1,
'disabled-handle-color': GrayText,
'disabled-handle-opacity': 1,
Expand Down
Loading

0 comments on commit 9694191

Please sign in to comment.