diff --git a/ui/npm-shrinkwrap.json b/ui/npm-shrinkwrap.json index ebb0104..9161148 100644 --- a/ui/npm-shrinkwrap.json +++ b/ui/npm-shrinkwrap.json @@ -1,12 +1,12 @@ { "name": "web-ui-boilerplate", - "version": "2.4.0", + "version": "2.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "web-ui-boilerplate", - "version": "2.4.0", + "version": "2.5", "license": "ISC", "dependencies": { "dialog-polyfill": "^0.5.6" diff --git a/ui/src/javascript/modules/toggle.ts b/ui/src/javascript/modules/toggle.ts deleted file mode 100644 index b5eef4c..0000000 --- a/ui/src/javascript/modules/toggle.ts +++ /dev/null @@ -1,31 +0,0 @@ -export default class Toggle { - private toggle: Element; - - constructor(toggle: Element) { - this.toggle = toggle; - - this.init(); - } - - public static start(): void { - const toggles = document.querySelectorAll('[role="switch"]'); - - toggles.forEach((toggle) => { - const instance = new Toggle(toggle); - return instance; - }); - } - - private init(): void { - this.toggle.addEventListener('click', () => this.handleClick()); - } - - private handleClick(): void { - const isChecked = this.toggle.getAttribute('aria-checked') === 'true'; - - this.toggle.setAttribute( - 'aria-checked', - Boolean(!isChecked).toString(), - ); - } -} diff --git a/ui/src/javascript/ui-init.ts b/ui/src/javascript/ui-init.ts index 36566ab..a449fb7 100644 --- a/ui/src/javascript/ui-init.ts +++ b/ui/src/javascript/ui-init.ts @@ -5,7 +5,6 @@ import RangeSlider from './modules/range-slider'; import Search from './modules/search'; import Slider from './modules/slider'; import Tabs from './modules/tabs'; -import Toggle from './modules/toggle'; import VideoPlayer from './modules/video-player'; // 2. For DEMO purposes only. @@ -18,6 +17,7 @@ import WebUIModal from './web-components/webui-modal'; import WebUINotify from './web-components/webui-notify'; import WebUIProse from './web-components/webui-prose'; import WebUIShare from './web-components/webui-share'; +import WebUIToggle from './web-components/webui-toggle'; export const uiInit = (): void => { FormValidate.start(); @@ -25,7 +25,6 @@ export const uiInit = (): void => { Search.start(); Slider.start(); Tabs.start(); - Toggle.start(); VideoPlayer.start(); // For DEMO purposes only. @@ -44,4 +43,6 @@ export const uiInit = (): void => { customElements.define('webui-prose', WebUIProse); !customElements.get('webui-share') && customElements.define('webui-share', WebUIShare); + !customElements.get('webui-toggle') && + customElements.define('webui-toggle', WebUIToggle); }; diff --git a/ui/src/javascript/web-components/webui-notify.ts b/ui/src/javascript/web-components/webui-notify.ts index 23e193b..009d21a 100644 --- a/ui/src/javascript/web-components/webui-notify.ts +++ b/ui/src/javascript/web-components/webui-notify.ts @@ -7,7 +7,7 @@ export default class WebUINotify extends HTMLElement { this.btnClose?.addEventListener('click', this); } - // Handle web component events from constructor(). + // Handle constructor() event listeners. handleEvent() { this.setAttribute('hidden', ''); } diff --git a/ui/src/javascript/web-components/webui-toggle.ts b/ui/src/javascript/web-components/webui-toggle.ts new file mode 100644 index 0000000..96f1744 --- /dev/null +++ b/ui/src/javascript/web-components/webui-toggle.ts @@ -0,0 +1,22 @@ +export default class WebUIToggle extends HTMLElement { + private switch: HTMLButtonElement | null; + + constructor() { + super(); + this.switch = this.querySelector('[role="switch"]'); + + if (!this.switch) return; + + this.switch.addEventListener('click', this); + } + + // Handle constructor() event listeners. + handleEvent() { + const isChecked = this.switch?.getAttribute('aria-checked') === 'true'; + + this.switch?.setAttribute( + 'aria-checked', + Boolean(!isChecked).toString(), + ); + } +} diff --git a/ui/src/stylesheets/components/_index.scss b/ui/src/stylesheets/components/_index.scss index d785660..c5c687a 100644 --- a/ui/src/stylesheets/components/_index.scss +++ b/ui/src/stylesheets/components/_index.scss @@ -16,5 +16,4 @@ @use 'slider'; @use 'tables'; @use 'tabs'; -@use 'toggle'; @use 'video-player'; diff --git a/ui/src/stylesheets/web-components/_index.scss b/ui/src/stylesheets/web-components/_index.scss index e127301..d54debb 100644 --- a/ui/src/stylesheets/web-components/_index.scss +++ b/ui/src/stylesheets/web-components/_index.scss @@ -4,3 +4,4 @@ @use 'webui-notify'; @use 'webui-prose'; @use 'webui-share'; +@use 'webui-toggle'; diff --git a/ui/src/stylesheets/components/_toggle.scss b/ui/src/stylesheets/web-components/_webui-toggle.scss similarity index 66% rename from ui/src/stylesheets/components/_toggle.scss rename to ui/src/stylesheets/web-components/_webui-toggle.scss index 21b50de..2628e4f 100644 --- a/ui/src/stylesheets/components/_toggle.scss +++ b/ui/src/stylesheets/web-components/_webui-toggle.scss @@ -6,34 +6,36 @@ Dependencies. @use '../base' as *; // @use '../mixins' as *; -.toggle { - align-items: center; - border: $border-width-s solid; - display: inline-flex; - padding: 0; +webui-toggle { + [role='switch'] { + align-items: center; + border: $border-width-s solid; + display: inline-flex; + padding: 0; - :is(&__on, &__off) { - padding: $gutter-s; - } - - &:active { - transform: none; + &:active { + transform: none; + } } - &[aria-checked='false'] { + [aria-checked='false'] { .toggle__off { background-color: hsl(var(--color-text) / 30%); } } - &[aria-checked='true'] { + [aria-checked='true'] { .toggle__on { background-color: $color-brand; color: $color-neutral-100; } } - &--has-label { + :is(.toggle__on, .toggle__off) { + padding: $gutter-s; + } + + .toggle--has-label { border: 0; gap: $gutter-s; diff --git a/ui/stories/5. Components/Toggle/Toggle.js b/ui/stories/5. Components/Toggle/Toggle.js deleted file mode 100644 index 0b56f27..0000000 --- a/ui/stories/5. Components/Toggle/Toggle.js +++ /dev/null @@ -1,27 +0,0 @@ -export const ToggleHtml = () => ` - -`; - -export const ToggleWithLabelHtml = () => ` - -`; diff --git a/ui/stories/5. Components/Toggle/Toggle.stories.js b/ui/stories/5. Components/Toggle/Toggle.stories.js deleted file mode 100644 index 9a1d951..0000000 --- a/ui/stories/5. Components/Toggle/Toggle.stories.js +++ /dev/null @@ -1,18 +0,0 @@ -import { ToggleHtml, ToggleWithLabelHtml } from './Toggle'; -export default { - title: 'Components/Toggle (Or Switch)', - parameters: { - status: { - type: 'stable', - }, - }, -}; - -export const Toggle = { - render: () => ToggleHtml(), -}; - -export const ToggleWithLabel = { - render: () => ToggleWithLabelHtml(), -}; -ToggleWithLabel.storyName = 'Toggle With Visible Label'; diff --git a/ui/stories/6. Web Components Or Custom Elements/WebUIProse/WebUIProse.stories.js b/ui/stories/6. Web Components Or Custom Elements/WebUIProse/WebUIProse.stories.js index 4e3dfe6..9668abd 100644 --- a/ui/stories/6. Web Components Or Custom Elements/WebUIProse/WebUIProse.stories.js +++ b/ui/stories/6. Web Components Or Custom Elements/WebUIProse/WebUIProse.stories.js @@ -11,3 +11,4 @@ export default { export const WebUIProse = { render: () => WebUIProseHtml(), }; +WebUIProse.storyName = ''; diff --git a/ui/stories/6. Web Components Or Custom Elements/WebUIToggle/WebUIToggle.js b/ui/stories/6. Web Components Or Custom Elements/WebUIToggle/WebUIToggle.js new file mode 100644 index 0000000..8f1a022 --- /dev/null +++ b/ui/stories/6. Web Components Or Custom Elements/WebUIToggle/WebUIToggle.js @@ -0,0 +1,31 @@ +export const WebUIToggleHtml = () => ` + + + +`; + +export const WebUIToggleWithLabelHtml = () => ` + + + +`; diff --git a/ui/stories/5. Components/Toggle/Toggle.mdx b/ui/stories/6. Web Components Or Custom Elements/WebUIToggle/WebUIToggle.mdx similarity index 62% rename from ui/stories/5. Components/Toggle/Toggle.mdx rename to ui/stories/6. Web Components Or Custom Elements/WebUIToggle/WebUIToggle.mdx index b9b2d4c..464b45e 100644 --- a/ui/stories/5. Components/Toggle/Toggle.mdx +++ b/ui/stories/6. Web Components Or Custom Elements/WebUIToggle/WebUIToggle.mdx @@ -1,15 +1,16 @@ import { Meta, Canvas } from '@storybook/blocks'; -import * as Toggle from './Toggle.stories'; +import * as WebUIToggle from './WebUIToggle.stories'; - + -# Toggle button (or switch) +# `` +- Toggle button (or switch) ## Accessibility considerations - See the [ARIA APG switch pattern](https://www.w3.org/WAI/ARIA/apg/patterns/switch/examples/switch-button/) and [Inclusive Components toggle](https://inclusive-components.design/toggle-button/) examples. ## Toggle with no visible label - + ## Toggle with visible label - + diff --git a/ui/stories/6. Web Components Or Custom Elements/WebUIToggle/WebUIToggle.stories.js b/ui/stories/6. Web Components Or Custom Elements/WebUIToggle/WebUIToggle.stories.js new file mode 100644 index 0000000..c3bcbd5 --- /dev/null +++ b/ui/stories/6. Web Components Or Custom Elements/WebUIToggle/WebUIToggle.stories.js @@ -0,0 +1,19 @@ +import { WebUIToggleHtml, WebUIToggleWithLabelHtml } from './WebUIToggle'; +export default { + title: 'Web Components Or Custom Elements/', + parameters: { + status: { + type: 'stable', + }, + }, +}; + +export const WebUIToggle = { + render: () => WebUIToggleHtml(), +}; +WebUIToggle.storyName = ''; + +export const WebUIToggleWithLabel = { + render: () => WebUIToggleWithLabelHtml(), +}; +WebUIToggleWithLabel.storyName = ' With Visible Label';