@decidables/decidables-elements
Version:
decidables-elements: Basic UI Web Components for the decidables project
181 lines (135 loc) • 4.25 kB
JavaScript
import {css, html} from 'lit';
import DecidablesElement from './decidables-element';
export default class DecidablesSwitch extends DecidablesElement {
static get properties() {
return {
checked: {
attribute: 'checked',
type: Boolean,
reflect: true,
},
disabled: {
attribute: 'disabled',
type: Boolean,
reflect: true,
},
};
}
constructor() {
super();
// Attributes
this.checked = false;
this.disabled = false;
}
changed(event) {
this.checked = event.target.checked;
this.dispatchEvent(new CustomEvent('change', {
detail: {
checked: this.checked,
},
bubbles: true,
}));
}
static get styles() {
return [
super.styles,
css`
:host {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
/* Adapted from https://codepen.io/guuslieben/pen/YyPRVP */
input[type=checkbox] {
/* visuallyhidden: https://github.com/h5bp/html5-boilerplate/blob/master/dist/doc/css.md */
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
white-space: nowrap;
border: 0;
clip-path: inset(100%); /* May cause a performance issue: https://github.com/h5bp/html5-boilerplate/issues/2021 */
}
input[type=checkbox] + label {
order: 1;
margin: 0 0.25rem 0.25rem;
font-weight: 400;
}
input[type=checkbox] + label + label {
position: relative;
min-width: 24px;
padding: 0 0 36px;
margin: 0.25rem 0.25rem 0;
font-weight: 400;
outline: none;
}
input[type=checkbox] + label + label::before,
input[type=checkbox] + label + label::after {
position: absolute;
left: 50%;
margin: 0;
outline: 0;
content: "";
transform: translate(-50%, 0);
transition: all var(---transition-duration) ease;
}
input[type=checkbox] + label + label::before {
bottom: 1px;
width: 8px;
height: 34px;
background-color: var(---color-element-disabled);
border-radius: 4px;
}
input[type=checkbox] + label + label::after {
bottom: 0;
width: 18px;
height: 18px;
background-color: var(---color-element-enabled);
border-radius: 50%;
box-shadow: var(---shadow-2);
}
input[type=checkbox]:checked + label + label::after {
transform: translate(-50%, -100%);
}
input[type=checkbox]:disabled + label + label::after {
background-color: var(---color-element-disabled);
box-shadow: none;
}
input[type=checkbox]:enabled + label,
input[type=checkbox]:enabled + label + label {
cursor: pointer;
}
input[type=checkbox]:enabled + label:hover + label::after,
input[type=checkbox]:enabled + label + label:hover::after {
box-shadow: var(---shadow-4);
}
input[type=checkbox]:enabled + label:active + label::after,
input[type=checkbox]:enabled + label + label:active::after {
box-shadow: var(---shadow-8);
}
input[type=checkbox]:enabled:focus-visible + label + label::after {
box-shadow: var(---shadow-4);
}
input[type=checkbox]:enabled:focus-visible + label + label:active::after,
input[type=checkbox]:enabled:focus-visible:active + label + label::after {
box-shadow: var(---shadow-8);
}
`,
];
}
render() {
return html`
<input type="checkbox" id="switch" ?checked=${this.checked} ?disabled=${this.disabled} @change=${this.changed.bind(this)}>
<label for="switch">
<slot name="off-label"></slot>
</label>
<label for="switch">
<slot></slot>
</label>
`;
}
}
customElements.define('decidables-switch', DecidablesSwitch);