fix: improve docs and examples for accordion & switch

This commit is contained in:
Thomas Allmer 2021-07-07 18:07:49 +02:00
parent 5e7e43d221
commit ae14f99875
13 changed files with 529 additions and 336 deletions

View file

@ -0,0 +1,6 @@
---
'@lion/accordion': patch
'@lion/switch': patch
---
Improve documentation and examples

View file

@ -7,5 +7,6 @@
"first-line-h1": false, "first-line-h1": false,
"no-trailing-punctuation": { "no-trailing-punctuation": {
"punctuation": ".,;。,;:!" "punctuation": ".,;。,;:!"
} },
"ol-prefix": false
} }

View file

@ -1,214 +0,0 @@
# Content >> Accordion >> Features ||20
```js script
import { LitElement, html } from '@mdjs/mdjs-preview';
import '@lion/accordion/define';
```
## Expanded
You can set `expanded` to pre-expand a certain invoker.
```js preview-story
export const expanded = () => html`
<lion-accordion .expanded=${[1]}>
<h3 slot="invoker">
<button>Lorem</button>
</h3>
<p slot="content">Lorem ipsum dolor sit, amet consectetur adipisicing elit.</p>
<h3 slot="invoker">
<button>Laboriosam</button>
</h3>
<p slot="content">
Laboriosam sequi odit cumque, enim aut assumenda itaque quis voluptas est quos fugiat unde
labore reiciendis saepe, iure, optio officiis obcaecati quibusdam.
</p>
</lion-accordion>
`;
```
## Slots Order
The invoker and content slots are ordered by DOM order.
```js preview-story
export const slotsOrder = () => html`
<lion-accordion>
<h3 slot="invoker">
<button>Lorem</button>
</h3>
<p slot="content">Lorem ipsum dolor sit, amet consectetur adipisicing elit.</p>
<h3 slot="invoker">
<button>Laboriosam</button>
</h3>
<p slot="content">
Laboriosam sequi odit cumque, enim aut assumenda itaque quis voluptas est quos fugiat unde
labore reiciendis saepe, iure, optio officiis obcaecati quibusdam.
</p>
</lion-accordion>
`;
```
## Multiline header
A header can be multiline.
```js preview-story
export const multilineHeader = () => html`
<lion-accordion>
<h3 slot="invoker">
<button>
header 1 with
<br />
multiple lines
</button>
</h3>
<p slot="content">content 1</p>
<h3 slot="invoker">
<button>header 2</button>
</h3>
<p slot="content">content 2</p>
</lion-accordion>
`;
```
## Distribute New Elements
Below, we demonstrate how you could dynamically add a new invoker + content.
```js preview-story
export const distributeNewElement = () => {
const tagName = 'demo-accordion-add-dynamically';
if (!customElements.get(tagName)) {
customElements.define(
tagName,
class extends LitElement {
static get properties() {
return {
__collection: { type: Array },
};
}
render() {
return html`
<h3>Append</h3>
<lion-accordion id="appendAccordion">
<h4 slot="invoker">
<button>header 1</button>
</h4>
<p slot="content">content 1</p>
<h4 slot="invoker">
<button>header 2</button>
</h4>
<p slot="content">content 2</p>
</lion-accordion>
<button @click="${this.__handleAppendClick}">Append</button>
<hr />
<h3>Push</h3>
<lion-accordion id="pushTabs">
<h4 slot="invoker">
<button>header 1</button>
</h4>
<p slot="content">content 1</p>
<h4 slot="invoker">
<button>header 2</button>
</h4>
<p slot="content">content 2</p>
${this.__collection.map(
item => html`
<h4 slot="invoker"><button>${item.invoker}</button></h4>
<p slot="content">${item.content}</p>
`,
)}
</lion-accordion>
<button @click="${this.__handlePushClick}">Push</button>
`;
}
constructor() {
super();
this.__collection = [];
}
__handleAppendClick() {
const accordionElement = this.shadowRoot.querySelector('#appendAccordion');
const c = 2;
const n = Math.floor(accordionElement.children.length / 2);
for (let i = n + 1; i < n + c; i += 1) {
const invoker = document.createElement('h4');
const button = document.createElement('button');
button.innerText = `header ${i}`;
invoker.setAttribute('slot', 'invoker');
invoker.appendChild(button);
const content = document.createElement('p');
content.setAttribute('slot', 'content');
content.innerText = `content ${i}`;
accordionElement.append(invoker);
accordionElement.append(content);
}
}
__handlePushClick() {
const accordionElement = this.shadowRoot.querySelector('#pushTabs');
const i = Math.floor(accordionElement.children.length / 2) + 1;
this.__collection = [
...this.__collection,
{
invoker: `header ${i}`,
content: `content ${i}`,
},
];
}
},
);
}
return html` <demo-accordion-add-dynamically></demo-accordion-add-dynamically> `;
};
```
One way is by creating the DOM elements and appending them as needed.
Inside your `lion-accordion` extension, an example for appending nodes on a certain button click:
```js
__handleAppendClick() {
const accordionAmount = this.children.length / 2;
const invoker = document.createElement('h4');
const button = document.createElement('button');
button.innerText = `header ${accordionAmount + 1}`;
invoker.setAttribute('slot', 'invoker');
invoker.appendChild(button);
const content = document.createElement('p');
content.setAttribute('slot', 'content');
content.innerText = `content ${accordionAmount + 1}`;
this.append(invoker);
this.append(content);
}
```
The other way is by adding data to a Lit property where you loop over this property in your template.
You then need to ensure this causes a re-render.
```js
__handlePushClick() {
const accordionAmount = this.children.length;
myCollection = [
...myCollection,
{
invoker: `header ${accordionAmount + 1}`,
content: `content ${accordionAmount + 1}`,
},
];
renderMyCollection();
}
```
Make sure your template re-renders when myCollection is updated.
```html
<lion-accordion id="pushAccordion">
${myCollection.map(item => html`
<h4 slot="invoker">
<button>${item.invoker}</button>
</h4>
<p slot="content">${item.content}</p>
`)}
</lion-accordion>
```

