UNPKG

@limetech/lime-elements

Version:
275 lines (274 loc) • 10.4 kB
import { h, Host, } from "@stencil/core"; import { createRandomString } from "../../util/random-string"; import { makeEnterClickable, removeEnterClickable, } from "../../util/make-enter-clickable"; /** * The Switch component is a fundamental element in UI design that serves as a toggle switch * to control the state of a specific setting or option in an application or website. * The two distinct positions of the Switch are visually indicative of the two states: * ON and OFF; making it easy for users to understand the current state of the controlled feature. * * The Switch component is widely used in user interfaces to enable users to * quickly and intuitively change binary settings. * * :::important * Checkboxes are sometimes used interchangeably with switches in user interfaces. * But there is an important difference between the two! Please read our guidelines about * [Switch vs. Checkbox](#/DesignGuidelines/switch-vs-checkbox.md/). * * @exampleComponent limel-example-switch-basic * @exampleComponent limel-example-switch-helper-text * @exampleComponent limel-example-switch-readonly */ export class Switch { constructor() { /** * Disables the switch when `true`, * and visually shows that the switch is editable but disabled. * This tells the users that if certain requirements are met, * the switch may become interactable. */ this.disabled = false; /** * Disables the switch when `true`. This visualizes the switch slightly differently. * But shows no visual sign indicating that the switch is disabled * or can ever become interactable. */ this.readonly = false; /** * The value of the switch */ this.value = false; /** * The labels to use to clarify what kind of data is being visualized, * when the component is `readonly`. */ this.readonlyLabels = []; this.helperTextId = createRandomString(); this.fieldId = createRandomString(); this.renderReadonly = () => { const icon = this.value ? { name: 'ok', color: 'var(--lime-primary-color, var(--limel-theme-primary-color))', } : 'minus'; return (h("limel-dynamic-label", { value: this.value, "aria-describedby": this.ariaDescribedBy, defaultLabel: { text: this.label, icon: icon }, labels: this.readonlyLabels })); }; this.renderInteractive = () => { return (h("div", { class: "switch" }, h("button", { id: this.fieldId, type: "button", role: "switch", "aria-checked": String(this.value), disabled: this.disabled, onClick: this.handleClick, "aria-describedby": this.ariaDescribedBy }, h("span", { class: "handle" })), h("label", { htmlFor: this.fieldId }, this.label))); }; this.renderHelperLine = () => { if (!this.hasHelperText()) { return; } return (h("limel-helper-line", { helperTextId: this.helperTextId, helperText: this.helperText, invalid: this.invalid })); }; this.hasHelperText = () => { return this.helperText !== null && this.helperText !== undefined; }; this.handleClick = (event) => { event.stopPropagation(); this.change.emit(!this.value); }; } componentWillLoad() { makeEnterClickable(this.host); } disconnectedCallback() { removeEnterClickable(this.host); } render() { return (h(Host, { key: '4adc29ba50c4e06948efef7b922c0fb70bb58ecb' }, this.readonly ? this.renderReadonly() : this.renderInteractive(), this.renderHelperLine())); } get ariaDescribedBy() { return this.helperText ? this.helperTextId : undefined; } static get is() { return "limel-switch"; } static get encapsulation() { return "shadow"; } static get originalStyleUrls() { return { "$": ["switch.scss"] }; } static get styleUrls() { return { "$": ["switch.css"] }; } static get properties() { return { "label": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Label to display next to the switch" }, "getter": false, "setter": false, "reflect": true, "attribute": "label" }, "disabled": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Disables the switch when `true`,\nand visually shows that the switch is editable but disabled.\nThis tells the users that if certain requirements are met,\nthe switch may become interactable." }, "getter": false, "setter": false, "reflect": true, "attribute": "disabled", "defaultValue": "false" }, "readonly": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Disables the switch when `true`. This visualizes the switch slightly differently.\nBut shows no visual sign indicating that the switch is disabled\nor can ever become interactable." }, "getter": false, "setter": false, "reflect": true, "attribute": "readonly", "defaultValue": "false" }, "invalid": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Set to `true` to indicate that the current value is invalid." }, "getter": false, "setter": false, "reflect": true, "attribute": "invalid" }, "value": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The value of the switch" }, "getter": false, "setter": false, "reflect": true, "attribute": "value", "defaultValue": "false" }, "helperText": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Optional helper text to display below the switch" }, "getter": false, "setter": false, "reflect": true, "attribute": "helper-text" }, "readonlyLabels": { "type": "unknown", "mutable": false, "complexType": { "original": "Array<Label<boolean>>", "resolved": "Label<boolean>[]", "references": { "Array": { "location": "global", "id": "global::Array" }, "Label": { "location": "import", "path": "../dynamic-label/label.types", "id": "src/components/dynamic-label/label.types.ts::Label", "referenceLocation": "Label" } } }, "required": false, "optional": true, "docs": { "tags": [], "text": "The labels to use to clarify what kind of data is being visualized,\nwhen the component is `readonly`." }, "getter": false, "setter": false, "defaultValue": "[]" } }; } static get states() { return { "fieldId": {} }; } static get events() { return [{ "method": "change", "name": "change", "bubbles": true, "cancelable": true, "composed": true, "docs": { "tags": [], "text": "Emitted when the value has changed" }, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} } }]; } static get elementRef() { return "host"; } }