feat: as BREAKING CHANGE add exports & convert to static docs page
5
.changeset/early-dolphins-build.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'babel-plugin-extend-docs': patch
|
||||
---
|
||||
|
||||
Still replace tags if templates uses `.foo=${{ key: 'value' }}`
|
||||
23
.changeset/famous-bears-confess.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
---
|
||||
'remark-extend': minor
|
||||
---
|
||||
|
||||
BREAKING CHANGE: Changing approach from overwriting extending files to using an import-based approach.
|
||||
|
||||
Removed features:
|
||||
|
||||
- `::replaceFrom`
|
||||
- `::replaceBetween`
|
||||
- `::addMdAfter`
|
||||
- `::removeFrom`
|
||||
- `::removeBetween`
|
||||
|
||||
Added Features:
|
||||
|
||||
- `::import`
|
||||
- `::importBlock`
|
||||
- `::importBlockContent`
|
||||
- `::importSmallBlock`
|
||||
- `::importSmallBlockContent`
|
||||
|
||||
See the updated documentation for how to use this new approach.
|
||||
5
.changeset/odd-beds-clean.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'providence-analytics': minor
|
||||
---
|
||||
|
||||
BREAKING: Align exports fields. If you want to import from CLI instead of main entrypoint (`import { ... } from 'providence-analytics';`) using export maps, you can now do so with `import { ... } from 'providence-analytics/src/cli';` instead of `import { ... } from 'providence-analytics/src/cli/index.js';`.
|
||||
40
.changeset/silly-ants-melt.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
---
|
||||
'@lion/accordion': minor
|
||||
'@lion/button': minor
|
||||
'@lion/calendar': minor
|
||||
'@lion/checkbox-group': minor
|
||||
'@lion/collapsible': minor
|
||||
'@lion/combobox': minor
|
||||
'@lion/core': minor
|
||||
'@lion/dialog': minor
|
||||
'@lion/fieldset': minor
|
||||
'@lion/form': minor
|
||||
'@lion/form-core': minor
|
||||
'@lion/form-integrations': minor
|
||||
'@lion/helpers': minor
|
||||
'@lion/icon': minor
|
||||
'@lion/input': minor
|
||||
'@lion/input-amount': minor
|
||||
'@lion/input-date': minor
|
||||
'@lion/input-datepicker': minor
|
||||
'@lion/input-email': minor
|
||||
'@lion/input-iban': minor
|
||||
'@lion/input-range': minor
|
||||
'@lion/input-stepper': minor
|
||||
'@lion/listbox': minor
|
||||
'@lion/localize': minor
|
||||
'@lion/overlays': minor
|
||||
'@lion/pagination': minor
|
||||
'@lion/progress-indicator': minor
|
||||
'@lion/radio-group': minor
|
||||
'@lion/select': minor
|
||||
'@lion/select-rich': minor
|
||||
'@lion/steps': minor
|
||||
'@lion/switch': minor
|
||||
'@lion/tabs': minor
|
||||
'@lion/textarea': minor
|
||||
'@lion/tooltip': minor
|
||||
'@lion/validate-messages': minor
|
||||
---
|
||||
|
||||
BREAKING: Align exports fields. This means no more wildcards, meaning you always import with bare import specifiers, extensionless. Import components where customElements.define side effect is executed by importing from '@lion/package/define'. For multi-component packages this defines all components (e.g. radio-group + radio). If you want to only import a single one, do '@lion/package/define-radio' for example for just lion-radio.
|
||||
4
.eleventyignore
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
node_modules/**
|
||||
/docs/_assets
|
||||
/docs/_includes
|
||||
/docs/_data
|
||||
|
|
@ -3,3 +3,5 @@ coverage/
|
|||
bundlesize/
|
||||
.history/
|
||||
*.d.ts
|
||||
_site-dev
|
||||
_site
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ module.exports = {
|
|||
files: ['**/*.js'],
|
||||
rules: {
|
||||
'wc/guard-super-call': 'off', // types will prevent you from calling the super if it's not in the base class, making the guard unnecessary
|
||||
'no-await-in-loop': 'off',
|
||||
'import/no-unresolved': 'off', // eslint not smart enough atm to understand package exports maps
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
|
|||
11
.gitignore
vendored
|
|
@ -42,6 +42,15 @@ local.log
|
|||
## browserstack
|
||||
browserstack.err
|
||||
|
||||
## Rocket ignore files (need to be the full relative path to the folders)
|
||||
docs/_merged_data/
|
||||
docs/_merged_assets/
|
||||
docs/_merged_includes/
|
||||
|
||||
debug.log
|
||||
|
||||
!packages/singleton-manager/demo/**/node_modules
|
||||
_site
|
||||
_site-dev
|
||||
|
||||
## generated test fiels
|
||||
__output
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
"line-length": {
|
||||
"line_length": -1
|
||||
},
|
||||
"fenced-code-language": false,
|
||||
"no-inline-html": false,
|
||||
"first-line-h1": false,
|
||||
"no-trailing-punctuation": {
|
||||
"punctuation": ".,;。,;:!"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
coverage/
|
||||
CHANGELOG.md
|
||||
bundlesize/
|
||||
_site
|
||||
_site-dev
|
||||
|
|
|
|||
|
|
@ -1,81 +0,0 @@
|
|||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
stories: [
|
||||
'../{packages,packages-node}/*/README.md',
|
||||
'../{packages,packages-node}/*/docs/*.md',
|
||||
'../{packages,packages-node}/*/docs/!(assets)**/*.md',
|
||||
'../packages/helpers/*/README.md',
|
||||
'../docs/README.md',
|
||||
'../docs/**/*.md',
|
||||
'../README.md',
|
||||
'../demo/README.md',
|
||||
'../demo/docs/*.md',
|
||||
],
|
||||
addons: [
|
||||
// order of tabs in addons panel
|
||||
'storybook-prebuilt/addon-actions/register.js',
|
||||
'storybook-prebuilt/addon-knobs/register.js',
|
||||
'storybook-prebuilt/addon-a11y/register.js',
|
||||
'storybook-prebuilt/addon-docs/register.js',
|
||||
// no tab in addons panel (e.g. load order does not matter here)
|
||||
'storybook-prebuilt/addon-backgrounds/register.js',
|
||||
'storybook-prebuilt/addon-links/register.js',
|
||||
'storybook-prebuilt/addon-viewport/register.js',
|
||||
],
|
||||
addons: [
|
||||
'storybook-prebuilt/addon-docs/register.js',
|
||||
'storybook-prebuilt/addon-actions/register.js',
|
||||
'storybook-prebuilt/addon-knobs/register.js',
|
||||
'storybook-prebuilt/addon-a11y/register.js',
|
||||
'storybook-prebuilt/addon-backgrounds/register.js',
|
||||
'storybook-prebuilt/addon-links/register.js',
|
||||
'storybook-prebuilt/addon-viewport/register.js',
|
||||
],
|
||||
esDevServer: {
|
||||
nodeResolve: true,
|
||||
watch: true,
|
||||
open: true,
|
||||
},
|
||||
rollup: config => {
|
||||
// temporarily hard copy all needed global files as all tested rollup plugins flatten the
|
||||
// directory structure
|
||||
// `rollup-plugin-copy` might work if issue 37 is resolved
|
||||
// https://github.com/vladshcherbin/rollup-plugin-copy/issues/37
|
||||
config.plugins.push({
|
||||
generateBundle() {
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: 'packages/form-integrations/dev-assets/FormatMixinDiagram-1.svg',
|
||||
source: fs.readFileSync(
|
||||
path.join(
|
||||
__dirname,
|
||||
'../packages/form-integrations/dev-assets/FormatMixinDiagram-1.svg',
|
||||
),
|
||||
),
|
||||
});
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: 'packages/form-integrations/dev-assets/FormatMixinDiagram-2.svg',
|
||||
source: fs.readFileSync(
|
||||
path.join(
|
||||
__dirname,
|
||||
'../packages/form-integrations/dev-assets/FormatMixinDiagram-2.svg',
|
||||
),
|
||||
),
|
||||
});
|
||||
this.emitFile({
|
||||
type: 'asset',
|
||||
fileName: 'packages/form-integrations/dev-assets/FormatMixinDiagram-3.svg',
|
||||
source: fs.readFileSync(
|
||||
path.join(
|
||||
__dirname,
|
||||
'../packages/form-integrations/dev-assets/FormatMixinDiagram-3.svg',
|
||||
),
|
||||
),
|
||||
});
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
<style>
|
||||
/**
|
||||
* Temp approach for showing local overlays that flow out of their container
|
||||
* Ideally, this would be configurable in Preview:
|
||||
* https://github.com/storybookjs/storybook/blob/next/lib/components/src/blocks/Preview.ts
|
||||
*/
|
||||
|
||||
.sbdocs.sbdocs-preview {
|
||||
overflow: initial;
|
||||
position: relative;
|
||||
z-index: unset;
|
||||
}
|
||||
|
||||
.sbdocs.sbdocs-preview > div:first-child {
|
||||
z-index: unset;
|
||||
}
|
||||
|
||||
.sbdocs.sbdocs-preview > div > div {
|
||||
overflow: initial;
|
||||
z-index: unset;
|
||||
}
|
||||
|
||||
.sbdocs.sbdocs-preview > div > div [scale='1'] {
|
||||
z-index: unset;
|
||||
transform: none;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,49 +0,0 @@
|
|||
import {
|
||||
addDecorator,
|
||||
addParameters,
|
||||
setCustomElements,
|
||||
withA11y,
|
||||
} from '@open-wc/demoing-storybook';
|
||||
import { sortEachDepth } from '../packages/helpers/index.js';
|
||||
|
||||
async function run() {
|
||||
// const customElements = await (
|
||||
// await fetch(new URL('../custom-elements.json', import.meta.url))
|
||||
// ).json();
|
||||
setCustomElements({});
|
||||
|
||||
addDecorator(withA11y);
|
||||
|
||||
addParameters({
|
||||
a11y: {
|
||||
config: {},
|
||||
options: {
|
||||
checks: { 'color-contrast': { options: { noScroll: true } } },
|
||||
restoreScroll: true,
|
||||
},
|
||||
},
|
||||
docs: {
|
||||
iframeHeight: '200px',
|
||||
},
|
||||
options: {
|
||||
showRoots: true,
|
||||
storySort: sortEachDepth([
|
||||
[
|
||||
'Intro',
|
||||
'Forms',
|
||||
'Buttons',
|
||||
'Overlays',
|
||||
'Navigation',
|
||||
'Localize',
|
||||
'Icons',
|
||||
'Others',
|
||||
'...',
|
||||
],
|
||||
['Intro', 'Features Overview', '...', 'Validation', 'System'],
|
||||
['Overview', '...', '_internals'],
|
||||
]),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
run();
|
||||
85
README.md
|
|
@ -1,38 +1,60 @@
|
|||
# Lion Web Components
|
||||
<p align="center">
|
||||
<img
|
||||
width="60%"
|
||||
src="./assets/logo.png"
|
||||
alt="Lion"
|
||||
/>
|
||||
</p>
|
||||
|
||||
```js script
|
||||
export default {
|
||||
title: 'Intro/Lion Web Components',
|
||||
};
|
||||
```
|
||||
<p align="center">
|
||||
<a href="https://github.com/modernweb-dev/rocket/actions"
|
||||
><img
|
||||
src="https://img.shields.io/github/workflow/status/modernweb-dev/rocket/Release/main?label=workflow&style=flat-square"
|
||||
alt="GitHub Actions workflow status"
|
||||
/></a>
|
||||
<a href="https://github.com/modernweb-dev/rocket/actions"
|
||||
><img
|
||||
src="https://img.shields.io/github/workflow/status/modernweb-dev/rocket/Release/main?label=workflow&style=flat-square"
|
||||
alt="GitHub Actions workflow status"
|
||||
/></a>
|
||||
<a href="https://www.tickgit.com/browse?repo=github.com/ing-bank/lion"
|
||||
><img
|
||||
src="https://badgen.net/https/api.tickgit.com/badgen/github.comgithub.com/ing-bank/lion"
|
||||
alt="Todos"
|
||||
/></a>
|
||||
</p>
|
||||
|
||||
Lion web components is a set of highly performant, accessible and flexible Web Components.
|
||||
They provide an unopinionated, white label layer that can be extended to your own layer of components.
|
||||
<p align="center">
|
||||
<a href="https://lion-web.netlify.app">Website</a>
|
||||
·
|
||||
<a href="https://lion-web.netlify.app/guides/">Guides</a>
|
||||
·
|
||||
<a href="https://lion-web.netlify.app/components/">Components</a>
|
||||
·
|
||||
<a href="https://lion-web.netlify.app/docs/">Documentation</a>
|
||||
·
|
||||
<a href="https://lion-web.netlify.app/blog/">Blog</a>
|
||||
</p>
|
||||
|
||||
For some more details see the [announcement blog post](https://medium.com/ing-blog/ing-open-sources-lion-a-library-for-performant-accessible-flexible-web-components-22ad165b1d3d).
|
||||
<h1></h1>
|
||||
|
||||
[](https://www.tickgit.com/browse?repo=github.com/ing-bank/lion)
|
||||
**Lion is a set of highly performant, accessible and flexible Web Components.!**
|
||||
|
||||
## Demos
|
||||
They provide an unopinionated, white-label layer that can be extended to your own layer of components.
|
||||
|
||||
We do have a [live Storybook](http://lion-web-components.netlify.com) which shows all our components.
|
||||
- **High Performance:** Focused on great performance in all relevant browsers with a minimal number of dependencies.
|
||||
- **Accessibility:** Aimed at compliance with the WCAG 2.1 AA standard to create components that are accessible for everybody.
|
||||
- **Flexibility:** Provides solutions through Web Components and JavaScript classes which can be used, adopted and extended to fit all needs.
|
||||
- **Modern Code:** Lion is distributes as pure es modules.
|
||||
- **Exposes functions/classes and Web Components:** Ships a functionality in it's most appropriate form.
|
||||
|
||||
**Please note:** This project uses Yarn [Workspaces](https://classic.yarnpkg.com/en/docs/workspaces). If you want to run all demos locally you need to get [Yarn](https://classic.yarnpkg.com/en/docs/install) and install all dependencies by executing `yarn install`.
|
||||
|
||||
The code examples make use of [Javascript tagged template literals](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) which are a key component of the [lit-html engine](https://lit-html.polymer-project.org/) used in Lion.
|
||||
Additionally imports like `import '@lion/form/lion-form.js'` need to be transformed somehow, for example by [es-dev-server](https://open-wc.org/developing/es-dev-server.html#node-resolve).
|
||||
|
||||
## Features
|
||||
|
||||
- High Performance - Focused on great performance in all relevant browsers with a minimal number of dependencies
|
||||
- Accessibility - Aimed at compliance with the WCAG 2.1 AA standard to create components that are accessible for everybody
|
||||
- Flexibility - Provides solutions through Web Components and JavaScript classes which can be used, adopted and extended to fit all needs
|
||||
- Pure ES Modules
|
||||
- Exposes functions/classes and Web Components
|
||||
|
||||
> Note: These demos may look a little bland but that is on purpose. They only come with functional stylings.
|
||||
> Note: Our demos may look a little bland but that is on purpose. They only come with functional stylings.
|
||||
> This makes sense as the main use case is to extend those components and if you do you do not want to override existing stylings.
|
||||
|
||||
<p align="center">
|
||||
<a href="https://lion-web.netlify.app/guides/"><strong>Explore the Lion Guides ▶</strong></a>
|
||||
</p>
|
||||
|
||||
## How to install
|
||||
|
||||
```bash
|
||||
|
|
@ -82,7 +104,7 @@ You can also use the lion elements directly, although this is likely not a commo
|
|||
|
||||
```html
|
||||
<script type="module">
|
||||
import '@lion/input/lion-input.js';
|
||||
import '@lion/input/define';
|
||||
</script>
|
||||
|
||||
<lion-input name="firstName"></lion-input>
|
||||
|
|
@ -150,18 +172,17 @@ The accessibility column indicates whether the functionality is accessible in it
|
|||
|
||||
## Technologies
|
||||
|
||||
Lion Web Components aims to be future proof and use well-supported proven technology. The stack we have chosen should reflect this.
|
||||
Lion Web Components aims to be future-proof and use well-supported proven technology. The stack we have chosen should reflect this.
|
||||
|
||||
- [lit-html](https://lit-html.polymer-project.org) and [lit-element](https://lit-element.polymer-project.org)
|
||||
- [npm](http://npmjs.com)
|
||||
- [yarn](https://yarnpkg.com)
|
||||
- [open-wc](https://open-wc.org)
|
||||
- [Karma](https://karma-runner.github.io)
|
||||
- [Open Web Components](https://open-wc.org)
|
||||
- [Modern Web](https://modern-web.dev)
|
||||
- [Mocha](https://mochajs.org)
|
||||
- [Chai](https://www.chaijs.com)
|
||||
- [ESLint](https://eslint.org)
|
||||
- [prettier](https://prettier.io)
|
||||
- [Storybook](https://storybook.js.org)
|
||||
- [ES modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)
|
||||
- Lots and lots of tests
|
||||
|
||||
|
|
@ -180,6 +201,8 @@ Check out our [coding guidelines](https://lion-web-components.netlify.app/?path=
|
|||
|
||||
## How to contribute
|
||||
|
||||
**Please note:** This project uses Yarn [Workspaces](https://classic.yarnpkg.com/en/docs/workspaces). If you want to run all demos locally you need to get [Yarn](https://classic.yarnpkg.com/en/docs/install) and install all dependencies by executing `yarn install`.
|
||||
|
||||
Lion Web Components are only as good as its contributions.
|
||||
Read our [contribution guide](https://github.com/ing-bank/lion/blob/master/CONTRIBUTING.md) and feel free to enhance/improve Lion. We keep feature requests closed while we're not working on them.
|
||||
|
||||
|
|
|
|||
BIN
assets/logo.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
|
|
@ -1,231 +0,0 @@
|
|||
# lea Tabs
|
||||
|
||||
> This is not a real implementation!
|
||||
>
|
||||
> It is an example of how you can reuse the functionality of Lion to create your own Style System
|
||||
|
||||
`lea-tabs` implements tabs view to allow users to quickly move between a small number of equally important views.
|
||||
|
||||
```js script
|
||||
import { html } from '@lion/core';
|
||||
import { LitElement } from '@lion/core';
|
||||
|
||||
import '../lea-tabs.js';
|
||||
import '../lea-tab.js';
|
||||
import '../lea-tab-panel.js';
|
||||
|
||||
export default {
|
||||
title: 'Intro/Tabs Example',
|
||||
};
|
||||
```
|
||||
|
||||
```js preview-story
|
||||
export const main = () => html`
|
||||
<lea-tabs>
|
||||
<lea-tab slot="tab">Info</lea-tab>
|
||||
<lea-tab-panel slot="panel"> Info page with lots of information about us. </lea-tab-panel>
|
||||
<lea-tab slot="tab">Work</lea-tab>
|
||||
<lea-tab-panel slot="panel"> Work page that showcases our work. </lea-tab-panel>
|
||||
</lea-tabs>
|
||||
`;
|
||||
```
|
||||
|
||||
## How to use
|
||||
|
||||
### Installation
|
||||
|
||||
```sh
|
||||
npm i --save @lion/tabs;
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```js
|
||||
import '@lion/tabs/lea-tabs.js';
|
||||
```
|
||||
|
||||
```html
|
||||
<lea-tabs>
|
||||
<lea-tab slot="tab">Info</lea-tab>
|
||||
<lea-tab-panel slot="panel"> Info page with lots of information about us. </lea-tab-panel>
|
||||
<lea-tab slot="tab">Work</lea-tab>
|
||||
<lea-tab-panel slot="panel"> Work page that showcases our work. </lea-tab-panel>
|
||||
</lea-tabs>
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
### Selected Index
|
||||
|
||||
You can set the `selectedIndex` to select a certain tab.
|
||||
|
||||
```js preview-story
|
||||
export const selectedIndex = () => html`
|
||||
<lea-tabs .selectedIndex=${1}>
|
||||
<lea-tab slot="tab">Info</lea-tab>
|
||||
<lea-tab-panel slot="panel"> Info page with lots of information about us. </lea-tab-panel>
|
||||
<lea-tab slot="tab">Work</lea-tab>
|
||||
<lea-tab-panel slot="panel"> Work page that showcases our work. </lea-tab-panel>
|
||||
</lea-tabs>
|
||||
`;
|
||||
```
|
||||
|
||||
### Slots Order
|
||||
|
||||
The tab and panel slots are ordered by DOM order.
|
||||
|
||||
This means you can switch the grouping in your `lea-tabs` from tab + panel to all tabs first or all panels first.
|
||||
|
||||
```js preview-story
|
||||
export const slotsOrder = () => html`
|
||||
<lea-tabs>
|
||||
<lea-tab slot="tab">Info</lea-tab>
|
||||
<lea-tab slot="tab">Work</lea-tab>
|
||||
<lea-tab-panel slot="panel"> Info page with lots of information about us. </lea-tab-panel>
|
||||
<lea-tab-panel slot="panel"> Work page that showcases our work. </lea-tab-panel>
|
||||
</lea-tabs>
|
||||
`;
|
||||
```
|
||||
|
||||
### Distribute New Elements
|
||||
|
||||
Below, we demonstrate on how you could dynamically add new tab + panels.
|
||||
|
||||
```js preview-story
|
||||
export const distributeNewElements = () => {
|
||||
const tagName = 'lea-tabs-experimental';
|
||||
if (!customElements.get(tagName)) {
|
||||
customElements.define(
|
||||
tagName,
|
||||
class extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
__collection: { type: Array },
|
||||
};
|
||||
}
|
||||
render() {
|
||||
return html`
|
||||
<h3>Append</h3>
|
||||
<button @click="${this.__handleAppendClick}">Append</button>
|
||||
<lea-tabs id="appendTabs">
|
||||
<lea-tab slot="tab">tab 1</lea-tab>
|
||||
<lea-tab-panel slot="panel">panel 1</lea-tab-panel>
|
||||
<lea-tab slot="tab">tab 2</lea-tab>
|
||||
<lea-tab-panel slot="panel">panel 2</lea-tab-panel>
|
||||
</lea-tabs>
|
||||
<hr />
|
||||
<h3>Push</h3>
|
||||
<button @click="${this.__handlePushClick}">Push</button>
|
||||
<lea-tabs id="pushTabs">
|
||||
<lea-tab slot="tab">tab 1</lea-tab>
|
||||
<lea-tab-panel slot="panel">panel 1</lea-tab-panel>
|
||||
<lea-tab slot="tab">tab 2</lea-tab>
|
||||
<lea-tab-panel slot="panel">panel 2</lea-tab-panel>
|
||||
${this.__collection.map(
|
||||
item => html`
|
||||
<lea-tab slot="tab">${item.button}</lea-tab>
|
||||
<lea-tab-panel slot="panel">${item.panel}</lea-tab-panel>
|
||||
`,
|
||||
)}
|
||||
</lea-tabs>
|
||||
`;
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
this.__collection = [];
|
||||
}
|
||||
__handleAppendClick() {
|
||||
const tabsElement = this.shadowRoot.querySelector('#appendTabs');
|
||||
const c = 2;
|
||||
const n = Math.floor(tabsElement.children.length / 2);
|
||||
for (let i = n + 1; i < n + c; i += 1) {
|
||||
const tab = document.createElement('lea-tab');
|
||||
tab.setAttribute('slot', 'tab');
|
||||
tab.innerText = `tab ${i}`;
|
||||
const panel = document.createElement('lea-tab-panel');
|
||||
panel.setAttribute('slot', 'panel');
|
||||
panel.innerText = `panel ${i}`;
|
||||
tabsElement.append(tab);
|
||||
tabsElement.append(panel);
|
||||
}
|
||||
}
|
||||
__handlePushClick() {
|
||||
const tabsElement = this.shadowRoot.querySelector('#pushTabs');
|
||||
const i = Math.floor(tabsElement.children.length / 2) + 1;
|
||||
this.__collection = [
|
||||
...this.__collection,
|
||||
{
|
||||
button: `tab ${i}`,
|
||||
panel: `panel ${i}`,
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
return html` <lea-tabs-experimental></lea-tabs-experimental> `;
|
||||
};
|
||||
```
|
||||
|
||||
One way is by creating the DOM elements and appending them as needed.
|
||||
|
||||
Inside your `lea-tabs` extension, an example for appending nodes on a certain button click:
|
||||
|
||||
```js
|
||||
__handleAppendClick() {
|
||||
const tabsAmount = this.children.length / 2;
|
||||
const tab = document.createElement('lea-tab');
|
||||
tab.setAttribute('slot', 'tab');
|
||||
tab.innerText = `tab ${tabsAmount + 1}`;
|
||||
const panel = document.createElement('lea-tab-panel');
|
||||
panel.setAttribute('slot', 'panel');
|
||||
panel.innerText = `panel ${tabsAmount + 1}`;
|
||||
this.append(tab);
|
||||
this.append(panel);
|
||||
}
|
||||
```
|
||||
|
||||
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 tabsAmount = this.children.length;
|
||||
myCollection = [
|
||||
...myCollection,
|
||||
{
|
||||
button: `tab ${tabsAmount + 1}`,
|
||||
panel: `panel ${tabsAmount + 1}`,
|
||||
},
|
||||
];
|
||||
renderMyCollection();
|
||||
}
|
||||
```
|
||||
|
||||
Make sure your template re-renders when myCollection is updated.
|
||||
|
||||
```html
|
||||
<lea-tabs id="pushTabs">
|
||||
${myCollection.map(item => html`
|
||||
<lea-tab slot="tab">${item.button}</lea-tab>
|
||||
<lea-tab-panel slot="panel">${item.panel}</lea-tab-panel>
|
||||
`)}
|
||||
</lea-tabs>
|
||||
```
|
||||
|
||||
## Rationale
|
||||
|
||||
### No separate active/focus state when using keyboard
|
||||
|
||||
We will immediately switch content as all our content comes from light dom (e.g. no latency)
|
||||
|
||||
See Note at <https://www.w3.org/TR/wai-aria-practices/#keyboard-interaction-19>
|
||||
|
||||
> It is recommended that tabs activate automatically when they receive focus as long as their
|
||||
> associated tab panels are displayed without noticeable latency. This typically requires tab
|
||||
> panel content to be preloaded.
|
||||
|
||||
### Panels are not focusable
|
||||
|
||||
Focusable elements should have a means to interact with them. Tab panels themselves do not offer any interactiveness.
|
||||
If there is a button or a form inside the tab panel then these elements get focused directly.
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import { LeaTabPanel } from './src/LeaTabPanel.js';
|
||||
|
||||
customElements.define('lea-tab-panel', LeaTabPanel);
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import { LeaTab } from './src/LeaTab.js';
|
||||
|
||||
customElements.define('lea-tab', LeaTab);
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
import { LeaTabs } from './src/LeaTabs.js';
|
||||
|
||||
customElements.define('lea-tabs', LeaTabs);
|
||||
4
docs/404.md
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
permalink: 404.html
|
||||
layout: layout-404
|
||||
---
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
# Coding Guidelines
|
||||
|
||||
```js script
|
||||
export default {
|
||||
title: 'Guidelines/Intro',
|
||||
};
|
||||
```
|
||||
|
||||
First be sure to understand our [definitions](?path=/docs/guidelines-definitions--page).
|
||||
|
||||
- [Guidelines for Styling](?path=/docs/guidelines-styling--page)
|
||||
- [Guidelines for Scoped Elements](?path=/docs/guidelines-scoped-elements--page)
|
||||
- [Guidelines for SubClasser APIs](?path=/docs/guidelines-subclasser-apis--page)
|
||||
BIN
docs/_assets/_static/icons/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
docs/_assets/_static/icons/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
docs/_assets/_static/icons/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 6.1 KiB |
BIN
docs/_assets/_static/icons/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 837 B |
BIN
docs/_assets/_static/icons/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
docs/_assets/_static/icons/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
39
docs/_assets/_static/icons/safari-pinned-tab.svg
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
||||
width="700.000000pt" height="700.000000pt" viewBox="0 0 700.000000 700.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<metadata>
|
||||
Created by potrace 1.11, written by Peter Selinger 2001-2013
|
||||
</metadata>
|
||||
<g transform="translate(0.000000,700.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
<path d="M2732 6067 c-12 -7 -62 -43 -111 -82 l-90 -70 -1 -91 c0 -87 -1 -91
|
||||
-30 -119 -17 -16 -28 -36 -26 -44 3 -9 8 -74 11 -146 4 -71 8 -141 10 -155 2
|
||||
-14 7 -83 10 -155 4 -71 8 -141 10 -155 2 -14 7 -79 10 -145 4 -66 8 -136 10
|
||||
-155 2 -19 6 -89 10 -155 4 -66 8 -136 10 -155 2 -19 7 -89 10 -155 4 -66 8
|
||||
-131 10 -145 1 -14 -9 -43 -23 -65 -15 -23 -26 -55 -26 -75 0 -38 10 -234 29
|
||||
-580 8 -139 11 -206 20 -370 4 -69 8 -150 10 -180 2 -30 7 -122 10 -205 4 -82
|
||||
9 -167 10 -188 3 -31 0 -37 -13 -33 -10 3 -33 8 -52 11 -19 3 -66 12 -105 20
|
||||
-38 8 -144 28 -235 45 -91 17 -208 40 -260 50 -52 11 -113 22 -135 26 -22 3
|
||||
-43 8 -46 9 -3 2 -28 7 -55 11 -27 3 -52 8 -55 10 -3 2 -21 6 -40 9 -19 3 -90
|
||||
16 -159 30 -69 13 -141 27 -160 30 -19 3 -78 14 -130 25 -52 10 -111 22 -130
|
||||
25 -19 3 -66 12 -105 20 -38 8 -86 17 -105 20 -19 3 -80 15 -135 25 -177 34
|
||||
-161 35 -263 -15 -72 -35 -92 -49 -92 -66 0 -33 58 -81 166 -137 250 -130 242
|
||||
-125 248 -158 6 -27 13 -33 60 -48 46 -14 55 -21 58 -43 4 -33 -5 -28 241
|
||||
-134 54 -23 95 -45 90 -48 -4 -4 -24 -19 -43 -33 -19 -14 -174 -127 -344 -252
|
||||
l-309 -228 -76 7 c-41 3 -78 8 -82 10 -3 3 -57 -25 -120 -61 -63 -36 -138 -80
|
||||
-167 -96 -29 -17 -52 -32 -50 -33 3 -4 628 -13 1123 -17 l260 -3 0 170 1 170
|
||||
93 125 c52 69 95 126 96 128 1 1 67 -14 146 -33 79 -20 155 -38 169 -41 14 -2
|
||||
32 -7 40 -10 8 -3 26 -8 40 -10 14 -3 36 -8 50 -13 14 -5 52 -15 85 -22 33 -7
|
||||
63 -15 68 -19 4 -3 -64 -55 -150 -114 -87 -59 -219 -149 -294 -200 -74 -51
|
||||
-144 -96 -154 -99 -10 -4 -15 -10 -12 -13 5 -5 5408 -6 5413 -1 2 1 -54 48
|
||||
-124 104 -228 183 -377 323 -497 464 -57 69 -239 344 -299 454 -10 18 -143
|
||||
241 -449 755 -64 107 -137 218 -163 245 -26 28 -86 92 -133 144 -47 52 -97
|
||||
106 -111 121 -93 100 -219 236 -239 259 -195 214 -241 257 -351 331 -97 65
|
||||
-146 109 -310 277 -171 177 -204 205 -267 237 -78 39 -62 21 -262 295 -146
|
||||
199 -142 196 -204 211 -50 12 -57 16 -63 44 -22 104 -90 254 -160 352 -116
|
||||
164 -306 278 -499 300 -27 3 -60 7 -71 9 -12 2 -31 -2 -42 -8z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
31
docs/_assets/logo.svg
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 457 457">
|
||||
<defs/>
|
||||
<g transform="translate(-247.653 -647.52)">
|
||||
<path fill="#65511b" d="M247.38 1008.44l91.25 1.03-.62-22.05 12.62-16.75 39.85 9.9-38.43 26.2-3.38 1.93 355.09-.12s-35.2-26.06-47.95-46.15c-12.91-20.32-49.38-82.24-49.38-82.24l-50-54.21-15.35-10.36-25.63-26.32-9.3-4.51-21.61-29.53-7.74-2.16s-6.81-44.22-50.2-45.2L413 718.61l-.27 12.01-3.4 2.93 6.63 102.33-3.47 5.94 5.5 103.31-136.33-26.07-12.37 5.75-.06 3.01 4.36 4.11 22.01 11.5 1.02 4.03 6.63 2.16 1.02 4.03 22.05 9.5-46.4 34.03-11.1-1.25-21.44 12.51z"/>
|
||||
<linearGradient id="a" x1="201.739" x2="210.647" y1="1781.71" y2="1778.468" gradientTransform="matrix(12.274 0 0 -67.886 -2104.537 121677.61)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#c19d3b"/>
|
||||
<stop offset="1" stop-color="#65511b"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#a)" d="M426.6 707.87l26.86 244.04-35.47-6.8-5.5-103.31 3.47-5.94-6.63-102.33 3.4-2.93.27-12.01 13.6-10.72z"/>
|
||||
<linearGradient id="b" x1="219.109" x2="219.562" y1="1780.966" y2="1778.31" gradientTransform="matrix(25.036 0 0 -12.792 -5195.276 23762.836)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#c19d3b"/>
|
||||
<stop offset="1" stop-color="#65511b"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#b)" d="M326.31 963.11l11.08 2.25-31.76 43.73-58.24-.65 21.43-12.55 11.1 1.25 46.39-34.03z"/>
|
||||
<linearGradient id="c" x1="226.508" x2="228.072" y1="1784.668" y2="1781.059" gradientTransform="matrix(31.819 0 0 -41.355 -6759.904 74504.36)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#c19d3b"/>
|
||||
<stop offset="1" stop-color="#65511b"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#c)" d="M476.8 753.07s-6.68 50.27-17.04 65.4c-7.3 9.04-13.26 19.08-17.71 29.82l5.88 53.44s9.29-18.86 56.63-45.86c14.68-8.37 35.85-10.22 51.87-29.91l-15.35-10.36-25.63-26.32-9.3-4.51-21.61-29.53-7.74-2.17z"/>
|
||||
<linearGradient id="d" x1="230.192" x2="231.598" y1="1783.099" y2="1780.414" gradientTransform="matrix(44.091 0 0 -35.032 -9687.025 63279.066)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#c19d3b"/>
|
||||
<stop offset="1" stop-color="#65511b"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#d)" d="M447.93 901.74s15.43-24.23 56.63-45.86c14.64-7.69 33.58-8.27 51.87-29.91l50 54.2a256.687 256.687 0 01-62.81 21.53c-27.95 5.39-41.53 15.55-50.61 23.37a276.64 276.64 0 01-39.54 26.84l-2.83-23.1-2.71-27.07z"/>
|
||||
<linearGradient id="e" x1="231.595" x2="232.99" y1="1785.571" y2="1779.909" gradientTransform="matrix(49.718 0 0 -21.1301 -11028.4 38569.195)" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0" stop-color="#c19d3b"/>
|
||||
<stop offset="1" stop-color="#65511b"/>
|
||||
</linearGradient>
|
||||
<path fill="url(#e)" d="M453.45 951.91a245.398 245.398 0 0038.42-25.75c9.08-7.81 21.55-18 49.5-23.39a272.307 272.307 0 0065.07-22.6l25.75 43.65c-43.55 6.04-82.95 26.21-103.07 29.77-37.18 6.57-75.67-1.68-75.67-1.68z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
23
docs/_assets/style.css
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
body[layout='layout-home'] .markdown-body .call-to-action:nth-of-type(2) {
|
||||
--primary-color: #222;
|
||||
--primary-color-lighter: #333;
|
||||
--primary-color-darker: #000;
|
||||
}
|
||||
|
||||
.markdown-body img {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
mdjs-preview {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
#main-header a[href="/blog/"] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1024px) {
|
||||
#main-header a[href="/blog/"] {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
41
docs/_assets/variables.css
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
html {
|
||||
--primary-color: #a07f23;
|
||||
--primary-color-lighter: #d1a62f;
|
||||
--primary-color-darker: #705918;
|
||||
--primary-color-accent: #cee5f6;
|
||||
--primary-text-color: #2c3e50;
|
||||
--primary-lines-color: #ccc;
|
||||
|
||||
/* Contrast colors */
|
||||
--contrast-color-light: #fff;
|
||||
--contrast-color-dark: #1d3557;
|
||||
|
||||
/* background-colors */
|
||||
--page-background: white;
|
||||
--footer-background: rgba(0, 0, 0, 0.1);
|
||||
|
||||
--text-color: black;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
--primary-color: #e63946;
|
||||
--primary-color-lighter: #e25761;
|
||||
--primary-color-darker: #a22831;
|
||||
--primary-color-accent: #cee5f6;
|
||||
--primary-text-color: #eee;
|
||||
|
||||
/* Contrast colors */
|
||||
--contrast-color-light: #fff;
|
||||
--contrast-color-dark: #1d3557;
|
||||
|
||||
/* background-colors */
|
||||
--page-background: #333;
|
||||
--footer-background: #4f4f4f;
|
||||
|
||||
--text-color: white;
|
||||
|
||||
--markdown-octicon-link: white;
|
||||
--markdown-syntax-background-color: #a0a0a0;
|
||||
--markdown-link-color: #fb7881;
|
||||
--markdown-blockquote-color: #c9e3ff;
|
||||
}
|
||||
41
docs/_data/footer.json
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
[
|
||||
{
|
||||
"name": "Discover",
|
||||
"children": [
|
||||
{
|
||||
"text": "Blog",
|
||||
"href": "/blog/"
|
||||
},
|
||||
{
|
||||
"text": "Help and Feedback",
|
||||
"href": "https://github.com/ing-bank/lion/issues"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Follow",
|
||||
"children": [
|
||||
{
|
||||
"text": "Github",
|
||||
"href": "https://github.com/ing-bank/lion"
|
||||
},
|
||||
{
|
||||
"text": "Twitter",
|
||||
"href": "https://twitter.com/daKmoR"
|
||||
},
|
||||
{
|
||||
"text": "Slack",
|
||||
"href": "/about/slack/"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Support",
|
||||
"children": [
|
||||
{
|
||||
"text": "Contribute",
|
||||
"href": "https://github.com/ing-bank/lion/blob/master/CONTRIBUTING.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
22
docs/_data/site.cjs
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
module.exports = async function () {
|
||||
return {
|
||||
dir: 'ltr',
|
||||
lang: 'en',
|
||||
name: 'Lion',
|
||||
description: 'Fundamental white label web components for building your design system',
|
||||
socialLinks: [
|
||||
{
|
||||
name: 'GitHub',
|
||||
url: 'https://github.com/ing-bank/lion',
|
||||
},
|
||||
],
|
||||
gitSiteUrl: 'https://github.com/ing-bank/lion',
|
||||
gitBranch: 'master',
|
||||
helpUrl: 'https://github.com/ing-bank/lion/issues',
|
||||
logoAlt: 'Lion Logo',
|
||||
iconColorMaskIcon: '#3f93ce',
|
||||
iconColorMsapplicationTileColor: '#1d3557',
|
||||
iconColorThemeColor: '#1d3557',
|
||||
analytics: 'G-151V7YV71K',
|
||||
};
|
||||
};
|
||||
5
docs/about/slack.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Slack
|
||||
|
||||
You can also find us on the Polymer Slack in the [#lion](https://polymer.slack.com/archives/CJGFWJN9J) channel.
|
||||
|
||||
You can join the Polymer Slack by visiting [https://www.polymer-project.org/slack-invite](https://www.polymer-project.org/slack-invite).
|
||||
173
docs/blog/controlling-exports.md
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
---
|
||||
title: Controlling exports
|
||||
published: true
|
||||
description: Maintainer can now define their public api of a package itself.
|
||||
date: 2021-03-09
|
||||
tags: [javascript, exports]
|
||||
cover_image: /blog/images/controlling-exports-cover-image.jpg
|
||||
---
|
||||
|
||||
When publishing npm packages it can often be hard to understand what users are actually using.
|
||||
|
||||
Basically, JavaScript allows you to write imports like this
|
||||
|
||||
```js
|
||||
import { addLeadingZero } '@lion/localize/src/date/utils/addLeadingZero.js';
|
||||
```
|
||||
|
||||
We as the maintainers of that package however consider this internal code, so any changes to it will not result in a new breaking change update.
|
||||
So if you depend on this directly then your code may break with any minor or patch update.
|
||||
|
||||
So why would we even "allow" such imports? Because so far there was no way to actually define and enforce what a maintainer considers to be the public API of the package. Now, with the introduction of node's [Package Entry Points](https://nodejs.org/api/packages.html#packages_package_entry_points) and the adoption of it in [@rollup/plugin-node-resolve](https://github.com/rollup/plugins/tree/master/packages/node-resolve#package-entrypoints) it can now be used in node, [@web/dev-server](https://modern-web.dev/docs/dev-server/overview/) and [rollup](https://rollupjs.org/).
|
||||
|
||||
How can you use those `Package Entry Points`?
|
||||
|
||||
Let's assume you have these two files in your `src` directory.
|
||||
|
||||
```js
|
||||
// src/index.js
|
||||
export { foo } from './public.js';
|
||||
|
||||
// src/public.js
|
||||
export const foo = 'public foo';
|
||||
|
||||
// src/internal.js
|
||||
export const bar = 'internal bar';
|
||||
```
|
||||
|
||||
If you publish the package "normally" then users will be able to write imports like this
|
||||
|
||||
```js
|
||||
import { foo } from 'my-pkg';
|
||||
import { foo } from 'my-pkg/src/public.js';
|
||||
import { bar } from 'my-pkg/src/internal.js';
|
||||
```
|
||||
|
||||
This has multiple issues, described in use cases:
|
||||
|
||||
1. Case 1: For maintenance purposes, we want to split `public.js` in `featureA.js` and `helpers.js`. Now all imports that use `import { foo } from 'my-pkg/src/public.js';` will break.
|
||||
2. Case 2: We found a package that solved what we did in `internal.js` in a more generic way. We don't treat it as public API, so we actually go ahead and get rid of this file. Now all imports for `import { bar } from 'my-pkg/src/internal.js';` will break.
|
||||
|
||||
Instead, what we actually want is all our consumers using the intended public API, which is
|
||||
|
||||
```js
|
||||
import { foo } from 'my-pkg';
|
||||
```
|
||||
|
||||
This way, above cases 1 and 2 just don't have any effect and we can freely refactor our codebase without introducing breaking changes. This means we can keep improving our code without disturbing our users. It's a win-win situation 🎉
|
||||
|
||||
Now, if someone tries to use a not defined export, like
|
||||
|
||||
```js
|
||||
import { bar } from 'my-pkg/src/internal.js';
|
||||
```
|
||||
|
||||
Then an error will be thrown
|
||||
|
||||
```
|
||||
Could not resolve import "my-pkg/src/internal.js"
|
||||
```
|
||||
|
||||
If a users needs access to `bar` then a GitHub Issue/Discussion should be opened to request it.
|
||||
Maintainers can then have a discussion if they want to make this part of the public API or not.
|
||||
|
||||
## Using consumer import in your own code
|
||||
|
||||
An additional benefit of using Package Entry Points is that you can write imports in the same way as your consumers.
|
||||
|
||||
So instead of writing demos or tests like
|
||||
|
||||
```js
|
||||
import { LionInput } from '../src/LionInput.js';
|
||||
```
|
||||
|
||||
we can now write
|
||||
|
||||
```js
|
||||
import { LionInput } from '@lion/input';
|
||||
```
|
||||
|
||||
This has the following benefits:
|
||||
|
||||
- We can make sure everything we are demoing/testing is actually part of the public API
|
||||
- Users can read / copy our demo code and it just works
|
||||
- We can move files around without needing to adjust our demos/docs/tests
|
||||
|
||||
## Exports for a single web component
|
||||
|
||||
Usage:
|
||||
|
||||
```js
|
||||
// only the classes
|
||||
import { MyElement } from 'my-element';
|
||||
|
||||
// OR
|
||||
|
||||
// execute customElements.define
|
||||
import 'my-element/define';
|
||||
```
|
||||
|
||||
Package Entry Points:
|
||||
|
||||
```json
|
||||
"exports": {
|
||||
".": "./src/index.js",
|
||||
"define": "./src/my-element.js",
|
||||
}
|
||||
```
|
||||
|
||||
## Exports for multiple web components
|
||||
|
||||
Usage:
|
||||
|
||||
```js
|
||||
// only the classes
|
||||
import { MyElement, SubElement } from 'my-element';
|
||||
|
||||
// OR
|
||||
|
||||
// execute customElements.define for all elements
|
||||
import 'my-element/define';
|
||||
|
||||
// execute customElements.define for a single element
|
||||
import 'my-element/define-my-element';
|
||||
import 'my-element/define-sub-element';
|
||||
```
|
||||
|
||||
Package Entry Points:
|
||||
|
||||
```json
|
||||
"exports": {
|
||||
".": "./src/index.js",
|
||||
"define": "./src/define.js",
|
||||
"define-my-element": "./src/my-element.js",
|
||||
"define-sub-element": "./src/sub-element.js",
|
||||
}
|
||||
```
|
||||
|
||||
in this case, the `src/define.js` should not contain any `customElements.define`, but instead it just imports the other define files
|
||||
|
||||
```js
|
||||
import 'my-element/define-my-element';
|
||||
import 'my-element/define-sub-element';
|
||||
```
|
||||
|
||||
## What does it mean for Lion?
|
||||
|
||||
Imports that worked before will need be be adjusted as they will no longer work.
|
||||
This is a breaking change.
|
||||
|
||||
```js
|
||||
// no longer works
|
||||
import '@lion/input/lion-input';
|
||||
import '@lion/input/lion-input.js';
|
||||
import { LionInput } from '@lion/input/src/LionInput.js';
|
||||
|
||||
// works
|
||||
import '@lion/input/define';
|
||||
import { LionInput } from '@lion/input';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
Photo by <a href="https://unsplash.com/@curology?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText">Curology</a> on <a href="https://unsplash.com/">Unsplash</a>
|
||||
|
|
@ -1,12 +1,13 @@
|
|||
# Extending Lion Documentation
|
||||
---
|
||||
title: Extending Lion Documentation
|
||||
published: true
|
||||
description: Extending a component library and its documentation for a speedy design system
|
||||
date: 2020-12-01
|
||||
tags: javascript, documentation, demos
|
||||
cover_image: https://miro.medium.com/max/2000/1*NZ6tdtJHHJjxtPmIFxWpGw.jpeg
|
||||
---
|
||||
|
||||
```js script
|
||||
export default {
|
||||
title: 'Guidelines/Extending documentation',
|
||||
};
|
||||
```
|
||||
|
||||
If you extend [Lion](https://lion-web-components.netlify.app/) components, you don't only want to reuse the components, but you probably want to reuse the documentation (Storybook demos) as well. Wouldn't it be nice to just take it all from lion, but replace it with your own design system extension, so you don't have the extra maintenance of essentially copying the docs from `Lion` for your own design system implementation?
|
||||
If you extend [Lion](https://lion-web.netlify.app/) components, you don't only want to reuse the components, but you probably want to reuse the documentation (Storybook demos) as well. Wouldn't it be nice to just take it all from lion, but replace it with your own design system extension, so you don't have the extra maintenance of essentially copying the docs from `Lion` for your own design system implementation?
|
||||
|
||||
In this blog we will explain how `Lion` supports this use case, and allows you to extend not just the components, but also the documentation.
|
||||
|
||||
|
|
@ -29,13 +30,13 @@ For step 1, we can use `@open-wc/demoing-storybook` version 2 or higher, which u
|
|||
|
||||
Install it manually (and see the docs for configuring):
|
||||
|
||||
```sh
|
||||
```bash
|
||||
npm i @open-wc/demoing-storybook --save-dev
|
||||
```
|
||||
|
||||
Or scaffold it with basic configuration by doing
|
||||
|
||||
```sh
|
||||
```bash
|
||||
npm init @open-wc
|
||||
```
|
||||
|
||||
|
|
@ -66,11 +67,11 @@ This step alone should already give you the `LionTabs` docs inside your own Stor
|
|||
|
||||
Potentially the hardest part is to analyse your extension `LeaTabs`, and to figure out how we should transform the import paths for `LionTabs` to new paths to your `LeaTabs`.
|
||||
|
||||
To do this we make use of [Providence](https://lion-web-components.netlify.app/?path=/docs/tools-providence-main--run-providence). This tool has a command that creates a full map of all the import paths of a reference project (`Lion`) and can replace them with the correct paths of a target project (`Lea`).
|
||||
To do this we make use of [Providence](https://lion-web.netlify.app/?path=/docs/tools-providence-main--run-providence). This tool has a command that creates a full map of all the import paths of a reference project (`Lion`) and can replace them with the correct paths of a target project (`Lea`).
|
||||
|
||||
So lets install it:
|
||||
|
||||
```sh
|
||||
```bash
|
||||
npm i providence-analytics --save-dev
|
||||
```
|
||||
|
||||
|
|
@ -86,7 +87,7 @@ The `--prefix-from` and `--prefix-to` are the prefixes of the project you extend
|
|||
|
||||
If you know you only use a single component from lion, you can reduce the time the tool needs for analysis, by specifying this package `-r 'node_modules/@lion/tabs'`.
|
||||
|
||||
Running the script will create a `providence-extend-docs-data.json` file, with all from/to information. You can change the name / location of the output file, refer to [Providence Documentation](https://lion-web-components.netlify.app/?path=/docs/tools-providence-main--run-providence) for this.
|
||||
Running the script will create a `providence-extend-docs-data.json` file, with all from/to information. You can change the name / location of the output file, refer to [Providence Documentation](https://lion-web.netlify.app/?path=/docs/tools-providence-main--run-providence) for this.
|
||||
|
||||
#### Running it automatically when upgrading lion dependency
|
||||
|
||||
|
|
@ -103,13 +104,13 @@ Inside ING, our design system also makes use of this providence tool to create t
|
|||
|
||||
Now that we have a JSON file with all the information we need to know about to replace import paths and tagnames inside templates, we can start transforming the `LionTabs` documentation to `LeaTabs` documentation.
|
||||
|
||||
For this, we created a `babel-plugin` called [babel-plugin-extend-docs](https://lion-web-components.netlify.app/?path=/docs/tools-babelpluginextenddocs--page).
|
||||
For this, we created a `babel-plugin` called [babel-plugin-extend-docs](https://lion-web.netlify.app/?path=/docs/tools-babelpluginextenddocs--page).
|
||||
|
||||
This will analyse the JavaScript script and story content inside the markdown files, which uses [MDJS](https://open-wc.org/mdjs/) syntax, and transform it on the fly in `es-dev-server`, as well as on rollup build for production.
|
||||
|
||||
So all you need to do is to install this plugin:
|
||||
|
||||
```sh
|
||||
```bash
|
||||
npm i babel-plugin-extend-docs --save-dev
|
||||
```
|
||||
|
||||
|
|
@ -164,7 +165,7 @@ In some cases you don't want to show all examples of how to use a component. Som
|
|||
|
||||
In our example, we will show you have to remove the `Rationale` section that you would normally inherit from the `Lion` documentation.
|
||||
|
||||
For this step we make use of a remark plugin for the MD content, similar to how you would use a babel plugin for JS content. It is called [Remark extend](https://lion-web-components.netlify.app/?path=/docs/tools-remark-extend--page).
|
||||
For this step we make use of a remark plugin for the MD content, similar to how you would use a babel plugin for JS content. It is called [Remark extend](https://lion-web.netlify.app/?path=/docs/tools-remark-extend--page).
|
||||
It will let you add, remove or replace sections or specific words.
|
||||
|
||||
First of all we need to add the plugin to the `.storybook/main.js`:
|
||||
|
|
@ -256,7 +257,7 @@ Or you can add an extra paragraph below the content. Create a fenced codeblock:
|
|||
::removeMdAfter(':scope:last-child')
|
||||
```
|
||||
|
||||
> See [Remark extend](https://lion-web-components.netlify.app/?path=/docs/tools-remark-extend--page) for more information
|
||||
> See [Remark extend](https://lion-web.netlify.app/?path=/docs/tools-remark-extend--page) for more information
|
||||
|
||||
### Lea Tabs Special Feature
|
||||
|
||||
124
docs/blog/extending-lions-website.md
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
---
|
||||
title: Extending lions website
|
||||
published: false
|
||||
description: A static website with docs and demos for lion
|
||||
date: 2021-03-10
|
||||
tags: [javascript, rocket, documentation]
|
||||
cover_image: /blog/images/introducing-lions-website-cover-image.jpg
|
||||
---
|
||||
|
||||
After a month of preparations we can finally present to you our new website. With it we are enabled to give more context to each of our components.
|
||||
Right now it's more or less a port for our existing demos from storybook. But we can organize it in a nicer way by splitting it into components, docs, guides and blog sections.
|
||||
|
||||
## Importing Content into Markdown files
|
||||
|
||||
We now use a system to import content from one markdown file into another.
|
||||
So let's say you find the documentation of `input-amount` useful and you want to present it on your page as well.
|
||||
Anywhere in your documentation you can now write.
|
||||
|
||||
👉 `docs/input-amount.md`
|
||||
|
||||
````md
|
||||
# Input Amount
|
||||
|
||||
```js ::import('@lion/input-amount/docs/overview.md', 'heading[depth=1] ~ *')
|
||||
|
||||
```
|
||||
````
|
||||
|
||||
So when you now go to `https://domain.com/input-amount/` you will actually see the content from `@lion/input-amount/docs/overview.md`.
|
||||
|
||||
Why is it a `js code block`?
|
||||
|
||||
- You can define a start and end for what should be imported (using [unist-util-select](https://github.com/syntax-tree/unist-util-select#support))
|
||||
- You can add adjustments to the content as a function
|
||||
- As links like `[go there](@lion/input-amount/docs/overview.md)` would not work anyways, having one syntax that allows for additional features is enough
|
||||
|
||||
### Importing Partial Content
|
||||
|
||||
Quite often you probably don't want to get the full file, so there is a special helper for that.
|
||||
|
||||
Let's assume you have the following source file
|
||||
|
||||
```md
|
||||
# First Headline
|
||||
|
||||
Content of first headline
|
||||
|
||||
## Second Headline
|
||||
|
||||
Content of second headline
|
||||
|
||||
## Third Headline
|
||||
|
||||
Content of Third headline
|
||||
```
|
||||
|
||||
and you only want to get the 2nd "block" e.g. 2nd headline + text.
|
||||
|
||||
With `importBlock` you can get exactly that.
|
||||
|
||||
A block starts with a headline and ends when the next headline of an equal level starts.
|
||||
|
||||
Note: importBlock is a faster way of writing imports for headlines
|
||||
|
||||
```md
|
||||
::importBlock('./path/to/file.md', '## red')
|
||||
// is the same as
|
||||
::import('./path/to/file.md', 'heading[depth=2]:has([value=red])', 'heading[depth=2]:has([value=red]) ~heading[depth=2]')
|
||||
```
|
||||
|
||||
If you want to know more please look at the documentation for [remark-extend](../docs/node-tools/remark-extend/overview.md).
|
||||
|
||||
## Upgrading Documentation
|
||||
|
||||
Unfortunately this is quite a different concept then what we used with storybook before. Luckily the content is very much the same.
|
||||
|
||||
Let's convert an example page
|
||||
|
||||
### FROM
|
||||
|
||||
````md
|
||||
# Calendar
|
||||
|
||||
`lion-calendar` is a reusable and accessible calendar view. It depends on [calendar](?path=/docs/calendar--default-story).
|
||||
|
||||
```js script
|
||||
import { html, css } from '@lion/core';
|
||||
import './lion-calendar.js';
|
||||
|
||||
export default {
|
||||
title: 'Others/Calendar',
|
||||
};
|
||||
```
|
||||
|
||||
...
|
||||
````
|
||||
|
||||
### TO
|
||||
|
||||
````md
|
||||
# Component >> Calendar ||20
|
||||
|
||||
`lion-calendar` is a reusable and accessible calendar view. It depends on [calendar](../../path/to/calendar.md).
|
||||
|
||||
```js script
|
||||
import { html, css } from '@lion/core';
|
||||
import '@lion/calendar/define';
|
||||
```
|
||||
|
||||
...
|
||||
````
|
||||
|
||||
So what you need to do:
|
||||
|
||||
1. Remove the js default export and put the title / navigation into the headline
|
||||
2. Replace all imports with the Package Entry Points
|
||||
3. Adjust all link to be relative links to actual files (instead of storybook specific urls)
|
||||
|
||||
## Upgrading Extending Documentation
|
||||
|
||||
If you are currently extending our storybook documentation then this will no longer work.
|
||||
For now we will need to ask you to stay on the current version and NOT upgrade.
|
||||
|
||||
We will release the necessary tools to extend our Lion Website in the upcoming weeks 🤗
|
||||
BIN
docs/blog/images/controlling-exports-cover-image.jpg
Normal file
|
After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 247 KiB After Width: | Height: | Size: 247 KiB |
BIN
docs/blog/images/introducing-lions-website-cover-image.jpg
Normal file
|
After Width: | Height: | Size: 15 KiB |
14
docs/blog/index.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
---
|
||||
title: Lion Blog
|
||||
layout: layout-blog-overview
|
||||
eleventyNavigation:
|
||||
key: Blog
|
||||
order: 40
|
||||
pagination:
|
||||
data: collections.blog
|
||||
size: 10
|
||||
reverse: true
|
||||
alias: posts
|
||||
---
|
||||
|
||||
Discover articles from the core team and contributors about Lion, tips and tricks included!
|
||||
|
|
@ -1,10 +1,11 @@
|
|||
# ING open sources Lion: A library of performant, accessible & flexible Web Components
|
||||
|
||||
```js script
|
||||
export default {
|
||||
title: 'Intro/Announcement',
|
||||
};
|
||||
```
|
||||
---
|
||||
title: ING open sources Lion
|
||||
published: true
|
||||
description: A library of performant, accessible & flexible Web Components
|
||||
date: 2020-08-10
|
||||
tags: [javascript, tests, demos]
|
||||
cover_image: https://miro.medium.com/max/1400/1*FT8CF6G-1IVa88G04nkf5w.png
|
||||
---
|
||||
|
||||
**TL;DR:** Web development can be hard, whether you're making your own components, implementing Design Systems, support many different browsers, incorporating accessibility, or adding third party dependencies. Lion aims to make your life a little bit easier, by taking the groundwork of feature complete, accessible, performant, and framework agnostic components out of your hands! Check out the repo at [ing-bank/lion](https://github.com/ing-bank/lion).
|
||||
|
||||
|
|
@ -79,9 +80,9 @@ Lion is a core package of white label Web Components. What this means is that th
|
|||
|
||||
And this is exactly what we at ING do as well. Our very own ing-web components extend the Lion components and apply our own ING visual identity which mostly is a thin layer on top of Lion.
|
||||
|
||||
Check out the [Lion demo's](http://lion-web-components.netlify.com/). Looks plain, doesn't it? And now compare Lion to ing-web:
|
||||
Check out the [Lion demo's](http://lion-web.netlify.app/). Looks plain, doesn't it? And now compare Lion to ing-web:
|
||||
|
||||

|
||||

|
||||
|
||||
### 🎯 Focus
|
||||
|
||||
|
|
@ -149,7 +150,7 @@ npm i lit-element @lion/tabs
|
|||
Create a `lea-tabs` component by reusing the functionality of Lion. This gives Lea all the functionality and accessible core that she needs for his custom tabs component.
|
||||
|
||||
```js
|
||||
import { css } from '@lion/core';
|
||||
import { css } from 'lit-element';
|
||||
import { LionTabs } from '@lion/tabs';
|
||||
|
||||
export class LeaTabs extends LionTabs {
|
||||
|
|
@ -178,7 +179,7 @@ customElements.define('lea-tabs', LeaTabs);
|
|||
Lea also wants to be able to style the tab and tab-panel according to Betatechs visual identity. In order to do so, she creates a `lea-tab-panel` component and a `lea-tab` component, which she can then fully style however she desires, and eventually place inside the `lea-tabs` component. You can see how Lea achieved this in the example down below.
|
||||
|
||||
```js
|
||||
import { LitElement, html, css } from '@lion/core';
|
||||
import { LitElement, html, css } from 'lit-element';
|
||||
|
||||
export class LeaTab extends LitElement {
|
||||
static get styles() {
|
||||
|
|
@ -209,7 +210,7 @@ Excellent! Lea can now use the tabs component like so:
|
|||
</lea-tabs>
|
||||
```
|
||||
|
||||
There we go, Lea's component is already done, so let's write some documentation. See the [live Lea tabs documentation page](?path=/docs/intro-tabs-example--default-story). You can see the full code of `lea-tabs` [on github](https://github.com/ing-bank/lion/tree/master/demo/).
|
||||
There we go, Lea's component is already done, so let's write some documentation. See the [live Lea tabs documentation page](../components/content/tabs/examples.md). You can see the full code of `lea-tabs` [on github](https://github.com/ing-bank/lion/tree/master/demo/).
|
||||
|
||||
P.S.: Do note that Lea is now responsible for keeping the documentation of `lea-tabs` up to date herself, and improvements on Lion's documentation will not automatically be reflected on Lea's documentation.
|
||||
|
||||
|
|
@ -223,7 +224,7 @@ Component libraries are in huge demand. By open-sourcing our extendable componen
|
|||
|
||||
Building applications is hard, and sometimes, you need a little bit more than just the right component alone, but also things like: Validation, Forms, Overlays, Localization, etc. But fear not; Lion has got you covered!
|
||||
|
||||
You can check them out in our [documentation](http://lion-web-components.netlify.com/), and we'll go into more depth about Lion's additional systems in future blog posts.
|
||||
You can check them out in our [documentation](http://lion-web.netlify.app/), and we'll go into more depth about Lion's additional systems in future blog posts.
|
||||
|
||||
## Thanks
|
||||
|
||||
110
docs/blog/introducing-lions-website.md
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
---
|
||||
title: Introducing lions website
|
||||
published: true
|
||||
description: A static website with docs and demos for lion
|
||||
date: 2021-03-10
|
||||
tags: [javascript, rocket, documentation]
|
||||
cover_image: /blog/images/introducing-lions-website-cover-image.jpg
|
||||
---
|
||||
|
||||
After a month of preparations, we can finally present to you our new website. With it, we are enabled to give more context to each of our components.
|
||||
Right now it's more or less a port for our existing demos from storybook. But we can organize it in a nicer way by splitting it into components, docs, guides and blog sections.
|
||||
|
||||
## Meet the new sections
|
||||
|
||||
1. [Guides](../guides/index.md) <br>
|
||||
A dedicated section where we will teach you about how to get started with lion. This section is completely new and will grow over time.
|
||||
2. [Components](../components/index.md) <br>
|
||||
Here you will find our documentation for each of our components. Each is split into two pages namely Overview and Features. We also plan to add an API page soonish.
|
||||
3. [Docs](../docs/index.md) <br>
|
||||
This is the home for general documentation which includes the fundamental systems all our components are build upon and various tools we use in the frontend or backend.
|
||||
4. [Blog](./index.md) <br>
|
||||
We now have a dedicated section about all our blog posts. Take a peek and follow our story.
|
||||
|
||||
## Upgrading Our Documentation
|
||||
|
||||
As this page is now a static website and no longer storybook we needed to convert all our documentation.
|
||||
Luckily the format is very similar.
|
||||
|
||||
Let's convert an example page
|
||||
|
||||
### FROM
|
||||
|
||||
````md
|
||||
# Calendar
|
||||
|
||||
`lion-calendar` is a reusable and accessible calendar view. It depends on [calendar](?path=/docs/calendar--default-story).
|
||||
|
||||
```js script
|
||||
import { html, css } from '@lion/core';
|
||||
import './lion-calendar.js';
|
||||
|
||||
export default {
|
||||
title: 'Others/Calendar',
|
||||
};
|
||||
```
|
||||
|
||||
...
|
||||
````
|
||||
|
||||
### TO
|
||||
|
||||
````md
|
||||
# Component >> Calendar ||20
|
||||
|
||||
`lion-calendar` is a reusable and accessible calendar view. It depends on [calendar](../../path/to/calendar.md).
|
||||
|
||||
```js script
|
||||
import { html, css } from '@lion/core';
|
||||
import '@lion/calendar/define';
|
||||
```
|
||||
|
||||
...
|
||||
````
|
||||
|
||||
So what we needed to do:
|
||||
|
||||
1. Remove the js default export and put the title / navigation into the headline
|
||||
2. Replace all imports with the Package Entry Points
|
||||
3. Adjust all link to be relative links to actual files (instead of storybook specific urls)
|
||||
|
||||
## Handling Mono Repo Documentation
|
||||
|
||||
All of our documentation now resides in the root `docs` folder. To publish them with our components we added a tool that can copy content and files into our published package.
|
||||
|
||||
Let's say you have this file in your documentation.
|
||||
|
||||
👉 `docs/components/accordion/overview.md`
|
||||
|
||||
```
|
||||
# Accordion
|
||||
|
||||
Is a very useful...
|
||||
```
|
||||
|
||||
Now you want to make sure it gets published with your accordion package so you replace you Readme file with this
|
||||
|
||||
👉 `packages/accordion/README.md`
|
||||
|
||||
```
|
||||
# Accordion
|
||||
|
||||
[=> See Source <=](../../docs/components/content/accordion/overview.md)
|
||||
```
|
||||
|
||||
Now by calling `publish-docs` within the `prepublishOnly` step your Readme file will contain the content of its source.
|
||||
|
||||
The benefits of this approach are
|
||||
|
||||
- Readme still makes sense on GitHub (e.g. you can navigate to the package and with one click you are at the docs)
|
||||
- The published readme contains all the documentation you need
|
||||
- All links are version safe (e.g. if you look at v0.5 it will link to the GitHub Pages at this time)
|
||||
|
||||
If you want to know more please look at the documentation for [publish-docs](../docs/node-tools/publish-docs/overview.md).
|
||||
|
||||
## Upgrading Extending Documentation
|
||||
|
||||
If you are currently extending our storybook documentation then this will no longer work.
|
||||
For now, we will need to ask you to stay on the current version and NOT upgrade.
|
||||
|
||||
We will release the necessary tools to extend our Lion Website in the upcoming weeks 🤗
|
||||
9
docs/browserconfig.xml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<TileColor>#1d3557</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
214
docs/components/content/accordion/features.md
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
# Content >> Accordion >> Features ||20
|
||||
|
||||
```js script
|
||||
import { LitElement, html } from '@lion/core';
|
||||
|
||||
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>
|
||||
```
|
||||
3
docs/components/content/accordion/index.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Content >> Accordion
|
||||
|
||||
-> go to Overview
|
||||
52
docs/components/content/accordion/overview.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Content >> Accordion >> Overview ||10
|
||||
|
||||
`lion-accordion` is a component used to toggle the display of sections of content.
|
||||
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
|
||||
import { html } from '@lion/core';
|
||||
import '@lion/accordion/define';
|
||||
```
|
||||
|
||||
```js preview-story
|
||||
export const main = () => 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>
|
||||
`;
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- content gets provided by users (slotted in)
|
||||
- handles accessibility
|
||||
- support navigation via keyboard
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i --save @lion/accordion
|
||||
```
|
||||
|
||||
```js
|
||||
import { LionAccordion } from '@lion/accordion';
|
||||
// or
|
||||
import '@lion/accordion/define';
|
||||
```
|
||||
|
||||
## 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.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { LionCollapsible } from '../index.js';
|
||||
import { LionCollapsible } from '@lion/collapsible';
|
||||
|
||||
const EVENT = {
|
||||
TRANSITION_END: 'transitionend',
|
||||
|
|
@ -8,8 +8,8 @@ const EVENT = {
|
|||
* `CustomCollapsible` is a class for custom collapsible element (`<custom-collapsible>` web component).
|
||||
* @customElement custom-collapsible
|
||||
*/
|
||||
// @ts-expect-error false positive for incompatible static get properties. Lit-element merges super properties already for you.
|
||||
export class CustomCollapsible extends LionCollapsible {
|
||||
/** @type {any} */
|
||||
static get properties() {
|
||||
return {
|
||||
transitioning: {
|
||||
|
|
@ -56,9 +56,7 @@ export class CustomCollapsible extends LionCollapsible {
|
|||
contentNode.style.setProperty('opacity', '1');
|
||||
contentNode.style.setProperty('padding', '12px 0');
|
||||
contentNode.style.setProperty('max-height', '0px');
|
||||
await /** @type {Promise<void>} */ (new Promise(resolve =>
|
||||
requestAnimationFrame(() => resolve()),
|
||||
));
|
||||
await new Promise(resolve => requestAnimationFrame(() => resolve()));
|
||||
contentNode.style.setProperty('max-height', expectedHeight);
|
||||
await this._waitForTransition({ contentNode });
|
||||
}
|
||||
|
|
@ -107,9 +105,9 @@ export class CustomCollapsible extends LionCollapsible {
|
|||
*/
|
||||
async __calculateHeight(contentNode) {
|
||||
contentNode.style.setProperty('max-height', '');
|
||||
await /** @type {Promise<void>} */ (new Promise(resolve =>
|
||||
requestAnimationFrame(() => resolve()),
|
||||
));
|
||||
await new Promise(resolve => requestAnimationFrame(() => resolve()));
|
||||
return this._contentHeight; // Expected height i.e. actual size once collapsed after animation
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('custom-collapsible', CustomCollapsible);
|
||||
83
docs/components/content/collapsible/examples.md
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
# Content >> Collapsible >> Examples ||30
|
||||
|
||||
```js script
|
||||
import { html } from '@lion/core';
|
||||
import '@lion/collapsible/define';
|
||||
import '@lion/button/define';
|
||||
import './assets/CustomCollapsible.js';
|
||||
import './assets/applyDemoCollapsibleStyles.js';
|
||||
```
|
||||
|
||||
## Custom Invoker Template
|
||||
|
||||
A custom template can be specified to the `invoker` slot. It can be any button or custom component which mimics the button behavior for better accessibility support. In the below example, `lion-button` and native `button` with styling is used as a collapsible invoker.
|
||||
|
||||
```js preview-story
|
||||
export const customInvokerTemplate = () => html`
|
||||
<lion-collapsible style="margin-top:16px;">
|
||||
<lion-button slot="invoker">More about cars</lion-button>
|
||||
<div slot="content">
|
||||
Most definitions of cars say that they run primarily on roads, seat one to eight people, have
|
||||
four tires, and mainly transport people rather than goods.
|
||||
</div>
|
||||
</lion-collapsible>
|
||||
`;
|
||||
```
|
||||
|
||||
## Extended collapsible with animation
|
||||
|
||||
`LionCollapsible` can easily be extended to add more features in the component, like animation for example.
|
||||
|
||||
```js preview-story
|
||||
export const customAnimation = () => html`
|
||||
<div class="demo-custom-collapsible-container">
|
||||
<div class="demo-custom-collapsible-body">
|
||||
A motorcycle, often called a motorbike, bike, or cycle, is a two- or three-wheeled motor
|
||||
vehicle.
|
||||
</div>
|
||||
<custom-collapsible>
|
||||
<button class="demo-custom-collapsible-invoker" slot="invoker">MORE ABOUT MOTORCYCLES</button>
|
||||
<div slot="content">
|
||||
Motorcycle design varies greatly to suit a range of different purposes: long distance
|
||||
travel, commuting, cruising, sport including racing, and off-road riding. Motorcycling is
|
||||
riding a motorcycle and related social activity such as joining a motorcycle club and
|
||||
attending motorcycle rallies.
|
||||
</div>
|
||||
</custom-collapsible>
|
||||
</div>
|
||||
<div class="demo-custom-collapsible-container">
|
||||
<div class="demo-custom-collapsible-body">
|
||||
A car (or automobile) is a wheeled motor vehicle used for transportation.
|
||||
</div>
|
||||
<custom-collapsible opened>
|
||||
<button class="demo-custom-collapsible-invoker" slot="invoker">MORE ABOUT CARS</button>
|
||||
<div slot="content">
|
||||
Most definitions of cars say that they run primarily on roads, seat one to eight people,
|
||||
have four tires, and mainly transport people rather than goods.
|
||||
</div>
|
||||
</custom-collapsible>
|
||||
</div>
|
||||
`;
|
||||
```
|
||||
|
||||
Use `_showAnimation()` and `_hideAnimation()` methods to customize open and close behavior. Check the code for a full example of a `custom-collapsible`.
|
||||
|
||||
```js
|
||||
_showAnimation({ contentNode }) {
|
||||
const expectedHeight = await this.__calculateHeight(contentNode);
|
||||
contentNode.style.setProperty('opacity', '1');
|
||||
contentNode.style.setProperty('padding', '12px 0');
|
||||
contentNode.style.setProperty('max-height', '0px');
|
||||
await new Promise(resolve => requestAnimationFrame(() => resolve()));
|
||||
contentNode.style.setProperty('max-height', expectedHeight);
|
||||
await this._waitForTransition({ contentNode });
|
||||
}
|
||||
|
||||
_hideAnimation({ contentNode }) {
|
||||
if (this._contentHeight === '0px') {
|
||||
return;
|
||||
}
|
||||
['opacity', 'padding', 'max-height'].map(prop => contentNode.style.setProperty(prop, 0));
|
||||
await this._waitForTransition({ contentNode });
|
||||
}
|
||||
```
|
||||
79
docs/components/content/collapsible/features.md
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# Content >> Collapsible >> Features ||20
|
||||
|
||||
```js script
|
||||
import { html } from '@lion/core';
|
||||
import '@lion/collapsible/define';
|
||||
```
|
||||
|
||||
## Default open
|
||||
|
||||
Add the `opened` attribute to keep the component default open.
|
||||
|
||||
```js preview-story
|
||||
export const defaultOpen = () => html`
|
||||
<lion-collapsible opened>
|
||||
<button slot="invoker">More about cars</button>
|
||||
<div slot="content">
|
||||
Most definitions of cars say that they run primarily on roads, seat one to eight people, have
|
||||
four tires, and mainly transport people rather than goods.
|
||||
</div>
|
||||
</lion-collapsible>
|
||||
`;
|
||||
```
|
||||
|
||||
## Methods
|
||||
|
||||
There are the following methods available to control the extra content for the collapsible.
|
||||
|
||||
- `toggle()`: toggle the extra content
|
||||
- `show()`: show the extra content
|
||||
- `hide()`: hide the extra content
|
||||
|
||||
```js preview-story
|
||||
export const methods = ({ shadowRoot }) => html`
|
||||
<lion-collapsible id="car-collapsible">
|
||||
<button slot="invoker">More about cars</button>
|
||||
<div slot="content">
|
||||
Most definitions of cars say that they run primarily on roads, seat one to eight people, have
|
||||
four tires, and mainly transport people rather than goods.
|
||||
</div>
|
||||
</lion-collapsible>
|
||||
<section style="margin-top:16px">
|
||||
<button @click=${() => shadowRoot.querySelector('#car-collapsible').toggle()}>
|
||||
Toggle content
|
||||
</button>
|
||||
<button @click=${() => shadowRoot.querySelector('#car-collapsible').show()}>
|
||||
Show content
|
||||
</button>
|
||||
<button @click=${() => shadowRoot.querySelector('#car-collapsible').hide()}>
|
||||
Hide content
|
||||
</button>
|
||||
</section>
|
||||
`;
|
||||
```
|
||||
|
||||
## Events
|
||||
|
||||
`lion-collapsible` fires an event on `invoker` click to notify the component's current state. It is useful for analytics purposes or to perform some actions while expanding and collapsing the component.
|
||||
|
||||
- `@opened-changed`: triggers when collapsible either gets opened or closed
|
||||
|
||||
```js preview-story
|
||||
export const events = ({ shadowRoot }) => html`
|
||||
<div class="demo-custom-collapsible-state-container">
|
||||
<strong id="collapsible-state"></strong>
|
||||
</div>
|
||||
<lion-collapsible
|
||||
@opened-changed=${ev => {
|
||||
const collapsibleState = shadowRoot.getElementById('collapsible-state');
|
||||
collapsibleState.innerText = `Opened: ${ev.target.opened}`;
|
||||
}}
|
||||
>
|
||||
<button slot="invoker">More about cars</button>
|
||||
<div slot="content">
|
||||
Most definitions of cars say that they run primarily on roads, seat one to eight people, have
|
||||
four tires, and mainly transport people rather than goods.
|
||||
</div>
|
||||
</lion-collapsible>
|
||||
`;
|
||||
```
|
||||
3
docs/components/content/collapsible/index.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Content >> Collapsible
|
||||
|
||||
-> go to Overview
|
||||
39
docs/components/content/collapsible/overview.md
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Content >> Collapsible >> Overview ||10
|
||||
|
||||
`lion-collapsible` is a combination of a button (the invoker), a chunk of 'extra content', and can be extended with an animation to disclose the extra content. There are two slots available respectively; `invoker` to specify the collapsible's invoker and `content` for the extra content of the collapsible.
|
||||
|
||||
```js script
|
||||
import { html } from '@lion/core';
|
||||
import '@lion/collapsible/define';
|
||||
```
|
||||
|
||||
```js preview-story
|
||||
export const main = () => html`
|
||||
<lion-collapsible>
|
||||
<button slot="invoker">More about cars</button>
|
||||
<div slot="content">
|
||||
Most definitions of cars say that they run primarily on roads, seat one to eight people, have
|
||||
four tires, and mainly transport people rather than goods.
|
||||
</div>
|
||||
</lion-collapsible>
|
||||
`;
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- Use `opened` attribute or `toggle()` method to render default open
|
||||
- `invoker` slot can be custom template e.g. `lion-button` or native `button` with custom styling
|
||||
- Observe the state with the help of `@opened-changed` event
|
||||
- `show()` and `hide()` are helper methods to hide or show the content from outside
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i --save @lion/collapsible
|
||||
```
|
||||
|
||||
```js
|
||||
import { LionCollapsible } from '@lion/collapsible';
|
||||
// or
|
||||
import '@lion/collapsible/define';
|
||||
```
|
||||
1
docs/components/content/index.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Content ||10
|
||||
|
|
@ -1,26 +1,26 @@
|
|||
import { svg, css } from '@lion/core';
|
||||
import { LionProgressIndicator } from '../index.js';
|
||||
import { html, css } from '@lion/core';
|
||||
import { LionProgressIndicator } from '@lion/progress-indicator';
|
||||
|
||||
export class CustomProgressIndicator extends LionProgressIndicator {
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
:host {
|
||||
display: inline-block;
|
||||
display: block;
|
||||
}
|
||||
|
||||
svg {
|
||||
animation: spinner-rotate 2s linear infinite;
|
||||
.progress--icon {
|
||||
display: inline-block;
|
||||
height: 48px;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
animation: spinner-rotate 2s linear infinite;
|
||||
}
|
||||
|
||||
circle {
|
||||
.progress--icon--circle {
|
||||
animation: spinner-dash 1.35s ease-in-out infinite;
|
||||
fill: none;
|
||||
stroke-width: 3.6;
|
||||
stroke: firebrick;
|
||||
stroke-width: 6px;
|
||||
stroke: var(--primary-color);
|
||||
stroke-dasharray: 100, 28; /* This is a fallback for IE11 */
|
||||
}
|
||||
|
||||
|
|
@ -49,8 +49,12 @@ export class CustomProgressIndicator extends LionProgressIndicator {
|
|||
}
|
||||
|
||||
_graphicTemplate() {
|
||||
return svg`<svg viewBox="22 22 44 44">
|
||||
<circle cx="44" cy="44" r="20.2" />
|
||||
</svg>`;
|
||||
return html`
|
||||
<svg class="progress--icon" viewBox="20 20 47 47">
|
||||
<circle class="progress--icon--circle" cx="44" cy="44" r="20.2" />
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('custom-progress-indicator', CustomProgressIndicator);
|
||||
76
docs/components/content/progress-indicator/examples.md
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
# Content >> Progress Indicator >> Examples ||30
|
||||
|
||||
```js script
|
||||
import { html } from '@lion/core';
|
||||
import './assets/custom-progress-indicator.js';
|
||||
```
|
||||
|
||||
## Extended indicator with a custom visual
|
||||
|
||||
`LionProgressIndicator` is designed to be extended to add visuals. Implement the `_graphicTemplate()` method to set the rendered content and apply styles normally.
|
||||
|
||||
### Example extension
|
||||
|
||||
```js
|
||||
class CustomProgressIndicator extends LionProgressIndicator {
|
||||
static get styles() {
|
||||
return [
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.progress--icon {
|
||||
display: inline-block;
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
animation: spinner-rotate 2s linear infinite;
|
||||
}
|
||||
|
||||
.progress--icon--circle {
|
||||
animation: spinner-dash 1.35s ease-in-out infinite;
|
||||
fill: none;
|
||||
stroke-width: 6px;
|
||||
stroke: var(--primary-color);
|
||||
stroke-dasharray: 100, 28; /* This is a fallback for IE11 */
|
||||
}
|
||||
|
||||
@keyframes spinner-rotate {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes spinner-dash {
|
||||
0% {
|
||||
stroke-dasharray: 6, 122;
|
||||
stroke-dashoffset: 0;
|
||||
}
|
||||
50% {
|
||||
stroke-dasharray: 100, 28;
|
||||
stroke-dashoffset: -16;
|
||||
}
|
||||
100% {
|
||||
stroke-dasharray: 6, 122;
|
||||
stroke-dashoffset: -127;
|
||||
}
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
_graphicTemplate() {
|
||||
return html`
|
||||
<svg class="progress--icon" viewBox="20 20 47 47">
|
||||
<circle class="progress--icon--circle" cx="44" cy="44" r="20.2" />
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Result
|
||||
|
||||
```js preview-story
|
||||
export const main = () => html` <custom-progress-indicator></custom-progress-indicator> `;
|
||||
```
|
||||
3
docs/components/content/progress-indicator/index.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Content >> Progress Indicator
|
||||
|
||||
-> go to Overview
|
||||
29
docs/components/content/progress-indicator/overview.md
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
# Content >> Progress Indicator >> Overview ||10
|
||||
|
||||
`lion-progress-indicator` implements accessibility requirements for progress indicators.
|
||||
|
||||
```html
|
||||
<lion-progress-indicator></lion-progress-indicator>
|
||||
```
|
||||
|
||||
Note: You don't see a live demo here as it would be empty, since there is no styling. Check out the [examples](./examples.md) if you want to see a possible implementation.
|
||||
|
||||
## Features
|
||||
|
||||
`LionProgressIndicator` is designed to be extended to add visuals.
|
||||
|
||||
- Accessibility compliant
|
||||
- Localized "Loading" label
|
||||
- Implementation independent of visuals
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i --save @lion/progress-indicator
|
||||
```
|
||||
|
||||
```js
|
||||
import { LionProgressIndicator } from '@lion/progress-indicator';
|
||||
// or
|
||||
import '@lion/progress-indicator/define';
|
||||
```
|
||||
23
docs/components/content/tabs/examples.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Content >> Tabs >> Examples ||30
|
||||
|
||||
```js script
|
||||
import { LitElement, html } from '@lion/core';
|
||||
import './src/lea-tabs.js';
|
||||
import './src/lea-tab.js';
|
||||
import './src/lea-tab-panel.js';
|
||||
```
|
||||
|
||||
## Lea Tabs
|
||||
|
||||
Learn how to create the `lea tabs` in our ["introducing lion" blogpost](../../../blog/ing-open-sources-lion.md).
|
||||
|
||||
```js preview-story
|
||||
export const main = () => html`
|
||||
<lea-tabs>
|
||||
<lea-tab slot="tab">Info</lea-tab>
|
||||
<lea-tab-panel slot="panel"> Info page with lots of information about us. </lea-tab-panel>
|
||||
<lea-tab slot="tab">Work</lea-tab>
|
||||
<lea-tab-panel slot="panel"> Work page that showcases our work. </lea-tab-panel>
|
||||
</lea-tabs>
|
||||
`;
|
||||
```
|
||||
194
docs/components/content/tabs/features.md
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
# Content >> Tabs >> Features ||20
|
||||
|
||||
```js script
|
||||
import { LitElement, html } from '@lion/core';
|
||||
|
||||
import '@lion/tabs/define';
|
||||
```
|
||||
|
||||
## Selected Index
|
||||
|
||||
You can set the `selectedIndex` to select a certain tab.
|
||||
|
||||
```js preview-story
|
||||
export const selectedIndex = () => html`
|
||||
<lion-tabs .selectedIndex=${1}>
|
||||
<button slot="tab">Info</button>
|
||||
<p slot="panel">Info page with lots of information about us.</p>
|
||||
<button slot="tab">Work</button>
|
||||
<p slot="panel">Work page that showcases our work.</p>
|
||||
</lion-tabs>
|
||||
`;
|
||||
```
|
||||
|
||||
## Slots Order
|
||||
|
||||
The tab and panel slots are ordered by DOM order.
|
||||
|
||||
This means you can switch the grouping in your `lion-tabs` from tab + panel to all tabs first or all panels first.
|
||||
|
||||
```js preview-story
|
||||
export const slotsOrder = () => html`
|
||||
<lion-tabs>
|
||||
<button slot="tab">Info</button>
|
||||
<button slot="tab">Work</button>
|
||||
<p slot="panel">Info page with lots of information about us.</p>
|
||||
<p slot="panel">Work page that showcases our work.</p>
|
||||
</lion-tabs>
|
||||
`;
|
||||
```
|
||||
|
||||
## Nesting tabs
|
||||
|
||||
You can include tabs within tabs
|
||||
|
||||
```js preview-story
|
||||
export const nestedTabs = () => html`
|
||||
<lion-tabs>
|
||||
<button slot="tab">Movies</button>
|
||||
<button slot="tab">Work</button>
|
||||
<div slot="panel">
|
||||
<p>Find some more info about our favorite movies:</p>
|
||||
<lion-tabs>
|
||||
<button slot="tab">Info about Cars</button>
|
||||
<button slot="tab">Info about Toy Story</button>
|
||||
<p slot="panel">
|
||||
Cars is a 2006 American computer-animated comedy film produced by Pixar Animation Studios
|
||||
and released by Walt Disney Pictures.
|
||||
</p>
|
||||
<p slot="panel">
|
||||
The feature film directorial debut of John Lasseter, it was the first entirely
|
||||
computer-animated feature film, as well as the first feature film from Pixar.
|
||||
</p>
|
||||
</lion-tabs>
|
||||
</div>
|
||||
<p slot="panel">Work page that showcases our work.</p>
|
||||
</lion-tabs>
|
||||
`;
|
||||
```
|
||||
|
||||
## Distribute New Elements
|
||||
|
||||
Below, we demonstrate on how you could dynamically add new tab + panels.
|
||||
|
||||
```js preview-story
|
||||
export const distributeNewElement = () => {
|
||||
const tagName = 'demo-tabs-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-tabs id="appendTabs">
|
||||
<button slot="tab">tab 1</button>
|
||||
<p slot="panel">panel 1</p>
|
||||
<button slot="tab">tab 2</button>
|
||||
<p slot="panel">panel 2</p>
|
||||
</lion-tabs>
|
||||
<button @click="${this.__handleAppendClick}">Append</button>
|
||||
<hr />
|
||||
<h3>Push</h3>
|
||||
<lion-tabs id="pushTabs">
|
||||
<button slot="tab">tab 1</button>
|
||||
<p slot="panel">panel 1</p>
|
||||
<button slot="tab">tab 2</button>
|
||||
<p slot="panel">panel 2</p>
|
||||
${this.__collection.map(
|
||||
item => html`
|
||||
<button slot="tab">${item.button}</button>
|
||||
<p slot="panel">${item.panel}</p>
|
||||
`,
|
||||
)}
|
||||
</lion-tabs>
|
||||
<button @click="${this.__handlePushClick}">Push</button>
|
||||
`;
|
||||
}
|
||||
constructor() {
|
||||
super();
|
||||
this.__collection = [];
|
||||
}
|
||||
__handleAppendClick() {
|
||||
const tabsElement = this.shadowRoot.querySelector('#appendTabs');
|
||||
const c = 2;
|
||||
const n = Math.floor(tabsElement.children.length / 2);
|
||||
for (let i = n + 1; i < n + c; i += 1) {
|
||||
const tab = document.createElement('button');
|
||||
tab.setAttribute('slot', 'tab');
|
||||
tab.innerText = `tab ${i}`;
|
||||
const panel = document.createElement('p');
|
||||
panel.setAttribute('slot', 'panel');
|
||||
panel.innerText = `panel ${i}`;
|
||||
tabsElement.append(tab);
|
||||
tabsElement.append(panel);
|
||||
}
|
||||
}
|
||||
__handlePushClick() {
|
||||
const tabsElement = this.shadowRoot.querySelector('#pushTabs');
|
||||
const i = Math.floor(tabsElement.children.length / 2) + 1;
|
||||
this.__collection = [
|
||||
...this.__collection,
|
||||
{
|
||||
button: `tab ${i}`,
|
||||
panel: `panel ${i}`,
|
||||
},
|
||||
];
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
return html` <demo-tabs-add-dynamically></demo-tabs-add-dynamically> `;
|
||||
};
|
||||
```
|
||||
|
||||
One way is by creating the DOM elements and appending them as needed.
|
||||
|
||||
Inside your `lion-tabs` extension, an example for appending nodes on a certain button click:
|
||||
|
||||
```js
|
||||
__handleAppendClick() {
|
||||
const tabsAmount = this.children.length / 2;
|
||||
const tab = document.createElement('button');
|
||||
tab.setAttribute('slot', 'tab');
|
||||
tab.innerText = `tab ${tabsAmount + 1}`;
|
||||
const panel = document.createElement('p');
|
||||
panel.setAttribute('slot', 'panel');
|
||||
panel.innerText = `panel ${tabsAmount + 1}`;
|
||||
this.append(tab);
|
||||
this.append(panel);
|
||||
}
|
||||
```
|
||||
|
||||
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 tabsAmount = this.children.length;
|
||||
myCollection = [
|
||||
...myCollection,
|
||||
{
|
||||
button: `tab ${tabsAmount + 1}`,
|
||||
panel: `panel ${tabsAmount + 1}`,
|
||||
},
|
||||
];
|
||||
renderMyCollection();
|
||||
}
|
||||
```
|
||||
|
||||
Make sure your template re-renders when myCollection is updated.
|
||||
|
||||
```html
|
||||
<lion-tabs id="pushTabs">
|
||||
${myCollection.map(item => html`
|
||||
<button slot="tab">${item.button}</button>
|
||||
<p slot="panel">${item.panel}</p>
|
||||
`)}
|
||||
</lion-tabs>
|
||||
```
|
||||
3
docs/components/content/tabs/index.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Content >> Tabs
|
||||
|
||||
-> go to Overview
|
||||
48
docs/components/content/tabs/overview.md
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
# Content >> Tabs >> Overview ||10
|
||||
|
||||
A component to allow users to quickly move between a small number of equally important views.
|
||||
|
||||
```js script
|
||||
import { LitElement, html } from '@lion/core';
|
||||
import '@lion/tabs/define';
|
||||
```
|
||||
|
||||
```js preview-story
|
||||
export const main = () => html`
|
||||
<lion-tabs>
|
||||
<button slot="tab">Info</button>
|
||||
<p slot="panel">Info page with lots of information about us.</p>
|
||||
<button slot="tab">Work</button>
|
||||
<p slot="panel">Work page that showcases our work.</p>
|
||||
</lion-tabs>
|
||||
`;
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i --save @lion/tabs;
|
||||
```
|
||||
|
||||
```js
|
||||
import { LionTabs } from '@lion/tabs';
|
||||
// or
|
||||
import '@lion/tabs/define';
|
||||
```
|
||||
|
||||
## Rationale
|
||||
|
||||
### No separate active/focus state when using keyboard
|
||||
|
||||
We will immediately switch content as all our content comes from light dom (e.g. no latency)
|
||||
|
||||
See Note at <https://www.w3.org/TR/wai-aria-practices/#keyboard-interaction-19>
|
||||
|
||||
> It is recommended that tabs activate automatically when they receive focus as long as their
|
||||
> associated tab panels are displayed without noticeable latency. This typically requires tab
|
||||
> panel content to be preloaded.
|
||||
|
||||
### Panels are not focusable
|
||||
|
||||
Focusable elements should have a means to interact with them. Tab panels themselves do not offer any interactivity.
|
||||
If there is a button or a form inside the tab panel then these elements get focused directly.
|
||||
|
|
@ -20,3 +20,5 @@ export class LeaTabPanel extends LitElement {
|
|||
`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('lea-tab-panel', LeaTabPanel);
|
||||
|
|
@ -41,3 +41,5 @@ export class LeaTab extends LitElement {
|
|||
return html`<slot></slot>`;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('lea-tab', LeaTab);
|
||||
|
|
@ -24,3 +24,5 @@ export class LeaTabs extends LionTabs {
|
|||
// being awesome
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('lea-tabs', LeaTabs);
|
||||
93
docs/components/icons/icon/features.md
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
# Icons >> Icon >> Features ||20
|
||||
|
||||
```js script
|
||||
import { html } from '@lion/core';
|
||||
import { icons } from '@lion/icon';
|
||||
import './assets/iconset-bugs.js';
|
||||
import './assets/iconset-misc.js';
|
||||
import * as spaceSet from './assets/iconset-space.js';
|
||||
|
||||
import '@lion/icon/define';
|
||||
|
||||
icons.addIconResolver('lion', (iconset, name) => {
|
||||
switch (iconset) {
|
||||
case 'bugs':
|
||||
return import('./assets/iconset-bugs.js').then(module => module[name]);
|
||||
case 'space':
|
||||
return import('./assets/iconset-space.js').then(module => module[name]);
|
||||
case 'misc':
|
||||
return import('./assets/iconset-misc.js').then(module => module[name]);
|
||||
default:
|
||||
throw new Error(`Unknown iconset ${iconset}`);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Icon sets
|
||||
|
||||
Icons are displayed using icon sets. These are collections of icons, lazily loaded on demand for performance.
|
||||
See the [system documentation](../../../docs/systems/icon/overview.md) to learn more about icon sets.
|
||||
|
||||
```js preview-story
|
||||
export const iconSets = () => html`
|
||||
${Object.keys(spaceSet).map(
|
||||
name => html`
|
||||
<style>
|
||||
.demo-icon__container {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
flex-grow: 1;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
padding: 4px;
|
||||
}
|
||||
.demo-icon__name {
|
||||
font-size: 10px;
|
||||
}
|
||||
</style>
|
||||
<div class="demo-icon__container">
|
||||
<lion-icon icon-id="lion:space:${name}" aria-label="${name}"></lion-icon>
|
||||
<span class="demo-icon__name">${name}</span>
|
||||
</div>
|
||||
`,
|
||||
)}
|
||||
`;
|
||||
```
|
||||
|
||||
If for some reason you don't want to lazy load icons, you can still import and use them
|
||||
synchronously.
|
||||
|
||||
## Accessibility
|
||||
|
||||
It is recommended to add an `aria-label` to provide information to visually impaired users:
|
||||
|
||||
A `lion-icon` without an `aria-label` attribute will be automatically given an `aria-hidden` attribute.
|
||||
|
||||
```js preview-story
|
||||
export const accessibleLabel = () => html`
|
||||
<lion-icon icon-id="lion:misc:arrowLeft" aria-label="Pointing left"></lion-icon>
|
||||
`;
|
||||
```
|
||||
|
||||
## Styling
|
||||
|
||||
By default, a `lion-icon` will be `1em` × `1em` (the current line-height).
|
||||
|
||||
`lion-icon` uses SVGs and may be styled with CSS, including using CSS properties such as `fill`:
|
||||
|
||||
```js preview-story
|
||||
export const Styling = () => html`
|
||||
<style>
|
||||
.demo-icon {
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
fill: blue;
|
||||
}
|
||||
</style>
|
||||
<lion-icon icon-id="lion:bugs:bug02" aria-label="Bug" class="demo-icon"></lion-icon>
|
||||
`;
|
||||
```
|
||||
|
||||
See [SVG and CSS](https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/SVG_and_CSS) on MDN web docs for more information.
|
||||
3
docs/components/icons/icon/index.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Icons >> Icon
|
||||
|
||||
-> go to Overview
|
||||
40
docs/components/icons/icon/overview.md
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Icons >> Icon >> Overview ||10
|
||||
|
||||
A web component for displaying icons.
|
||||
|
||||
```js script
|
||||
import { html } from '@lion/core';
|
||||
import { icons } from '@lion/icon';
|
||||
import '@lion/icon/define';
|
||||
|
||||
icons.addIconResolver('lion', (iconset, name) => {
|
||||
switch (iconset) {
|
||||
case 'bugs':
|
||||
return import('./assets/iconset-bugs.js').then(module => module[name]);
|
||||
case 'space':
|
||||
return import('./assets/iconset-space.js').then(module => module[name]);
|
||||
case 'misc':
|
||||
return import('./assets/iconset-misc.js').then(module => module[name]);
|
||||
default:
|
||||
throw new Error(`Unknown iconset ${iconset}`);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
```js preview-story
|
||||
export const main = () => html`
|
||||
<lion-icon icon-id="lion:space:alienSpaceship" style="width: 50px; height: 50px;"></lion-icon>
|
||||
`;
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i --save @lion/icon
|
||||
```
|
||||
|
||||
```js
|
||||
import { LionIcon } from '@lion/icon';
|
||||
// or
|
||||
import '@lion/icon/define';
|
||||
```
|
||||
1
docs/components/icons/index.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
# Icons ||30
|
||||
16
docs/components/index.md
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
# Components ||20
|
||||
|
||||
We offer many web components for your application needs. For each, you will find an overview page to highlight its capabilities and how to start using it. Additionally, there will be a features page that showcases multiple use cases in action. Some even have a dedicated examples page so you can see a possible styled implementation.
|
||||
|
||||
For organizational purposes, we split them into the following groups.
|
||||
|
||||
1. [Content](./content/accordion/overview.md) <br>
|
||||
Everything to help you organize your content.
|
||||
2. [Icons](./icons/icon/overview.md) <br>
|
||||
Loading and displaying icons.
|
||||
3. [Inputs](./inputs/overview.md) <br>
|
||||
Input components that lets you make complex forms with ease, including validation.
|
||||
4. [Interaction](./interaction/button/overview.md) <br>
|
||||
A set of interactive components.
|
||||
5. [Navigation](./navigation/pagination/overview.md) <br>
|
||||
The reasoning behind some of our decisions.
|
||||
192
docs/components/inputs/calendar/features.md
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
# Inputs >> Calendar >> Features ||20
|
||||
|
||||
```js script
|
||||
import { html, css } from '@lion/core';
|
||||
import '@lion/calendar/define';
|
||||
```
|
||||
|
||||
## Selected date
|
||||
|
||||
The `selectedDate` is the date which is currently marked as selected.
|
||||
You usually select a date by clicking on it with the mouse or hitting Enter on the keyboard.
|
||||
|
||||
The `selectedDate` might not be within the dates in the current month view.
|
||||
|
||||
```js preview-story
|
||||
export const selectedDate = () => html`
|
||||
<style>
|
||||
.demo-calendar {
|
||||
border: 1px solid #adadad;
|
||||
box-shadow: 0 0 16px #ccc;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<lion-calendar class="demo-calendar" .selectedDate=${new Date(1988, 2, 5)}></lion-calendar>
|
||||
`;
|
||||
```
|
||||
|
||||
## Central Date
|
||||
|
||||
The `centralDate` defines which day will be focused when keyboard moves the focus to the current month grid.
|
||||
By default it is set to today, or the enabled day of the current month view that is closest to today's date.
|
||||
|
||||
The next and previous months' buttons work by changing the `centralDate` with plus or minus one month.
|
||||
Changing the `centralDate` may mean a different view will be displayed to your users if it is in a different month.
|
||||
Usually if you change only the day, "nothing" happens as it's already currently in view.
|
||||
|
||||
The `centralDate` can be different from `selectedDate` as you can have today as actively selected but still look at date that is years ago.
|
||||
When the `selectedDate` changes, it will sync its value to the `centralDate`.
|
||||
|
||||
```js preview-story
|
||||
export const centralDate = () => {
|
||||
const today = new Date();
|
||||
const centralDate = new Date(today.getFullYear(), today.getMonth() + 1, today.getDate());
|
||||
return html`
|
||||
<style>
|
||||
.demo-calendar {
|
||||
border: 1px solid #adadad;
|
||||
box-shadow: 0 0 16px #ccc;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<lion-calendar class="demo-calendar" .centralDate="${centralDate}"></lion-calendar>
|
||||
`;
|
||||
};
|
||||
```
|
||||
|
||||
## Controlling focus
|
||||
|
||||
You can control the focus by calling the following methods
|
||||
|
||||
- `focusCentralDate()`
|
||||
- `focusSelectedDate()`
|
||||
- `focusDate(dateInstanceToFocus)`
|
||||
|
||||
> Be aware that the central date changes when a new date is focused.
|
||||
|
||||
```js preview-story
|
||||
export const controllingFocus = () => {
|
||||
const today = new Date();
|
||||
const selectedDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1);
|
||||
const centralDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 5);
|
||||
return html`
|
||||
<style>
|
||||
.demo-calendar {
|
||||
border: 1px solid #adadad;
|
||||
box-shadow: 0 0 16px #ccc;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<lion-calendar
|
||||
id="js-demo-calendar"
|
||||
class="demo-calendar"
|
||||
.selectedDate="${selectedDate}"
|
||||
.centralDate="${centralDate}"
|
||||
></lion-calendar>
|
||||
<button
|
||||
@click="${e => e.target.parentElement.querySelector('#js-demo-calendar').focusCentralDate()}"
|
||||
>
|
||||
Set focus on: Central date
|
||||
</button>
|
||||
<button
|
||||
@click="${e => e.target.parentElement.querySelector('#js-demo-calendar').focusSelectedDate()}"
|
||||
>
|
||||
Set focus on: Selected date
|
||||
</button>
|
||||
<button
|
||||
@click="${e => e.target.parentElement.querySelector('#js-demo-calendar').focusDate(today)}"
|
||||
>
|
||||
Set focus on: Today
|
||||
</button>
|
||||
`;
|
||||
};
|
||||
```
|
||||
|
||||
## Limiting selectable values
|
||||
|
||||
### Providing a lower limit
|
||||
|
||||
To give a lower limit you can bind a date to the `minDate` property.
|
||||
|
||||
```js preview-story
|
||||
export const providingLowerLimit = () => {
|
||||
const minDate = new Date();
|
||||
return html`
|
||||
<style>
|
||||
.demo-calendar {
|
||||
border: 1px solid #adadad;
|
||||
box-shadow: 0 0 16px #ccc;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<lion-calendar class="demo-calendar" .minDate="${minDate}"></lion-calendar>
|
||||
`;
|
||||
};
|
||||
```
|
||||
|
||||
### Provide a higher limit
|
||||
|
||||
To give a higher limit you can bind a date to the `maxDate` property. In this example, we show how to create an offset of + 2 days.
|
||||
|
||||
```js preview-story
|
||||
export const providingHigherLimit = () => {
|
||||
const today = new Date();
|
||||
const maxDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 2);
|
||||
return html`
|
||||
<style>
|
||||
.demo-calendar {
|
||||
border: 1px solid #adadad;
|
||||
box-shadow: 0 0 16px #ccc;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<lion-calendar class="demo-calendar" .maxDate="${maxDate}"></lion-calendar>
|
||||
`;
|
||||
};
|
||||
```
|
||||
|
||||
### Provide a list of disabled dates
|
||||
|
||||
In some cases a specific date or day of the week needs to be disabled, supply those days to the `disableDates` property.
|
||||
|
||||
```js preview-story
|
||||
export const disabledDates = () => html`
|
||||
<style>
|
||||
.demo-calendar {
|
||||
border: 1px solid #adadad;
|
||||
box-shadow: 0 0 16px #ccc;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<lion-calendar
|
||||
class="demo-calendar"
|
||||
.disableDates=${day => day.getDay() === 6 || day.getDay() === 0}
|
||||
></lion-calendar>
|
||||
`;
|
||||
```
|
||||
|
||||
### Combined disable dates
|
||||
|
||||
To limit the scope of possible dates further, combine the methods mentioned above.
|
||||
|
||||
```js preview-story
|
||||
export const combinedDisabledDates = () => {
|
||||
const today = new Date();
|
||||
const maxDate = new Date(today.getFullYear(), today.getMonth() + 2, today.getDate());
|
||||
return html`
|
||||
<style>
|
||||
.demo-calendar {
|
||||
border: 1px solid #adadad;
|
||||
box-shadow: 0 0 16px #ccc;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<lion-calendar
|
||||
class="demo-calendar"
|
||||
.disableDates=${day => day.getDay() === 6 || day.getDay() === 0}
|
||||
.minDate="${new Date()}"
|
||||
.maxDate="${maxDate}"
|
||||
></lion-calendar>
|
||||
`;
|
||||
};
|
||||
```
|
||||
3
docs/components/inputs/calendar/index.md
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
# Inputs >> Calendar ||20
|
||||
|
||||
-> go to Overview
|
||||
49
docs/components/inputs/calendar/overview.md
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
# Inputs >> Calendar >> Overview ||10
|
||||
|
||||
`lion-calendar` is a reusable and accessible calendar view.
|
||||
|
||||
```js script
|
||||
import { html, css } from '@lion/core';
|
||||
import '@lion/calendar/define';
|
||||
```
|
||||
|
||||
```js story
|
||||
export const main = () => {
|
||||
return html`
|
||||
<style>
|
||||
.demo-calendar {
|
||||
border: 1px solid #adadad;
|
||||
box-shadow: 0 0 16px #ccc;
|
||||
max-width: 500px;
|
||||
}
|
||||
</style>
|
||||
<lion-calendar class="demo-calendar"></lion-calendar>
|
||||
`;
|
||||
};
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
- fully accessible keyboard navigation (Arrow Keys, PgUp, PgDn, ALT+PgUp, ALT+PgDn)
|
||||
- **minDate**: disables all dates before a given date
|
||||
- **maxDate**: disables all dates after a given date
|
||||
- **disableDates**: disables some dates within an available range
|
||||
- **selectedDate**: currently selected date
|
||||
- **centralDate**: date that determines the currently visible month and that will be focused when keyboard moves the focus to the month grid
|
||||
- **focusedDate**: (getter only) currently focused date (if there is any with real focus)
|
||||
- **focusDate(date)**: focus on a certain date
|
||||
- **focusSelectedDate()**: focus on the current selected date
|
||||
- **focusCentralDate()**: focus on the current central date
|
||||
- **firstDayOfWeek**: typically Sunday (default) or Monday
|
||||
- **weekdayHeaderNotation**: long/short/narrow for the current locale (e.g. Thursday/Thu/T)
|
||||
- **locale**: different locale for the current component only
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm i --save @lion/calendar
|
||||
```
|
||||
|
||||
```js
|
||||
import '@lion/calendar/define';
|
||||
```
|
||||