View file

@ -1,52 +1,127 @@
# Content >> Accordion >> Overview ||10 # Content >> Accordion >> Overview ||10
A web component that can be used to toggle the display of sections of content. <p class="lion-paragraph--emphasis">An accordion is a vertically stacked set of interactive headings that each contain a title representing a section of content. It allows users to toggle the display of sections of content.</p>
Its purpose is to reduce the need to scroll when presenting multiple sections of content on a single page. Accordions often allow users to get the big picture before focusing on details.
```js script ```js script
import { html } from '@mdjs/mdjs-preview'; import { html as previewHtml } from '@mdjs/mdjs-preview';
import '@lion/accordion/define';
``` ```
```js preview-story ```js preview-story
export const main = () => html` import { html, LitElement, ScopedElementsMixin } from '@lion/core';
import { LionAccordion } from '@lion/accordion';
class MyComponent extends ScopedElementsMixin(LitElement) {
static get scopedElements() {
return { 'lion-accordion': LionAccordion };
}
render() {
return html`
<lion-accordion> <lion-accordion>
<h3 slot="invoker"> <h3 slot="invoker">
<button>Lorem</button> <button>Sensory Factors</button>
</h3> </h3>
<p slot="content">Lorem ipsum dolor sit, amet consectetur adipisicing elit.</p> <div slot="content">
<h3 slot="invoker"> <p>
<button>Laboriosam</button> The taste of oranges is determined mainly by the relative ratios of sugars and acids,
</h3> whereas orange aroma derives from volatile organic compounds, including alcohols,
<p slot="content"> aldehydes, ketones, terpenes, and esters. Bitter limonoid compounds, such as limonin,
Laboriosam sequi odit cumque, enim aut assumenda itaque quis voluptas est quos fugiat unde decrease gradually during development, whereas volatile aroma compounds tend to peak in
labore reiciendis saepe, iure, optio officiis obcaecati quibusdam. mid to lateseason development. Taste quality tends to improve later in harvests when
there is a higher sugar/acid ratio with less bitterness. As a citrus fruit, the orange
is acidic, with pH levels ranging from 2.9 to 4.0.
</p> </p>
<p>
Sensory qualities vary according to genetic background, environmental conditions during
development, ripeness at harvest, postharvest conditions, and storage duration.
</p>
</div>
<h3 slot="invoker">
<button>Nutritional value</button>
</h3>
<div slot="content">
Orange flesh is 87% water, 12% carbohydrates, 1% protein, and contains negligible fat
(table). In a 100 gram reference amount, orange flesh provides 47 calories, and is a rich
source of vitamin C, providing 64% of the Daily Value. No other micronutrients are present
in significant amounts (table).
</div>
</lion-accordion> </lion-accordion>
`; `;
}
}
customElements.define('my-component', MyComponent);
export const overview = () => previewHtml`<my-component></my-component>`;
``` ```
## When to use
- Accordions are commonly used to reduce the need to scroll when presenting multiple sections of content on a single page
- Longer pages can benefit users. Accordions shorten pages and reduce scrolling, but they increase the interaction cost by requiring people to decide on topic headings.
- Accordions conserve space on mobile but they can also cause disorientation and too much scrolling.
- Accordions should be avoided when your audience needs most or all of the content on the page to answer their question. Better to show all page content at once when the use case supports it.
- Accordions are more suitable when people need only a few key pieces of content on a single page. By hiding most of the content, users can spend their time more efficiently focused on the few topics that matter.
## Features ## Features
- content gets provided by users (slotted in) - Content gets provided by users (slotted in)
- handles accessibility - Handles accessibility
- support navigation via keyboard - Support navigation via keyboard
## Installation ## How to use
```bash ### Code
npm i --save @lion/accordion
```
```js 1. Install
import { LionAccordion } from '@lion/accordion';
// or
import '@lion/accordion/define';
```
## Rationale ```bash
npm i --save @lion/accordion
```
### Contents are not focusable 2. Use scoped registry
Focusable elements should be interactive. Contents themselves do not offer any interactivity. ```js
If there is a button or a form inside the tab panel then these elements get focused directly. import { html, LitElement, ScopedElementsMixin } from '@lion/core';
import { LionAccordion } from '@lion/accordion';
class MyComponent extends ScopedElementsMixin(LitElement) {
static get scopedElements() {
return { 'lion-accordion': LionAccordion };
}
render() {
return html`
<lion-accordion>
<h3 slot="invoker">
<button>Nutritional value</button>
</h3>
<p slot="content">
Orange flesh is 87% water, 12% carbohydrates, 1% protein, and contains negligible fat
(table). In a 100 gram reference amount, orange flesh provides 47 calories, and is a
rich source of vitamin C, providing 64% of the Daily Value. No other micronutrients are
present in significant amounts (table).
</p>
</lion-accordion>
`;
}
}
```
3. Use html
```html
<script type="module">
import '@lion/accordion/define';
</script>
<lion-accordion>
<h3 slot="invoker">
<button>Nutritional value</button>
</h3>
<p slot="content">
Orange flesh is 87% water, 12% carbohydrates, 1% protein, and contains negligible fat
(table). In a 100 gram reference amount, orange flesh provides 47 calories, and is a rich
source of vitamin C, providing 64% of the Daily Value. No other micronutrients are present in
significant amounts (table).
</p>
</lion-accordion>
```

View file

@ -0,0 +1,47 @@
# Content >> Accordion >> Reference ||30
<p class="lion-paragraph--emphasis">Everything you need to re-use the accordion.</p>
## Requirements
This component fulfils the following requirements:
1. An Accordion lets you toggle the visibility of content for a specific section
2. An Accordion contains a visual indicator/icon as an affordance to toggle the visibility of the content
3. Every section consists of a section title (always visible) and section content (visible when expanded)
4. The individual sections (title + content) are clearly grouped
5. Multiple sections can be expanded at the same time
6. The section heading (title + visual indicator) is used as the interaction trigger
7. An Accordion does not reposition the page when content drops out of the viewport when expanding a section (no auto scrolling)
## Rationale
### Contents are not focusable
Focusable elements should be interactive. Contents themselves do not offer any interactivity.
If there is a button or a form inside the tab panel then these elements get focused directly.
## Keyboard interactions
| <kbd>Key</kbd> | Action |
| :--------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| <kbd>Enter or Spacebar</kbd> | When focus is on the accordion header for a collapsed panel, expands the associated panel. When focus is on the accordion header for an expanded panel, collapses the panel if the implementation supports collapsing |
| <kbd>Tab</kbd> | Moves focus to the next focusable element; all focusable elements in the accordion are included in the page Tab sequence. |
| <kbd>Shift+Tab</kbd> | Moves focus to the previous focusable element; all focusable elements in the accordion are included in the page Tab sequence. |
| <kbd>Down arrow </kbd> | If focus is on an accordion header, moves focus to the next accordion header. If focus is on the last accordion header, either does nothing or moves focus to the first accordion header. |
| <kbd>Up arrow</kbd> | If focus is on an accordion header, moves focus to the previous accordion header. If focus is on the first accordion header, either does nothing or moves focus to the last accordion header. |
| <kbd>Home</kbd> | When focus is on an accordion header, moves focus to the first accordion header. |
| <kbd>End</kbd> | When focus is on an accordion header, moves focus to the last accordion header. |
## WAI-ARIA roles
- The title of each accordion header is contained in an element with role button.
- Each accordion header button is wrapped in an element with role heading that has a value set for aria-level that is appropriate for the information architecture of the page.
- If the native host language has an element with an implicit heading and aria-level, such as an HTML heading tag, a native host language element may be used.
- The button element is the only element inside the heading element. That is, if there are other visually persistent elements, they are not included inside the heading element.
- If the accordion panel associated with an accordion header is visible, the header button element has aria-expanded set to true. If the panel is not visible, aria-expanded is set to false.
- The accordion header button element has aria-controls set to the ID element containing the accordion panel content.
- If the accordion panel associated with an accordion header is visible, and if the accordion does not permit the panel to be collapsed, the header button element has aria-disabled set to true.
- Optionally, each element that serves as a container for panel content has role region and aria-labelledby with a value that refers to the button that controls display of the panel.
- Avoid using the region role in circumstances that create landmark region proliferation, e.g. in an accordion that contains more than approximately 6 panels that can be expanded at the same time.
- Role region is especially helpful to the perception of structure by screen reader users when panels contain heading elements or a nested accordion.

View file

@ -0,0 +1,252 @@
# Content >> Accordion >> Use Cases ||20
```js script
import { html as previewHtml } from '@mdjs/mdjs-preview';
import '@lion/accordion/define';
```
## Default Accordion collapsed
All accordion panels are collapsed by default.
```html preview-story
<lion-accordion>
<h3 slot="invoker">
<button>Sensory Factors</button>
</h3>
<div slot="content" class="lion-paragraph-container">
<p>
The taste of oranges is determined mainly by the relative ratios of sugars and acids, whereas
orange aroma derives from volatile organic compounds, including alcohols, aldehydes, ketones,
terpenes, and esters. Bitter limonoid compounds, such as limonin, decrease gradually during
development, whereas volatile aroma compounds tend to peak in mid to lateseason development.
Taste quality tends to improve later in harvests when there is a higher sugar/acid ratio with
less bitterness. As a citrus fruit, the orange is acidic, with pH levels ranging from 2.9 to
4.0.
</p>
<p>
Sensory qualities vary according to genetic background, environmental conditions during
development, ripeness at harvest, postharvest conditions, and storage duration.
</p>
</div>
<h3 slot="invoker">
<button>Nutritional value</button>
</h3>
<div slot="content">
Orange flesh is 87% water, 12% carbohydrates, 1% protein, and contains negligible fat (table).
In a 100 gram reference amount, orange flesh provides 47 calories, and is a rich source of
vitamin C, providing 64% of the Daily Value. No other micronutrients are present in significant
amounts (table).
</div>
</lion-accordion>
```
## Expanded
Multiple accordion panels can be expanded at the same time. When content drops out of the viewport when expanding an accordion panel, the accordion does not reposition the page (no autoscrolling).
```html preview-story
<lion-accordion expanded="[1]">
<h3 slot="invoker">
<button>Sensory Factors</button>
</h3>
<div slot="content" class="lion-paragraph-container">
<p>
The taste of oranges is determined mainly by the relative ratios of sugars and acids, whereas
orange aroma derives from volatile organic compounds, including alcohols, aldehydes, ketones,
terpenes, and esters. Bitter limonoid compounds, such as limonin, decrease gradually during
development, whereas volatile aroma compounds tend to peak in mid to lateseason development.
Taste quality tends to improve later in harvests when there is a higher sugar/acid ratio with
less bitterness. As a citrus fruit, the orange is acidic, with pH levels ranging from 2.9 to
4.0.
</p>
<p>
Sensory qualities vary according to genetic background, environmental conditions during
development, ripeness at harvest, postharvest conditions, and storage duration.
</p>
</div>
<h3 slot="invoker">
<button>Nutritional value</button>
</h3>
<div slot="content">
Orange flesh is 87% water, 12% carbohydrates, 1% protein, and contains negligible fat (table).
In a 100 gram reference amount, orange flesh provides 47 calories, and is a rich source of
vitamin C, providing 64% of the Daily Value. No other micronutrients are present in significant
amounts (table).
</div>
</lion-accordion>
```
## Slots Order
The invoker and content slots are ordered by DOM order. This means you can put all invoker nodes at the top followed by all container nodes and it will still retain the correct order.
```html preview-story
<lion-accordion>
<h3 slot="invoker">
<button>Sensory Factors</button>
</h3>
<h3 slot="invoker">
<button>Nutritional value</button>
</h3>
<div slot="content" class="lion-paragraph-container">
<p>
The taste of oranges is determined mainly by the relative ratios of sugars and acids, whereas
orange aroma derives from volatile organic compounds, including alcohols, aldehydes, ketones,
terpenes, and esters. Bitter limonoid compounds, such as limonin, decrease gradually during
development, whereas volatile aroma compounds tend to peak in mid to lateseason development.
Taste quality tends to improve later in harvests when there is a higher sugar/acid ratio with
less bitterness. As a citrus fruit, the orange is acidic, with pH levels ranging from 2.9 to
4.0.
</p>
<p>
Sensory qualities vary according to genetic background, environmental conditions during
development, ripeness at harvest, postharvest conditions, and storage duration.
</p>
</div>
<div slot="content">
Orange flesh is 87% water, 12% carbohydrates, 1% protein, and contains negligible fat (table).
In a 100 gram reference amount, orange flesh provides 47 calories, and is a rich source of
vitamin C, providing 64% of the Daily Value. No other micronutrients are present in significant
amounts (table).
</div>
</lion-accordion>
```
## Multiline header
A header can be multiline.
```html preview-story
<lion-accordion>
<h3 slot="invoker">
<button>
Sensory Factors <br />
<small>or the experience of taste</small>
</button>
</h3>
<div slot="content" class="lion-paragraph-container">
<p>
The taste of oranges is determined mainly by the relative ratios of sugars and acids, whereas
orange aroma derives from volatile organic compounds, including alcohols, aldehydes, ketones,
terpenes, and esters. Bitter limonoid compounds, such as limonin, decrease gradually during
development, whereas volatile aroma compounds tend to peak in mid to lateseason development.
Taste quality tends to improve later in harvests when there is a higher sugar/acid ratio with
less bitterness. As a citrus fruit, the orange is acidic, with pH levels ranging from 2.9 to
4.0.
</p>
<p>
Sensory qualities vary according to genetic background, environmental conditions during
development, ripeness at harvest, postharvest conditions, and storage duration.
</p>
</div>
<h3 slot="invoker">
<button>
Nutritional value
<small>or the raw data</small>
</button>
</h3>
<div slot="content">
Orange flesh is 87% water, 12% carbohydrates, 1% protein, and contains negligible fat (table).
In a 100 gram reference amount, orange flesh provides 47 calories, and is a rich source of
vitamin C, providing 64% of the Daily Value. No other micronutrients are present in significant
amounts (table).
</div>
</lion-accordion>
```
## Distribute New Elements
Below, we demonstrate how you could dynamically add a new invoker + content.
One way is by creating the DOM elements and appending them as needed. For how this work feel tree to check out the `__handleAppendClick` function.
Another way is by adding data to the Lit property that you loop over in your template. See `__handlePushClick` for an example.
```js preview-story
import { html, LitElement } from '@lion/core';
export const distributeNewElement = () => {
class DemoDistribute extends LitElement {
static get properties() {
return {
__collection: { type: Array },
};
}
render() {
return html`
<h3>Append</h3>
<lion-accordion id="appendAccordion">
<h4 slot="invoker">
<button>header 1</button>
</h4>
<p slot="content">content 1</p>
<h4 slot="invoker">
<button>header 2</button>
</h4>
<p slot="content">content 2</p>
</lion-accordion>
<button @click="${this.__handleAppendClick}">Append dom elements</button>
<hr />
<h3>Push</h3>
<lion-accordion id="pushTabs">
<h4 slot="invoker">
<button>header 1</button>
</h4>
<p slot="content">content 1</p>
<h4 slot="invoker">
<button>header 2</button>
</h4>
<p slot="content">content 2</p>
${this.__collection.map(
item => html`
<h4 slot="invoker"><button>${item.invoker}</button></h4>
<p slot="content">${item.content}</p>
`,
)}
</lion-accordion>
<button @click="${this.__handlePushClick}">Push to tabs collection</button>
`;
}
constructor() {
super();
this.__collection = [];
}
__handleAppendClick() {
const accordionElement = this.shadowRoot.querySelector('#appendAccordion');
const c = 2;
const n = Math.floor(accordionElement.children.length / 2);
for (let i = n + 1; i < n + c; i += 1) {
const invoker = document.createElement('h4');
const button = document.createElement('button');
button.innerText = `header ${i}`;
invoker.setAttribute('slot', 'invoker');
invoker.appendChild(button);
const content = document.createElement('p');
content.setAttribute('slot', 'content');
content.innerText = `content ${i}`;
accordionElement.append(invoker);
accordionElement.append(content);
}
}
__handlePushClick() {
const accordionElement = this.shadowRoot.querySelector('#pushTabs');
const i = Math.floor(accordionElement.children.length / 2) + 1;
this.__collection = [
...this.__collection,
{
invoker: `header ${i}`,
content: `content ${i}`,
},
];
}
}
customElements.define('demo-distribute', DemoDistribute);
return previewHtml`<demo-distribute></demo-distribute>`;
};
```

View file

@ -1,14 +1,27 @@
# Interaction >> Switch >> Overview ||10 # Interaction >> Switch >> Overview ||10
<p class="paragraph--emphasis">The Switch is used to toggle a property or feature on or off.</p> <p class="lion-paragraph--emphasis">The Switch is used to toggle a property or feature on or off.</p>
```js script ```js script
import { html } from '@mdjs/mdjs-preview'; import { html as previewHtml } from '@mdjs/mdjs-preview';
import '@lion/switch/define-switch'; import '@lion/switch/define-switch';
``` ```
```js preview-story ```js preview-story
export const main = () => html`<lion-switch label="Label" help-text="Help text"></lion-switch>`; import { html, LitElement, ScopedElementsMixin } from '@lion/core';
import { LionSwitch } from '@lion/switch';
class MyComponent extends ScopedElementsMixin(LitElement) {
static get scopedElements() {
return { 'lion-switch': LionSwitch };
}
render() {
return html`<lion-switch label="Label" help-text="Help text"></lion-switch>`;
}
}
customElements.define('my-component', MyComponent);
export const main = () => previewHtml`<my-component></my-component>`;
``` ```
## When to use ## When to use
@ -25,14 +38,36 @@ export const main = () => html`<lion-switch label="Label" help-text="Help text">
## How to use ## How to use
### Installation ### Code
```bash 1. Install
npm i --save @lion/switch
```
```js ```bash
import { LionSwitch } from '@lion/switch'; npm i --save @lion/switch
// or ```
import '@lion/switch/define-switch';
``` 2. Use scoped registry
```js
import { html, LitElement, ScopedElementsMixin } from '@lion/core';
import { LionSwitch } from '@lion/switch';
class MyComponent extends ScopedElementsMixin(LitElement) {
static get scopedElements() {
return { 'lion-switch': LionSwitch };
}
render() {
return html`<lion-switch></lion-switch>`;
}
}
```
3. Use html
```html
<script type="module">
import '@lion/switch/define-switch';
</script>
<lion-switch></lion-switch>
```

View file

@ -1,6 +1,24 @@
# Interaction >> Switch >> Reference ||30 # Interaction >> Switch >> Reference ||30
<p class="paragraph--emphasis">Everything you need to re-use the switch.</p> <p class="lion-paragraph--emphasis">Everything you need to re-use the switch.</p>
## Requirements
This component fulfils the following requirements:
1. The component clearly communicates what is it for.
2. The component supports helper text.
3. The component supports smart defaults.
4. The component supports the following states: on, off, hover (Web only), focused, disabled, pressed and processing
5. The transformation between ON and OFF states are enhanced by an animation.
6. Toggling the switch (on <-> off) will execute the underlying action immediately.
## Keyboard interactions
| <kbd>Key</kbd> | Action |
| :------------------ | :------------------------------------------------------------------------------------------------ |
| <kbd>Enter</kbd> | On keyboard focus, pressing <kbd>Enter</kbd> changes the state of the switch to “On” or “Off”. |
| <kbd>Spacebar</kbd> | On keyboard focus, pressing <kbd>Spacebar</kbd> changes the state of the switch to “On” or “Off”. |
## WAI-ARIA roles ## WAI-ARIA roles
@ -19,21 +37,3 @@
role: switch<br> role: switch<br>
state: aria-checked=“false”<br> state: aria-checked=“false”<br>
SR: “Label, off, switch” SR: “Label, off, switch”
## Keyboard interactions
| <kbd>Key</kbd> | Action |
| :------------------ | :------------------------------------------------------------------------------------------------ |
| <kbd>Enter</kbd> | On keyboard focus, pressing <kbd>Enter</kbd> changes the state of the switch to “On” or “Off”. |
| <kbd>Spacebar</kbd> | On keyboard focus, pressing <kbd>Spacebar</kbd> changes the state of the switch to “On” or “Off”. |
## Requirements
This component fulfils the following requirements:
1. The component clearly communicates what is it for.
2. The component supports helper text.
3. The component supports smart defaults.
4. The component supports the following states: on, off, hover (Web only), focused, disabled, pressed and processing
5. The transformation between ON and OFF states are enhanced by an animation.
6. Toggling the switch (on <-> off) will execute the underlying action immediately.

View file

@ -12,17 +12,16 @@ import '@lion/helpers/define-sb-action-logger';
You can disable switches. You can disable switches.
```js preview-story ```html preview-story
export const disabled = () => html` <lion-switch label="Label" disabled></lion-switch> `; <lion-switch label="Label" disabled></lion-switch>
``` ```
## Validation ## Validation
Simple example that illustrates where validation feedback will be displayed. An example that illustrates how an info validation feedback can be always displayed.
```js preview-story ```js preview-story
export const validation = () => { class IsTrue extends Validator {
const IsTrue = class extends Validator {
static get validatorName() { static get validatorName() {
return 'IsTrue'; return 'IsTrue';
} }
@ -32,34 +31,29 @@ export const validation = () => {
static async getMessage() { static async getMessage() {
return "You won't get the latest news!"; return "You won't get the latest news!";
} }
}; }
const tagName = 'custom-switch';
if (!customElements.get(tagName)) { class CustomSwitch extends LionSwitch {
customElements.define(
tagName,
class CustomSwitch extends LionSwitch {
static get validationTypes() { static get validationTypes() {
return [...super.validationTypes, 'info']; return [...super.validationTypes, 'info'];
} }
_showFeedbackConditionFor(type) { _showFeedbackConditionFor(type, meta) {
if (type === 'info') { if (type === 'info') {
return true; return true;
} }
return super._showFeedbackConditionFor(type); return super._showFeedbackConditionFor(type, meta);
} }
}, }
); customElements.define('custom-switch', CustomSwitch);
}
return html` export const validation = () => html`
<custom-switch <custom-switch
id="newsletterCheck"
name="newsletterCheck" name="newsletterCheck"
label="Subscribe to newsletter" label="Subscribe to newsletter"
.validators="${[new IsTrue(null, { type: 'info' })]}" .validators="${[new IsTrue(null, { type: 'info' })]}"
></custom-switch> ></custom-switch>
`; `;
};
``` ```
## With checked-changed handler ## With checked-changed handler

View file

@ -1,3 +0,0 @@
# Lion Accordion Features
[=> See Source <=](../../../docs/components/content/accordion/features.md)

View file

@ -0,0 +1,3 @@
# Lion Accordion Reference
[=> See Source <=](../../../docs/components/content/accordion/reference.md)

View file

@ -0,0 +1,3 @@
# Lion Accordion Use Cases
[=> See Source <=](../../../docs/components/content/accordion/use-cases.md)

View file

@ -1277,13 +1277,6 @@
dependencies: dependencies:
vary "^1.1.2" vary "^1.1.2"
"@lion/accordion@^0.4.2":
version "0.4.2"
resolved "https://registry.yarnpkg.com/@lion/accordion/-/accordion-0.4.2.tgz#efeb56360113a2b68e182ff29ef0932edd17df8c"
integrity sha512-xETjNmpBWYO1tYx2nBMq0I45UgydUJafZ4ft3szH3fQFjYWSBwjJjKsWxIhZSqX/IoTJzA0nNCdtbXoVEbSCLg==
dependencies:
"@lion/core" "0.16.0"
"@lion/core@0.16.0": "@lion/core@0.16.0":
version "0.16.0" version "0.16.0"
resolved "https://registry.yarnpkg.com/@lion/core/-/core-0.16.0.tgz#c4c8ac81b8d5bece6d40d561a392382c7ae73533" resolved "https://registry.yarnpkg.com/@lion/core/-/core-0.16.0.tgz#c4c8ac81b8d5bece6d40d561a392382c7ae73533"
@ -1354,11 +1347,12 @@
unist-util-visit "^2.0.3" unist-util-visit "^2.0.3"
"@mdjs/mdjs-preview@^0.5.0": "@mdjs/mdjs-preview@^0.5.0":
version "0.5.0" version "0.5.1"
resolved "https://registry.yarnpkg.com/@mdjs/mdjs-preview/-/mdjs-preview-0.5.0.tgz#cd4177d303b5e034efe6472e424dbc91b7fbfec9" resolved "https://registry.yarnpkg.com/@mdjs/mdjs-preview/-/mdjs-preview-0.5.1.tgz#e8a252130cd21e8accdbc175f73ca109986a3039"
integrity sha512-GjLZLYJnXjFTrG77sxWqebSpFXoJHhIvTGDh1AjnIdtEOcnOqGjwaOrLjS751xPKSlS8GTo2G/6+usGeWfrx1Q== integrity sha512-wxLR0dtku/Uv/LllEXx61r+H1S1n2pRM30Ht57aITukbFBoeh1xZoA/c9j/X+a2/paQNXzG9KsnMfUH0HKMsOQ==
dependencies: dependencies:
"@lion/accordion" "^0.4.2" "@lion/accordion" "^0.6.1"
"@open-wc/scoped-elements" "^2.0.0-next.3"
lit "^2.0.0-rc.2" lit "^2.0.0-rc.2"
"@mdjs/mdjs-story@^0.3.0": "@mdjs/mdjs-story@^0.3.0":