Add a toggle component
This commit is contained in:
parent
92553cb1f1
commit
6e2dfa1cf1
5 changed files with 165 additions and 3 deletions
|
|
@ -26,10 +26,13 @@ export function StyledShadowElement(Base) {
|
||||||
/** @type {ShadowRoot} */
|
/** @type {ShadowRoot} */
|
||||||
_shadow;
|
_shadow;
|
||||||
|
|
||||||
constructor() {
|
constructor({focusable = false} = {}) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this._shadow = this.attachShadow({ mode: `open` });
|
this._shadow = this.attachShadow({
|
||||||
|
mode: `open`,
|
||||||
|
delegatesFocus: focusable,
|
||||||
|
});
|
||||||
this._style = document.createElement(`style`);
|
this._style = document.createElement(`style`);
|
||||||
this._shadow.appendChild(this._style);
|
this._shadow.appendChild(this._style);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
97
module/apps/elements/Toggle.mjs
Normal file
97
module/apps/elements/Toggle.mjs
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
import { StyledShadowElement } from "./StyledShadowElement.mjs";
|
||||||
|
|
||||||
|
export class TafToggle extends StyledShadowElement(HTMLElement) {
|
||||||
|
static elementName = `taf-toggle`;
|
||||||
|
|
||||||
|
static _stylePath = `toggle.css`;
|
||||||
|
|
||||||
|
_mounted;
|
||||||
|
_internals;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super({ focusable: true });
|
||||||
|
|
||||||
|
this._internals = this.attachInternals();
|
||||||
|
this._internals.role = `checkbox`;
|
||||||
|
};
|
||||||
|
|
||||||
|
get type() {
|
||||||
|
return `checkbox`;
|
||||||
|
};
|
||||||
|
|
||||||
|
get name() {
|
||||||
|
return this.getAttribute(`name`);
|
||||||
|
};
|
||||||
|
set name(newName) {
|
||||||
|
this.setAttribute(`name`, newName);
|
||||||
|
};
|
||||||
|
|
||||||
|
get value() {
|
||||||
|
return this._input.value;
|
||||||
|
};
|
||||||
|
set value(newValue) {
|
||||||
|
this._input.value = newValue;
|
||||||
|
};
|
||||||
|
|
||||||
|
get checked() {
|
||||||
|
return this.hasAttribute(`checked`);
|
||||||
|
};
|
||||||
|
set checked(newValue) {
|
||||||
|
if (typeof newValue !== `boolean`) { return };
|
||||||
|
this.toggleAttribute(`checked`, newValue);
|
||||||
|
};
|
||||||
|
|
||||||
|
get disabled() {
|
||||||
|
return this.matches(`:disabled`);
|
||||||
|
};
|
||||||
|
set disabled(value) {
|
||||||
|
this.toggleAttribute(`disabled`, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
get editable() {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
connectedCallback() {
|
||||||
|
super.connectedCallback();
|
||||||
|
if (this._mounted) { return };
|
||||||
|
|
||||||
|
this._internals.checked = this.checked;
|
||||||
|
|
||||||
|
/*
|
||||||
|
This converts all of the double-dash prefixed properties on the
|
||||||
|
element to CSS variables so that they don't all need to be
|
||||||
|
provided by doing style=""
|
||||||
|
*/
|
||||||
|
for (const attrVar of this.attributes) {
|
||||||
|
if (attrVar.name?.startsWith(`var:`)) {
|
||||||
|
const prop = attrVar.name.replace(`var:`, ``);
|
||||||
|
this.style.setProperty(`--` + prop, attrVar.value);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const label = document.createElement(`label`);
|
||||||
|
label.dataset.type = `round`;
|
||||||
|
|
||||||
|
const input = document.createElement(`input`);
|
||||||
|
input.type = `checkbox`;
|
||||||
|
input.toggleAttribute(`switch`, true);
|
||||||
|
input.checked = this.checked;
|
||||||
|
|
||||||
|
label.appendChild(input);
|
||||||
|
|
||||||
|
const slider = document.createElement(`div`);
|
||||||
|
slider.classList = `slider`;
|
||||||
|
label.appendChild(slider);
|
||||||
|
|
||||||
|
this._shadow.appendChild(label);
|
||||||
|
|
||||||
|
this._mounted = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
disconnectedCallback() {
|
||||||
|
super.disconnectedCallback();
|
||||||
|
if (!this._mounted) { return };
|
||||||
|
this._mounted = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
import { Logger } from "../../utils/Logger.mjs";
|
import { Logger } from "../../utils/Logger.mjs";
|
||||||
import { TafIcon } from "./Icon.mjs";
|
import { TafIcon } from "./Icon.mjs";
|
||||||
import { TafSVGLoader } from "./svgLoader.mjs";
|
import { TafSVGLoader } from "./svgLoader.mjs";
|
||||||
|
import { TafToggle } from "./Toggle.mjs";
|
||||||
|
|
||||||
const components = [
|
const components = [
|
||||||
TafSVGLoader,
|
TafSVGLoader,
|
||||||
TafIcon,
|
TafIcon,
|
||||||
|
TafToggle,
|
||||||
];
|
];
|
||||||
|
|
||||||
export function registerCustomComponents() {
|
export function registerCustomComponents() {
|
||||||
|
|
|
||||||
55
styles/components/toggle.css
Normal file
55
styles/components/toggle.css
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
:host {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.slider {
|
||||||
|
width: var(--size, 16px);
|
||||||
|
height: var(--size, 16px);
|
||||||
|
background: var(
|
||||||
|
--slider-colour,
|
||||||
|
var(--toggle-slider-unchecked-colour)
|
||||||
|
);
|
||||||
|
transition: all var(--speed, 150ms) ease-in-out;
|
||||||
|
border-radius: 9999px;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
padding: var(--padding, 4px);
|
||||||
|
height: calc(var(--size, 16px) + (var(--padding, 4px) * 2));
|
||||||
|
width: calc((var(--size, 16px) * 2) + (var(--padding, 4px) * 2));
|
||||||
|
border-radius: 9999px;
|
||||||
|
background: var(
|
||||||
|
--toggle-background,
|
||||||
|
var(--toggle-background-colour)
|
||||||
|
);
|
||||||
|
box-sizing: border-box;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
/* Non-checked, clicking */
|
||||||
|
&:active .slider {
|
||||||
|
width: calc(var(--size, 16px) * 1.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* checked, non-clicking */
|
||||||
|
& > :checked + .slider {
|
||||||
|
transform: translateX(var(--size, 16px));
|
||||||
|
background: var(
|
||||||
|
--slider-checked-colour,
|
||||||
|
var(--toggle-slider-checked-colour)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* checked, clicking */
|
||||||
|
&:active > :checked + .slider {
|
||||||
|
width: calc(var(--size, 16px) * 1.5);
|
||||||
|
transform: translateX(calc(var(--size, 16px) * 0.5));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,10 @@
|
||||||
--spinner-outer-colour: white;
|
--spinner-outer-colour: white;
|
||||||
--spinner-inner-colour: #FF3D00;
|
--spinner-inner-colour: #FF3D00;
|
||||||
|
|
||||||
|
--toggle-background-colour: #171e26;
|
||||||
|
--toggle-slider-unchecked-colour: maroon;
|
||||||
|
--toggle-slider-checked-colour: green;
|
||||||
|
|
||||||
--tab-button-active-border: rebeccapurple;
|
--tab-button-active-border: rebeccapurple;
|
||||||
--tab-button-hover-bg: var(--color-cool-3);
|
--tab-button-hover-bg: var(--color-cool-3);
|
||||||
|
|
||||||
|
|
@ -19,7 +23,8 @@
|
||||||
--item-card-header-background: #242d38;
|
--item-card-header-background: #242d38;
|
||||||
--item-card-header-color: white;
|
--item-card-header-color: white;
|
||||||
--item-card-header-input-background: #2b3642;
|
--item-card-header-input-background: #2b3642;
|
||||||
--item-card-header-input-color: white;
|
--item-card-header-input-colour: white;
|
||||||
|
--item-card-header-disabled-input-colour: gray;
|
||||||
|
|
||||||
/* Chip Variables */
|
/* Chip Variables */
|
||||||
--chip-color: #fff7ed;
|
--chip-color: #fff7ed;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue