From bcd074d1fbce8754d428538df723ba402603e2c8 Mon Sep 17 00:00:00 2001 From: Thomas Allmer Date: Wed, 25 Mar 2020 10:20:17 +0100 Subject: [PATCH] feat: use markdown javascript (mdjs) for documentation Co-authored-by: CubLion --- .eslintrc.js | 1 + .markdownlint.json | 2 +- .storybook/main.js | 23 +- README.md | 205 +- .../10-announcement.stories.mdx => README.md} | 31 +- demo/docs/20-lea-tabs.md | 253 ++ .../{stories => docs/assets}/side-by-side.png | Bin demo/stories/20-lea-tabs.stories.mdx | 255 -- docs/README.md | 12 +- docs/definitions.md | 52 - docs/guidelines-styling.md | 205 -- docs/guidelines/10-guidelines-definitions.md | 63 + docs/guidelines/20-guidelines-styling.md | 46 + .../30-guidelines-scoped-elements.md | 107 + .../40-guidelines-subclasser-apis.md} | 17 +- docs/intros/intros-buttons.md | 22 + .../intros/intros-icon.md | 10 +- docs/intros/intros-navigation.md | 20 + docs/intros/intros-others.md | 17 + docs/rationals/001-side-effects.md | 6 + es-dev-server.config.js | 8 + package.json | 4 +- packages/ajax/README.md | 178 + .../ajax/{stories => docs/assets}/data.json | 0 packages/ajax/package.json | 1 + packages/ajax/stories/index.stories.mdx | 279 -- packages/babel-plugin-extend-docs/README.md | 6 + packages/button/README.md | 120 +- .../{stories => docs/assets}/icon.svg.js | 0 packages/button/package.json | 1 + packages/button/stories/index.stories.mdx | 173 - packages/calendar/README.md | 199 + packages/calendar/package.json | 1 + packages/calendar/stories/index.stories.mdx | 257 -- packages/checkbox-group/README.md | 155 +- packages/checkbox-group/package.json | 1 + .../checkbox-group/stories/index.stories.mdx | 328 -- packages/choice-input/README.md | 14 +- packages/core/README.md | 69 +- packages/core/stories/index.stories.mdx | 67 - packages/dialog/README.md | 175 + .../{stories => docs}/demo-dialog-style.js | 0 .../styled-dialog-content.js | 0 packages/dialog/package.json | 1 + packages/dialog/stories/index.stories.mdx | 279 -- packages/field/README.md | 38 +- packages/field/docs/CustomFieldsTutorial.md | 14 +- packages/field/docs/FormFundaments.md | 8 + packages/field/docs/FormattingAndParsing.md | 8 + packages/fieldset/README.md | 45 +- .../helpers/demo-fieldset-child.js | 0 .../fieldset/stories/overview.stories.mdx | 41 - packages/form-system/README.md | 52 +- .../form-system/docs/15-features-overview.md | 153 + .../docs/17-validation-examples.md | 405 +++ .../20-system-overview.md} | 14 +- .../25-system-model-value.md} | 10 +- .../30-system-formatting.md} | 221 +- .../docs/35-system-interaction-states.md | 178 + .../40-system-creating-a-custom-field.md} | 22 +- .../docs/50-content-inside-fields.md | 23 + .../form-system/docs/fieldset-examples.md | 192 + .../{stories => docs}/helper-wc/h-output.js | 1 + .../form-system/stories/10-intro.stories.mdx | 33 - .../stories/15-features-overview.stories.mdx | 159 - .../17-Validation-Examples.stories.mdx | 694 ---- .../35-System-InteractionStates.stories.mdx | 180 - .../50-Content-inside-fields.stories.mdx | 26 - .../stories/fieldset-examples.stories.mdx | 387 -- .../stories/flow-diagrams.stories.js | 17 - .../stories/form-examples.stories.mdx | 181 - packages/form/README.md | 36 + packages/form/stories/overview.stories.mdx | 33 - packages/helpers/README.md | 14 + packages/helpers/sb-action-logger/README.md | 170 +- .../stories/index.stories.mdx | 167 - .../helpers/stories/helpers-intro.stories.mdx | 13 - packages/icon/README.md | 104 +- .../{stories => docs}/icons/bugs/bug01.svg.js | 0 .../{stories => docs}/icons/bugs/bug02.svg.js | 0 .../{stories => docs}/icons/bugs/bug05.svg.js | 0 .../{stories => docs}/icons/bugs/bug06.svg.js | 0 .../{stories => docs}/icons/bugs/bug08.svg.js | 0 .../{stories => docs}/icons/bugs/bug12.svg.js | 0 .../{stories => docs}/icons/bugs/bug19.svg.js | 0 .../{stories => docs}/icons/bugs/bug23.svg.js | 0 .../{stories => docs}/icons/bugs/bug24.svg.js | 0 .../{stories => docs}/icons/iconset-bugs.js | 0 .../{stories => docs}/icons/iconset-misc.js | 0 .../{stories => docs}/icons/iconset-space.js | 0 .../icons/misc/arrowLeft.svg.js | 0 .../icons/space/aliens-spaceship.svg.js | 0 .../icons/space/meteor.svg.js | 0 .../icons/space/moon-flag.svg.js | 0 .../{stories => docs}/icons/space/moon.svg.js | 0 .../icons/space/night.svg.js | 0 .../icons/space/orbit.svg.js | 0 .../icons/space/planet.svg.js | 0 .../icons/space/robot.svg.js | 0 .../icons/space/rocket.svg.js | 0 .../icons/space/satellite.svg.js | 0 .../icons/space/signal.svg.js | 0 .../icons/space/space-helmet.svg.js | 0 .../{stories => docs}/icons/space/sun.svg.js | 0 .../icons/space/telescope.svg.js | 0 .../system.stories.mdx => docs/system.md} | 15 +- packages/icon/stories/icon-resolvers.js | 14 - packages/icon/stories/icon.stories.mdx | 132 - packages/input-amount/README.md | 134 +- .../input-amount/stories/index.stories.mdx | 193 - packages/input-date/README.md | 98 +- packages/input-date/stories/index.stories.mdx | 155 - packages/input-datepicker/README.md | 113 +- .../stories/index.stories.mdx | 169 - packages/input-email/README.md | 69 +- .../input-email/stories/index.stories.mdx | 124 - packages/input-iban/README.md | 83 +- packages/input-iban/stories/index.stories.mdx | 120 - packages/input-range/README.md | 92 +- .../input-range/stories/index.stories.mdx | 153 - packages/input/README.md | 190 +- packages/input/stories/index.stories.mdx | 283 -- packages/input/stories/translations/de-DE.js | 5 - packages/input/stories/translations/de.js | 6 - packages/input/stories/translations/en-GB.js | 5 - packages/input/stories/translations/en.js | 15 - packages/input/stories/translations/fr-FR.js | 5 - packages/input/stories/translations/fr.js | 6 - packages/input/stories/translations/nl-NL.js | 5 - packages/input/stories/translations/nl.js | 6 - packages/input/stories/translations/zh-CN.js | 5 - packages/input/stories/translations/zh.js | 6 - .../intros/stories/buttons-intro.stories.mdx | 20 - .../stories/lion-web-components.stories.mdx | 76 - .../stories/navigation-intro.stories.mdx | 18 - .../intros/stories/others-intro.stories.mdx | 15 - packages/localize/README.md | 56 +- .../localize/{docs => _docs}/amount-html.md | 0 packages/localize/{docs => _docs}/date.md | 0 packages/localize/{docs => _docs}/message.md | 0 packages/localize/{docs => _docs}/number.md | 0 .../localize/docs/10-features-overview.md | 157 + packages/localize/docs/20-numbers.md | 221 ++ packages/localize/docs/30-dates.md | 199 + .../50-system-overview.md} | 10 +- .../60-system-rationale.md} | 10 +- .../localize/{stories => docs}/all-locales.js | 0 .../{stories => docs}/translations/en-AU.js | 0 .../{stories => docs}/translations/en-GB.js | 0 .../{stories => docs}/translations/en-US.js | 0 .../{stories => docs}/translations/en.js | 0 .../{stories => docs}/translations/nl-BE.js | 0 .../{stories => docs}/translations/nl-NL.js | 0 .../{stories => docs}/translations/nl.js | 0 .../localize/stories/10-intro.stories.mdx | 38 - .../stories/12-features-overview.stories.mdx | 99 - packages/localize/stories/15-text.stories.mdx | 42 - .../localize/stories/25-numbers.stories.mdx | 216 -- .../localize/stories/30-dates.stories.mdx | 197 - packages/localize/stories/message.stories.js | 61 - packages/overlays/README.md | 20 +- .../20-index.stories.mdx => docs/20-index.md} | 582 +-- .../30-system-rationale.md} | 12 +- .../overlays/docs/40-system-configuration.md | 365 ++ packages/overlays/docs/OverlaySystemScope.md | 10 +- .../applyDemoOverlayStyles.js | 0 .../{stories => docs}/demo-overlay-system.js | 1 + .../{stories => docs}/directives/ref.js | 0 .../overlays/stories/10-intro.stories.mdx | 35 - .../40-system-configuration.stories.mdx | 568 --- packages/radio-group/README.md | 170 +- .../radio-group/stories/index.stories.mdx | 258 -- packages/remark-extend/README.md | 6 + packages/select-rich/README.md | 388 +- .../select-rich/stories/index.stories.mdx | 585 --- packages/select/README.md | 121 +- packages/select/stories/index.stories.mdx | 191 - packages/singleton-manager/README.md | 6 + packages/steps/README.md | 192 +- packages/steps/package.json | 1 + packages/steps/stories/index.stories.mdx | 265 -- packages/switch/README.md | 91 + packages/switch/package.json | 1 + packages/switch/stories/index.stories.mdx | 173 - packages/tabs/README.md | 220 ++ packages/tabs/package.json | 1 + packages/tabs/stories/index.stories.mdx | 247 -- packages/textarea/README.md | 107 +- packages/textarea/stories/index.stories.mdx | 143 - packages/tooltip/README.md | 218 +- packages/tooltip/stories/index.stories.mdx | 274 -- packages/tooltip/stories/tooltipDemoStyles.js | 26 - packages/validate/README.md | 68 +- .../validate/docs/{ => assets}/FlowDiagram.md | 0 .../Overview.stories.mdx => docs/system.md} | 23 +- yarn.lock | 3208 ++++++----------- 196 files changed, 7740 insertions(+), 11774 deletions(-) rename demo/{stories/10-announcement.stories.mdx => README.md} (97%) create mode 100644 demo/docs/20-lea-tabs.md rename demo/{stories => docs/assets}/side-by-side.png (100%) delete mode 100644 demo/stories/20-lea-tabs.stories.mdx delete mode 100644 docs/definitions.md delete mode 100644 docs/guidelines-styling.md create mode 100644 docs/guidelines/10-guidelines-definitions.md create mode 100644 docs/guidelines/20-guidelines-styling.md create mode 100644 docs/guidelines/30-guidelines-scoped-elements.md rename docs/{subclasser-apis.md => guidelines/40-guidelines-subclasser-apis.md} (67%) create mode 100644 docs/intros/intros-buttons.md rename packages/intros/stories/icon-intro.stories.mdx => docs/intros/intros-icon.md (87%) create mode 100644 docs/intros/intros-navigation.md create mode 100644 docs/intros/intros-others.md create mode 100644 es-dev-server.config.js rename packages/ajax/{stories => docs/assets}/data.json (100%) delete mode 100644 packages/ajax/stories/index.stories.mdx rename packages/button/{stories => docs/assets}/icon.svg.js (100%) delete mode 100644 packages/button/stories/index.stories.mdx delete mode 100644 packages/calendar/stories/index.stories.mdx delete mode 100644 packages/checkbox-group/stories/index.stories.mdx delete mode 100644 packages/core/stories/index.stories.mdx rename packages/dialog/{stories => docs}/demo-dialog-style.js (100%) rename packages/dialog/{stories => docs}/styled-dialog-content.js (100%) delete mode 100644 packages/dialog/stories/index.stories.mdx rename packages/fieldset/{stories => docs}/helpers/demo-fieldset-child.js (100%) delete mode 100644 packages/fieldset/stories/overview.stories.mdx create mode 100644 packages/form-system/docs/15-features-overview.md create mode 100644 packages/form-system/docs/17-validation-examples.md rename packages/form-system/{stories/20-System-Overview.stories.mdx => docs/20-system-overview.md} (92%) rename packages/form-system/{stories/25-System-ModelValue.stories.mdx => docs/25-system-model-value.md} (89%) rename packages/form-system/{stories/30-System-Formatting.stories.mdx => docs/30-system-formatting.md} (53%) create mode 100644 packages/form-system/docs/35-system-interaction-states.md rename packages/form-system/{stories/40-System-creating-a-custom-field.stories.mdx => docs/40-system-creating-a-custom-field.md} (88%) create mode 100644 packages/form-system/docs/50-content-inside-fields.md create mode 100644 packages/form-system/docs/fieldset-examples.md rename packages/form-system/{stories => docs}/helper-wc/h-output.js (97%) delete mode 100644 packages/form-system/stories/10-intro.stories.mdx delete mode 100644 packages/form-system/stories/15-features-overview.stories.mdx delete mode 100644 packages/form-system/stories/17-Validation-Examples.stories.mdx delete mode 100644 packages/form-system/stories/35-System-InteractionStates.stories.mdx delete mode 100644 packages/form-system/stories/50-Content-inside-fields.stories.mdx delete mode 100644 packages/form-system/stories/fieldset-examples.stories.mdx delete mode 100644 packages/form-system/stories/flow-diagrams.stories.js delete mode 100644 packages/form-system/stories/form-examples.stories.mdx delete mode 100644 packages/form/stories/overview.stories.mdx delete mode 100644 packages/helpers/sb-action-logger/stories/index.stories.mdx delete mode 100644 packages/helpers/stories/helpers-intro.stories.mdx rename packages/icon/{stories => docs}/icons/bugs/bug01.svg.js (100%) rename packages/icon/{stories => docs}/icons/bugs/bug02.svg.js (100%) rename packages/icon/{stories => docs}/icons/bugs/bug05.svg.js (100%) rename packages/icon/{stories => docs}/icons/bugs/bug06.svg.js (100%) rename packages/icon/{stories => docs}/icons/bugs/bug08.svg.js (100%) rename packages/icon/{stories => docs}/icons/bugs/bug12.svg.js (100%) rename packages/icon/{stories => docs}/icons/bugs/bug19.svg.js (100%) rename packages/icon/{stories => docs}/icons/bugs/bug23.svg.js (100%) rename packages/icon/{stories => docs}/icons/bugs/bug24.svg.js (100%) rename packages/icon/{stories => docs}/icons/iconset-bugs.js (100%) rename packages/icon/{stories => docs}/icons/iconset-misc.js (100%) rename packages/icon/{stories => docs}/icons/iconset-space.js (100%) rename packages/icon/{stories => docs}/icons/misc/arrowLeft.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/aliens-spaceship.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/meteor.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/moon-flag.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/moon.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/night.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/orbit.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/planet.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/robot.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/rocket.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/satellite.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/signal.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/space-helmet.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/sun.svg.js (100%) rename packages/icon/{stories => docs}/icons/space/telescope.svg.js (100%) rename packages/icon/{stories/system.stories.mdx => docs/system.md} (94%) delete mode 100644 packages/icon/stories/icon-resolvers.js delete mode 100644 packages/icon/stories/icon.stories.mdx delete mode 100644 packages/input-amount/stories/index.stories.mdx delete mode 100644 packages/input-date/stories/index.stories.mdx delete mode 100644 packages/input-datepicker/stories/index.stories.mdx delete mode 100644 packages/input-email/stories/index.stories.mdx delete mode 100644 packages/input-iban/stories/index.stories.mdx delete mode 100644 packages/input-range/stories/index.stories.mdx delete mode 100644 packages/input/stories/index.stories.mdx delete mode 100644 packages/input/stories/translations/de-DE.js delete mode 100644 packages/input/stories/translations/de.js delete mode 100644 packages/input/stories/translations/en-GB.js delete mode 100644 packages/input/stories/translations/en.js delete mode 100644 packages/input/stories/translations/fr-FR.js delete mode 100644 packages/input/stories/translations/fr.js delete mode 100644 packages/input/stories/translations/nl-NL.js delete mode 100644 packages/input/stories/translations/nl.js delete mode 100644 packages/input/stories/translations/zh-CN.js delete mode 100644 packages/input/stories/translations/zh.js delete mode 100644 packages/intros/stories/buttons-intro.stories.mdx delete mode 100644 packages/intros/stories/lion-web-components.stories.mdx delete mode 100644 packages/intros/stories/navigation-intro.stories.mdx delete mode 100644 packages/intros/stories/others-intro.stories.mdx rename packages/localize/{docs => _docs}/amount-html.md (100%) rename packages/localize/{docs => _docs}/date.md (100%) rename packages/localize/{docs => _docs}/message.md (100%) rename packages/localize/{docs => _docs}/number.md (100%) create mode 100644 packages/localize/docs/10-features-overview.md create mode 100644 packages/localize/docs/20-numbers.md create mode 100644 packages/localize/docs/30-dates.md rename packages/localize/{stories/50-system-overview.stories.mdx => docs/50-system-overview.md} (99%) rename packages/localize/{stories/60-system-rationale.stories.mdx => docs/60-system-rationale.md} (96%) rename packages/localize/{stories => docs}/all-locales.js (100%) rename packages/localize/{stories => docs}/translations/en-AU.js (100%) rename packages/localize/{stories => docs}/translations/en-GB.js (100%) rename packages/localize/{stories => docs}/translations/en-US.js (100%) rename packages/localize/{stories => docs}/translations/en.js (100%) rename packages/localize/{stories => docs}/translations/nl-BE.js (100%) rename packages/localize/{stories => docs}/translations/nl-NL.js (100%) rename packages/localize/{stories => docs}/translations/nl.js (100%) delete mode 100644 packages/localize/stories/10-intro.stories.mdx delete mode 100644 packages/localize/stories/12-features-overview.stories.mdx delete mode 100644 packages/localize/stories/15-text.stories.mdx delete mode 100644 packages/localize/stories/25-numbers.stories.mdx delete mode 100644 packages/localize/stories/30-dates.stories.mdx delete mode 100644 packages/localize/stories/message.stories.js rename packages/overlays/{stories/20-index.stories.mdx => docs/20-index.md} (55%) rename packages/overlays/{stories/30-system-rationale.stories.mdx => docs/30-system-rationale.md} (98%) create mode 100644 packages/overlays/docs/40-system-configuration.md rename packages/overlays/{stories => docs}/applyDemoOverlayStyles.js (100%) rename packages/overlays/{stories => docs}/demo-overlay-system.js (95%) rename packages/overlays/{stories => docs}/directives/ref.js (100%) delete mode 100644 packages/overlays/stories/10-intro.stories.mdx delete mode 100644 packages/overlays/stories/40-system-configuration.stories.mdx delete mode 100644 packages/radio-group/stories/index.stories.mdx delete mode 100644 packages/select-rich/stories/index.stories.mdx delete mode 100644 packages/select/stories/index.stories.mdx delete mode 100644 packages/steps/stories/index.stories.mdx delete mode 100644 packages/switch/stories/index.stories.mdx delete mode 100644 packages/tabs/stories/index.stories.mdx delete mode 100644 packages/textarea/stories/index.stories.mdx delete mode 100644 packages/tooltip/stories/index.stories.mdx delete mode 100644 packages/tooltip/stories/tooltipDemoStyles.js rename packages/validate/docs/{ => assets}/FlowDiagram.md (100%) rename packages/validate/{stories/Overview.stories.mdx => docs/system.md} (93%) diff --git a/.eslintrc.js b/.eslintrc.js index 562ab2e5e..67da708c8 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -8,6 +8,7 @@ module.exports = { '**/test-node/**/*.js', '**/demo/**/*.js', '**/stories/**/*.js', + '**/docs/**/*.js', '**/*.config.js', ], rules: { diff --git a/.markdownlint.json b/.markdownlint.json index df0c79855..beda11a36 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -3,6 +3,6 @@ "line_length": -1 }, "no-trailing-punctuation": { - "punctuation": ".,;:!。,;:!" + "punctuation": ".,;。,;:!" } } diff --git a/.storybook/main.js b/.storybook/main.js index 6db921120..19cd7f675 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -3,9 +3,26 @@ const path = require('path'); module.exports = { stories: [ - '../packages/*/stories/*.stories.{js,mdx}', - '../packages/helpers/*/stories/*.stories.{js,mdx}', - '../demo/stories/*.stories.{js,mdx}', + '../packages/*/README.md', + '../packages/*/docs/*.md', + '../docs/README.md', + '../docs/**/*.md', + '../README.md', + '../demo/README.md', + '../demo/docs/*.md', + '../packages/helpers/README.md', + '../packages/helpers/*/README.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', diff --git a/README.md b/README.md index be472d400..8c3147b1e 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # Lion Web Components +```js script +export default { + title: 'Intro/Lion Web Components', +}; +``` + 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. @@ -13,6 +19,32 @@ We do have a [live Storybook](http://lion-web-components.netlify.com) which show **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 depencies by executing `yarn install`. +## Features + +- pure es modules +- exposes functions/classes and web components +- provides pure functionality +- fully accessible +- built to be extended + +> Note: These 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. + +## Systems + +Lion web components is logically organized in groups of systems. + +| System | Description | +| ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Forms](?path=/docs/forms-intro--page) | A system that lets you make complex forms with ease. Add validation, translations and use a wide range of pre made form controls. | +| [Buttons](?path=/docs/buttons-intro--page) | Every application needs buttons to allow interactions. These web components bring common UX patterns while still full integrated with (native) forms. | +| [Overlays](?path=/docs/overlays-intro--page) | If something needs to overlay content this is your place. Dialogs, Tooltips and a full overlay system to build more if needed | +| [Navigation](?path=/docs/navigation-intro--page) | Components which are used to guide users | +| [Localize](?path=/docs/localize-intro--page) | Localize text, numbers, dates and a way to store/fetch these data within web components | +| [Icons](?path=/docs/icons-intro--page) | Loading and displaying icons | +| [Others](?path=/docs/others-intro--page) | Features not fitting any other category | +| [Helpers](?path=/docs/helpers-intro--page) | Helpers to make your and your life easier | + ## How to install ```bash @@ -23,43 +55,43 @@ npm i @lion/ The accessibility column indicates whether the functionality is accessible in its core. Aspects like styling and content determine actual accessibility in usage. -| Package | Version | Description | Accessibility | -| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ | -------------------------- | -| **-- Buttons --** | | | | -| [button](./packages/button) | [![button](https://img.shields.io/npm/v/@lion/button.svg)](https://www.npmjs.com/package/@lion/button) | Button | ✔️ | -| [switch](./packages/switch) | [![switch](https://img.shields.io/npm/v/@lion/switch.svg)](https://www.npmjs.com/package/@lion/switch) | Switch | ✔️ | -| **-- Forms --** | | | | -| [form](./packages/form) | [![form](https://img.shields.io/npm/v/@lion/form.svg)](https://www.npmjs.com/package/@lion/form) | Wrapper for multiple form elements | ✔️ | -| [field](./packages/field) | [![field](https://img.shields.io/npm/v/@lion/field.svg)](https://www.npmjs.com/package/@lion/field) | Base Class for all inputs | ✔️ | -| [fieldset](./packages/fieldset) | [![fieldset](https://img.shields.io/npm/v/@lion/fieldset.svg)](https://www.npmjs.com/package/@lion/fieldset) | Group for form inputs | ✔️ | -| [validate](./packages/validate) | [![validate](https://img.shields.io/npm/v/@lion/validate.svg)](https://www.npmjs.com/package/@lion/validate) | Validation for form components | n/a | -| [checkbox](./packages/checkbox) | [![checkbox](https://img.shields.io/npm/v/@lion/checkbox.svg)](https://www.npmjs.com/package/@lion/checkbox) | Checkbox form element | ✔️ | -| [checkbox-group](./packages/checkbox-group) | [![checkbox-group](https://img.shields.io/npm/v/@lion/checkbox-group.svg)](https://www.npmjs.com/package/@lion/checkbox-group) | Group of checkboxes | ✔️ | -| [input](./packages/input) | [![input](https://img.shields.io/npm/v/@lion/input.svg)](https://www.npmjs.com/package/@lion/input) | Input element for strings | ✔️ | -| [input-amount](./packages/input-amount) | [![input-amount](https://img.shields.io/npm/v/@lion/input-amount.svg)](https://www.npmjs.com/package/@lion/input-amount) | Input element for amounts | ✔️ | -| [input-date](./packages/input-date) | [![input-date](https://img.shields.io/npm/v/@lion/input-date.svg)](https://www.npmjs.com/package/@lion/input-date) | Input element for dates | ✔️ | -| [input-datepicker](./packages/input-datepicker) | [![input-datepicker](https://img.shields.io/npm/v/@lion/input-datepicker.svg)](https://www.npmjs.com/package/@lion/input-datepicker) | Input element for dates with a datepicker | ✔️ | -| [input-email](./packages/input-email) | [![input-email](https://img.shields.io/npm/v/@lion/input-email.svg)](https://www.npmjs.com/package/@lion/input-email) | Input element for e-mails | ✔️ | -| [input-iban](./packages/input-iban) | [![input-iban](https://img.shields.io/npm/v/@lion/input-iban.svg)](https://www.npmjs.com/package/@lion/input-iban) | Input element for IBANs | ✔️ | -| [input-range](./packages/input-range) | [![input-range](https://img.shields.io/npm/v/@lion/input-range.svg)](https://www.npmjs.com/package/@lion/input-range) | Input element for a range of values | ✔️ | -| [radio](./packages/radio) | [![radio](https://img.shields.io/npm/v/@lion/radio.svg)](https://www.npmjs.com/package/@lion/radio) | Radio from element | ✔️ | -| [radio-group](./packages/radio-group) | [![radio-group](https://img.shields.io/npm/v/@lion/radio-group.svg)](https://www.npmjs.com/package/@lion/radio-group) | Group of radios | ✔️ | -| [select](./packages/select) | [![select](https://img.shields.io/npm/v/@lion/select.svg)](https://www.npmjs.com/package/@lion/select) | Simple native dropdown element | ✔️ | -| [textarea](./packages/textarea) | [![textarea](https://img.shields.io/npm/v/@lion/textarea.svg)](https://www.npmjs.com/package/@lion/textarea) | Multiline text input | ✔️ | -| **-- Overlays --** | | | | -| [overlays](./packages/overlays) | [![overlays](https://img.shields.io/npm/v/@lion/overlays.svg)](https://www.npmjs.com/package/@lion/overlays) | Overlay System | ✔️ | -| [dialog](./packages/dialog) | [![dialog](https://img.shields.io/npm/v/@lion/dialog.svg)](https://www.npmjs.com/package/@lion/dialog) | Dialog element | ✔️ | -| [tooltip](./packages/tooltip) | [![tooltip](https://img.shields.io/npm/v/@lion/tooltip.svg)](https://www.npmjs.com/package/@lion/tooltip) | Tooltip element | [#175][i175] | -| **-- Icons --** | | | | -| [icon](./packages/icon) | [![icon](https://img.shields.io/npm/v/@lion/icon.svg)](https://www.npmjs.com/package/@lion/icon) | Display our svg icons | [#173][i173], [#172][i172] | -| **-- Navigation --** | | | | -| [steps](./packages/steps) | [![steps](https://img.shields.io/npm/v/@lion/steps.svg)](https://www.npmjs.com/package/@lion/steps) | Multi Step System | n/a | -| [tabs](./packages/tabs) | [![tBS](https://img.shields.io/npm/v/@lion/tabs.svg)](https://www.npmjs.com/package/@lion/tabs) | Move between a small number of equally important views | n/a | -| **-- Others --** | | | | -| [core](./packages/core) | [![core](https://img.shields.io/npm/v/@lion/core.svg)](https://www.npmjs.com/package/@lion/core) | Core System (exports LitElement, lit-html) | n/a | -| [calendar](./packages/calendar) | [![calendar](https://img.shields.io/npm/v/@lion/calendar.svg)](https://www.npmjs.com/package/@lion/calendar) | Standalone calendar | [#195][i195], [#194][i194] | -| [localize](./packages/localize) | [![localize](https://img.shields.io/npm/v/@lion/localize.svg)](https://www.npmjs.com/package/@lion/localize) | Localize and translate your application/components | n/a | -| [ajax](./packages/ajax) | [![ajax](https://img.shields.io/npm/v/@lion/ajax.svg)](https://www.npmjs.com/package/@lion/ajax) | Fetching data via ajax request | n/a | +| Package | Version | Description | Accessibility | +| --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------ | -------------------------- | +| **-- Forms --** | | | ✔️ | +| [form](?path=/docs/forms-form-overview--page) | [![form](https://img.shields.io/npm/v/@lion/form.svg)](https://www.npmjs.com/package/@lion/form) | Wrapper for multiple form elements | ✔️ | +| [field](?path=/docs/forms-system-overview--page) | [![field](https://img.shields.io/npm/v/@lion/field.svg)](https://www.npmjs.com/package/@lion/field) | Base Class for all inputs | ✔️ | +| [fieldset](?path=/docs/forms-fieldset-overview--page) | [![fieldset](https://img.shields.io/npm/v/@lion/fieldset.svg)](https://www.npmjs.com/package/@lion/fieldset) | Group for form inputs | ✔️ | +| [validate](?path=/docs/form-system-validate-system--page) | [![validate](https://img.shields.io/npm/v/@lion/validate.svg)](https://www.npmjs.com/package/@lion/validate) | Validation for form components | n/a | +| [checkbox](?path=/docs/forms-checkbox--default-story) | [![checkbox](https://img.shields.io/npm/v/@lion/checkbox.svg)](https://www.npmjs.com/package/@lion/checkbox) | Checkbox form element | ✔️ | +| [checkbox-group](?path=/docs/forms-checkbox-group--default-story) | [![checkbox-group](https://img.shields.io/npm/v/@lion/checkbox-group.svg)](https://www.npmjs.com/package/@lion/checkbox-group) | Group of checkboxes | ✔️ | +| [input](?path=/docs/forms-input--default-story) | [![input](https://img.shields.io/npm/v/@lion/input.svg)](https://www.npmjs.com/package/@lion/input) | Input element for strings | ✔️ | +| [input-amount](?path=/docs/forms-input-amount--default-story) | [![input-amount](https://img.shields.io/npm/v/@lion/input-amount.svg)](https://www.npmjs.com/package/@lion/input-amount) | Input element for amounts | ✔️ | +| [input-date](?path=/docs/forms-input-date--default-story) | [![input-date](https://img.shields.io/npm/v/@lion/input-date.svg)](https://www.npmjs.com/package/@lion/input-date) | Input element for dates | ✔️ | +| [input-datepicker](?path=/docs/forms-input-datepicker--default-story) | [![input-datepicker](https://img.shields.io/npm/v/@lion/input-datepicker.svg)](https://www.npmjs.com/package/@lion/input-datepicker) | Input element for dates with a datepicker | ✔️ | +| [input-email](?path=/docs/forms-input-email--default-story) | [![input-email](https://img.shields.io/npm/v/@lion/input-email.svg)](https://www.npmjs.com/package/@lion/input-email) | Input element for e-mails | ✔️ | +| [input-iban](?path=/docs/forms-input-iban--default-story) | [![input-iban](https://img.shields.io/npm/v/@lion/input-iban.svg)](https://www.npmjs.com/package/@lion/input-iban) | Input element for IBANs | ✔️ | +| [input-range](?path=/docs/forms-input-range--default-story) | [![input-range](https://img.shields.io/npm/v/@lion/input-range.svg)](https://www.npmjs.com/package/@lion/input-range) | Input element for a range of values | ✔️ | +| [radio](?path=/docs/forms-radio--default-story) | [![radio](https://img.shields.io/npm/v/@lion/radio.svg)](https://www.npmjs.com/package/@lion/radio) | Radio from element | ✔️ | +| [radio-group](?path=/docs/forms-radio-group--default-story) | [![radio-group](https://img.shields.io/npm/v/@lion/radio-group.svg)](https://www.npmjs.com/package/@lion/radio-group) | Group of radios | ✔️ | +| [select](?path=/docs/forms-select--default-story) | [![select](https://img.shields.io/npm/v/@lion/select.svg)](https://www.npmjs.com/package/@lion/select) | Simple native dropdown element | ✔️ | +| [textarea](?path=/docs/forms-textarea--default-story) | [![textarea](https://img.shields.io/npm/v/@lion/textarea.svg)](https://www.npmjs.com/package/@lion/textarea) | Multiline text input | ✔️ | +| **-- Buttons --** | | | | +| [button](?path=/docs/buttons-button--default-story) | [![button](https://img.shields.io/npm/v/@lion/button.svg)](https://www.npmjs.com/package/@lion/button) | Button | ✔️ | +| [switch](?path=/docs/buttons-switch--default-off) | [![switch](https://img.shields.io/npm/v/@lion/switch.svg)](https://www.npmjs.com/package/@lion/switch) | Switch | ✔️ | +| **-- Overlays --** | | | | +| [overlays](?path=/docs/overlays-system-overview--default-story) | [![overlays](https://img.shields.io/npm/v/@lion/overlays.svg)](https://www.npmjs.com/package/@lion/overlays) | Overlay System | ✔️ | +| [dialog](?path=/docs/overlays-dialog--default-story) | [![dialog](https://img.shields.io/npm/v/@lion/dialog.svg)](https://www.npmjs.com/package/@lion/dialog) | Dialog element | ✔️ | +| [tooltip](?path=/docs/overlays-tooltip--default-story) | [![tooltip](https://img.shields.io/npm/v/@lion/tooltip.svg)](https://www.npmjs.com/package/@lion/tooltip) | Tooltip element | [#175][i175] | +| **-- Icons --** | | | | +| [icon](?path=/docs/icons-icon--default-story) | [![icon](https://img.shields.io/npm/v/@lion/icon.svg)](https://www.npmjs.com/package/@lion/icon) | Display our svg icons | [#173][i173], [#172][i172] | +| **-- Navigation --** | | | | +| [steps](?path=/docs/navigation-steps--default-story) | [![steps](https://img.shields.io/npm/v/@lion/steps.svg)](https://www.npmjs.com/package/@lion/steps) | Multi Step System | n/a | +| [tabs](?path=/docs/navigation-tabs--default-story) | [![tBS](https://img.shields.io/npm/v/@lion/tabs.svg)](https://www.npmjs.com/package/@lion/tabs) | Move between a small number of equally important views | n/a | +| **-- Others --** | | | | +| [core](?path=/docs/deep-dives-core--page) | [![core](https://img.shields.io/npm/v/@lion/core.svg)](https://www.npmjs.com/package/@lion/core) | Core System (exports LitElement, lit-html) | n/a | +| [localize](?path=/docs/localize-localize--default-story) | [![localize](https://img.shields.io/npm/v/@lion/localize.svg)](https://www.npmjs.com/package/@lion/localize) | Localize and translate your application/components | n/a | +| [ajax](?path=/docs/others-ajax--default-story) | [![ajax](https://img.shields.io/npm/v/@lion/ajax.svg)](https://www.npmjs.com/package/@lion/ajax) | Fetching data via ajax request | n/a | +| [calendar](?path=/docs/calendar--default-story) | [![calendar](https://img.shields.io/npm/v/@lion/calendar.svg)](https://www.npmjs.com/package/@lion/calendar) | Standalone calendar | [#195][i195], [#194][i194] | ## How to use @@ -135,100 +167,6 @@ Check out our [coding guidelines](./docs/README.md) for more detailed informatio Lion Web Components are only as good as its contributions. Read our [contribution guide](./CONTRIBUTING.md) and feel free to enhance/improve Lion. We keep feature requests closed while we're not working on them. -## Scoped elements - -The [CustomElementRegistry](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry) provides methods for registering custom elements. One of the limitations of working with this global registry is that multiple versions of the same element cannot co-exist. This causes bottlenecks in software delivery that should be managed by the teams and complex build systems. [Scoped Custom Element Registries](https://github.com/w3c/webcomponents/issues/716) is a proposal that will solve the problem. Since this functionality won't be available (especially not cross browser) anytime soon, we've adopted [OpenWC's Scoped Elements](https://open-wc.org/scoped-element). - -Whenever a lion component uses composition (meaning it uses another lion component inside), we -apply ScopedElementsMixin to make sure it uses the right version of this internal component. - -```js -import { ScopedElementsMixin, LitElement, html } from '@lion/core'; - -import { LionInput } from '@lion/input'; -import { LionButton } from '@lion/button'; - -class MyElement extends ScopedElementsMixin(LitElement) { - static get scopedElements() { - return { - 'lion-input': LionInput, - 'lion-button': LionButton, - }; - } - - render() { - return html` - - Save - `; - } -} -``` - -### Query selectors - -Since Scoped Elements changes tagnames under the hood, a tagname querySelector should be written -like this: - -```js -this.querySelector(this.constructor.getScopedTagName('lion-input')); -``` - -### CSS selectors - -Avoid tagname css selectors (we already avoid query selectors internally in lion, but just be aware -that a selector like `lion-input {...}` will stop working ). - -### Edge cases - -Sometimes we need to render parts of a template to light dom for [accessibility](https://wicg.github.io/aom/explainer.html). For instance we render a node via lit-html that we append to the host element, so -it gets slotted in the right position. -In this case, we should also make sure that we also scope the rendered element. - -We can do this as follows: - -```js -_myLightTemplate() { - return html` - This template may be overridden by a Subclasser. - Even I don't end up in shadow root, I need to be scoped to constructor.scopedElements as well. -
- True - -
- `; -} - -__getLightDomNode() { - const renderParent = document.createElement('div'); - this.constructor.render(this._myLightTemplate(), renderParent, { - scopeName: this.localName, - eventContext: this, - }); - // this node will be appended to the host - return renderParent.firstElementChild; -} - -connectedCallback() { - super.connectedCallback(); - this.appendChild(this.__getLightDomNode()); -} -``` - -In a less complex case, we might just want to add a child node to the dom. - -```js -import { ScopedElementsMixin, LitElement } from '@lion/core'; - -... - -__getLightDomNode() { - return document.createElement(this.constructor.getScopedTagName('lion-input')); -} -``` - -We encourage you to have a look at [OpenWC's Scoped elements](https://open-wc.org/scoped-elements). - ## Contact Feel free to create a github issue for any feedback or questions you might have. @@ -236,11 +174,6 @@ You can also find us on the Polymer slack in the [#lion](https://polymer.slack.c You can join the Polymer slack by visiting [https://www.polymer-project.org/slack-invite](https://www.polymer-project.org/slack-invite). -## Support and issues - -As stated above "support and issues time" is currently rather limited: feel free to open a discussion. -However, we can not guarantee any response times. - [i172]: https://github.com/ing-bank/lion/issues/172 [i173]: https://github.com/ing-bank/lion/issues/173 [i175]: https://github.com/ing-bank/lion/issues/175 diff --git a/demo/stories/10-announcement.stories.mdx b/demo/README.md similarity index 97% rename from demo/stories/10-announcement.stories.mdx rename to demo/README.md index a0bf42454..8e0f442d7 100644 --- a/demo/stories/10-announcement.stories.mdx +++ b/demo/README.md @@ -1,9 +1,11 @@ -import { Story, Meta, html, Preview } from '@open-wc/demoing-storybook'; - - - # ING open sources Lion: A library of performant, accessible & flexible Web Components +```js script +export default { + title: 'Intro/Announcement', +}; +``` + **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). As some of you may already know, ING has a long and rich history of building Web Components, starting out with the Polymer library, all the way up to the recently released LitElement. @@ -18,7 +20,7 @@ So today, I'm happy to share with you all that ING is open-sourcing its own core Imagine the following fictional scenario: -> Lea is a developer who works at Betatech, and is working on a new in-house application. +> Lea is a developer who works at Betatech, and is working on a new in-house application. ### Framework Agnostic @@ -51,6 +53,7 @@ Or, alternatively Does Lea's story feel relatable? It highlights multiple common issues in modern web development: + - Finding and adding a dependency is a big deal - Picking something because of looks alone might not always be the best choice - Adjusting behavior or styling can be tough to maintain @@ -60,7 +63,7 @@ It highlights multiple common issues in modern web development: 🤔 Imagine having components that purely focus on functionality, and leave the design up to you 🤔 Imagine that these components come with great accessibility and performance -🤔 Imagine these components are highly extendable and flexible +🤔 Imagine these components are highly extendable and flexible Now stop imagining, and look at Lion 🦁 @@ -71,20 +74,22 @@ Now stop imagining, and look at Lion 🦁 Lion is a white-label, open-source, framework-agnostic component library, and can be the foundation for your codified in-house Design System. Aligning on design and usability is already a tough challenge, with Lion, we hope to take some of the work out of your hands. ### White Label + Lion is a core package of white label Web Components. What this means is that the core components only consist of very minimal styling, yet has all the fundamental functionalities. White label products are often created so others can easily rebrand them with their own visual identity. This is great because it means that everyone can use the core functionalities of our components while bringing their own branding or Design System because surprisingly, not everyone loves orange. 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: -![Lion - ing-web side by side](https://raw.githubusercontent.com/ing-bank/lion/master/demo/stories/side-by-side.png) +![Lion - ing-web side by side](https://raw.githubusercontent.com/ing-bank/lion/master/demo/docs/assets/side-by-side.png) ### 🎯 Focus + Lion was designed with a focus on global usage and reusability in mind. And as such, the following features were incorporated right from the start: ♻️ Reusability - Our components are meant to be distributed and used on a global scale 🚹 Accessibility - Our components are meant to be accessible for everyone -🚀 Performance - Our components are meant to be small, performant and fast +🚀 Performance - Our components are meant to be small, performant and fast These features allow us to roll out our components globally and have a single point of truth. It ensures that everyone in ING has a solid set of building blocks to build their application with, and get up and running in no time. @@ -102,7 +107,7 @@ Lion is built from the ground up to allow for accessibility and extendability as > Everyone should use web components but not everyone should write them -*- [Erik Kroes](https://twitter.com/erikkroes)* +_- [Erik Kroes](https://twitter.com/erikkroes)_ ## 🙋‍ Join us! @@ -116,7 +121,7 @@ Additionally, the more users and contributors Lion has, the more stable the Lion ### Contribute to Lion! -At the time of writing, Lion is still in beta phase. We'd love to have your feedback before going to a stable release, so: Do you like open source, and do you want to help Lion out? +At the time of writing, Lion is still in beta phase. We'd love to have your feedback before going to a stable release, so: Do you like open source, and do you want to help Lion out? You can do so by: - Reporting/fixing issues @@ -153,7 +158,7 @@ export class LeaTabs extends LionTabs { super.styles, css` /* my stylings */ - ` + `, ]; } @@ -177,7 +182,9 @@ import { LitElement, html, css } from 'lit-element'; export class LeaTab extends LitElement { static get styles() { - return css`/* my stylings */`; + return css` + /* my stylings */ + `; } render() { diff --git a/demo/docs/20-lea-tabs.md b/demo/docs/20-lea-tabs.md new file mode 100644 index 000000000..4ece82176 --- /dev/null +++ b/demo/docs/20-lea-tabs.md @@ -0,0 +1,253 @@ +# 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 'lit-html'; +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` + + Info + + Info page with lots of information about us. + + Work + + Work page that showcases our work. + + +`; +``` + +## How to use + +### Installation + +```sh +npm i --save @lion/tabs; +``` + +### Usage + +```js +import '@lion/tabs/lea-tabs.js'; +``` + +```html + + Info + + Info page with lots of information about us. + + Work + + Work page that showcases our work. + + +``` + +## Examples + +### Selected Index + +You can set the `selectedIndex` to select a certain tab. + +```js preview-story +export const selectedIndex = () => html` + + Info + + Info page with lots of information about us. + + Work + + Work page that showcases our work. + + +`; +``` + +### 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` + + Info + Work + + Info page with lots of information about us. + + + Work page that showcases our work. + + +`; +``` + +### 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` +

Append

+ + + tab 1 + panel 1 + tab 2 + panel 2 + +
+

Push

+ + + tab 1 + panel 1 + tab 2 + panel 2 + ${this.__collection.map( + item => html` + ${item.button} + ${item.panel} + `, + )} + + `; + } + 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` + + `; +}; +``` + +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 + + ${myCollection.map(item => html` + ${item.button} + ${item.panel} + `)} + +``` + +## 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 + +> 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. diff --git a/demo/stories/side-by-side.png b/demo/docs/assets/side-by-side.png similarity index 100% rename from demo/stories/side-by-side.png rename to demo/docs/assets/side-by-side.png diff --git a/demo/stories/20-lea-tabs.stories.mdx b/demo/stories/20-lea-tabs.stories.mdx deleted file mode 100644 index 384b9eff6..000000000 --- a/demo/stories/20-lea-tabs.stories.mdx +++ /dev/null @@ -1,255 +0,0 @@ -import { Story, Meta, html, Preview } from '@open-wc/demoing-storybook'; -import { LitElement } from '@lion/core'; - -import '../lea-tabs.js'; -import '../lea-tab.js'; -import '../lea-tab-panel.js'; - - - -# 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. - - - - {html` - - Info - - Info page with lots of information about us. - - Work - - Work page that showcases our work. - - - `} - - - -## How to use - -### Installation - -```sh -npm i --save @lion/tabs; -``` - -### Usage - -```js -import '@lion/tabs/lea-tabs.js'; -``` - -```html - - Info - - Info page with lots of information about us. - - Work - - Work page that showcases our work. - - -``` - -## Examples - -### Selected Index - -You can set the `selectedIndex` to select a certain tab. - - - - {html` - - Info - - Info page with lots of information about us. - - Work - - Work page that showcases our work. - - - `} - - - -### 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. - - - - {html` - - Info - Work - - Info page with lots of information about us. - - - Work page that showcases our work. - - - `} - - - -### Distribute New Elements - -Below, we demonstrate on how you could dynamically add new tab + panels. - - - {() => { - 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` -

Append

- - - tab 1 - panel 1 - tab 2 - panel 2 - -
-

Push

- - - tab 1 - panel 1 - tab 2 - panel 2 - ${this.__collection.map( - item => html` - ${item.button} - ${item.panel} - `, - )} - - `; - } - 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` - - `; - }} -
- -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 - - ${myCollection.map(item => html` - ${item.button} - ${item.panel} - `)} - -``` - -## 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 - -> 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. diff --git a/docs/README.md b/docs/README.md index 9671ac7c7..74610c7a8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,5 +1,13 @@ # Coding Guidelines -First be sure to understand our [definitions](./definitions.md). +```js script +export default { + title: 'Guidelines/Intro', +}; +``` -- [Guidelines for Styling](./guidelines-styling.md) +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) diff --git a/docs/definitions.md b/docs/definitions.md deleted file mode 100644 index 81bd921fc..000000000 --- a/docs/definitions.md +++ /dev/null @@ -1,52 +0,0 @@ -# Definitions and terms - -Below you will find a list of definitions and terms that will be used throughout our code -documentation. - -- `Application Developer`: - Developers consuming our webcomponents inside an application (not extending them). - Application Developers are only allowed to interact with `public` properties and methods. - Can be abbreviated as `AD`. Sometimes also called `Consuming Developer`. - -- `Subclasser`: - Developers extending our webcomponents. For instance: `MaterialInput extends LionInput`. - Subclassers have access to protected methods (prefixed with an underscore or marked as protected), - but not to private methods. - -- `public`: - Methods and properties are public when they are not prefixed by an underscore. - They can be used by Application Developers. - - ```js - class SoccerPlayer { - kickBall() { - // Soccer player can kick a ball - } - } - ``` - -- `protected`: - Methods and properties are protected when they contain one underscore or are explicitly marked as - protected in the code. - They can be used by Subclassers. - - ```js - class SoccerPlayer { - _catchBall() { - // Soccer player usually do not need to catch a ball (with it's hands) - } - } - ``` - -- `private`: - Methods and properties are protected when they contain two underscores or are explicitly marked as - private in the code. - They can be used within the class where they are defined (developers of Lion components). - - ```js - class SoccerPlayer { - __score() { - // internally save how many goals have been made - } - } - ``` diff --git a/docs/guidelines-styling.md b/docs/guidelines-styling.md deleted file mode 100644 index 77ceaf519..000000000 --- a/docs/guidelines-styling.md +++ /dev/null @@ -1,205 +0,0 @@ -# Guidlines for Styling - -## Markup and styling - -All Lion webcomponents have white label styling: this means theming is not applied, -but functional styling is. - -### Functional styling - -Functional styling can be divided into defaults for 'basic layout' and 'accessibility'. -Examples for both categories can be found below: - -- Basic layout examples: - - - A dropdown menu has 'position: absolute' - - A lion-button might behave as an 'display: inline-block' element - - A suffix attached to an input is horizontally positioned (instead of vertically stacked) - -- Accessibility examples: - - content (for instance a caption in a table) can be 'visually hidden': it will be - readable by screen readers, but invisible for end users - - when an html table is used, we allow [subclassers](./definitions.md) to override the display - property ('table-cell') to 'flex'. By putting the proper accessible roles ('role="cell"') in the - markup, we guaruantee our markup stays accessible - -Although Lion components try to stay as unbiased as possible with regard to styling, defaults will -be needed. In these cases we try to follow the platform as much as possible. If the platform -doesn't provide defaults, the largest common denominator across exisiting UI frameworks is taken as -a lead. - -## Style components - -A style component consists of a set of css classes mapping to a certain html structure. Although css -components are often implemented by webcomponents, they should be considered modules on their own, -reusable in different contexts: they should be considered the lowest abstraction layer of a -webcomponent. - -A webcomponent usually implements a css module (mapped at host level), but the opposite is not -necessarily true: a css module doesn't have to be used inside a webcomponent or at the root level -of a webcomponent. - -Advantages of developing style components isolated from webcomponents are: - -- They can be reused in non shadow dom contexts. -- Not everything has to be a webcomponent: anchor or card styling inside a webcomponent would be a - matter of importing a style component into a shadowroot. - -### Requirements - -Style components are written with the following assumptions in mind: - -- **Environment agnostic**: Lion webcomponents are unopinionated about their environment: they - should be usable in every context/framework/technology thinkable, regardless of whether shadow dom - is used. -- **Customisable**: They should provide an api for [subclassers](./definitions.md): - - **white label**: components (just like webcomponents) are white label components. They provide - a flexible html structure which should be mappable to any Design System. - This approach is inspired by [Inuitcss](https://github.com/inuitcss/inuitcss) (an architectural - foundation for white label style components) and [Bootstrap Material](https://fezvrasta.github.io/bootstrap-material-design/) - (a Material Design system based on existing Bootstrap html/class names). - This is also [a great example of a Design System](https://www.carbondesignsystem.com/components/checkbox/code) - taking this(style components as lowest abstraction layer) approach. - - **well structured**: for clear, readable and maintainable code we use [BEM](http://getbem.com/): - it forces the - developer to think about component structure in terms of 'block', 'element' and 'modifier' - parts/roles. The classes defined in a BEM component form the api for a - [subclasser](./definitions.md): he can 'fill in' the BEM selectors by overriding them in the - `static get styles()` configuration property on the constructor of a webcomponent. - - **flexible markup**: By making the HTML structure purposely 'loose', multiple Design Systems can - be made compatible with the style component. When the default html/css structure is not flexible - enough, it can be extended by creating new BEM element selectors. - -## Why BEM? - -For css class naming, we use [BEM](http://getbem.com/) naming conventions. This helps you identify -semantics of your markup at a quick glance, resulting in more readable and maintainable code. -BEM provides us the following advantages: - -- **Clear namings** that convey meaning about semantics and structure at a quick glance -- **Prevent collisions** within shadow roots. Larger shadow roots using multiple style components - would easily collide when css selectors would be scoped to the shadow dom in which they were - created. For instance, calling the header of a card '.header' instead of '.c-card\_\_header' - would make the card component not reusable in different contexts. -- **Maximum flexibility** we can write css regardless of context. When we create a style component - for a card, we can offer it as a style component only and later decide to offer it as a webcomponent. - Or offer the style component - as a more lower level api for advanced use cases and the webcomponent (that has limiting markup and - styling options) for the majority of cases. - Also, when we already have a webcomponent for the card and people want to create a custom card - component, it might make more sense to write a new webcomponent instead of extending the existing - card webcomponent. - Having style components as described above, allows for maximum flexibility in these scenarios. - Future CSS updates can then be done from a central place, without having to rewrite forked webcomponents. -- **Performance** we aim for applications having a limited number of shadow roots and we consider - shadow root creation a performance concern. Style components reduce the need for shadow roots. - - -### Challenges with BEM in shadow dom - -Mapping BEM components to shadow root is not really straightforward: - -1. host styles should be rewritten to `:host {}` instead of `.my-block {}` -2. slot styles be rewritten to `::slotted(.my-block__element)` instead of `.my-block__element` -3. we should not [self-apply classes](https://developers.google.com/web/fundamentals/web-components/best-practices) - on host level. Apart from this being a bad practice, it will trigger linting errors in our setup. - -### Mapping host and slot styles - -The [CSS Module](https://github.com/w3c/webcomponents/issues/759) and [CSS Selector](https://github.com/w3c/csswg-drafts/issues/3714) proposals would allow us to reuse BEM components more easily within webcomponents. -We might also think about other ways of creating build steps that would allow us to map BEM -components to a shadow root, making it possible to map hosts and slots in an eay way. - - - -### No self-application of classes - -In order to adhere to this rule, notation of our BEM modifiers that live on the host (which are -ususally written like `.my-block--my-modifier`) will be rewritten to `.my-block[my-modifier]` -Although this would only be needed for the third challenge as described above, for consistency, -we apply it to all our modifiers within our style component. -So for instance `.my-block__element--my-other-modifier` becomes -`.my-block__element[my-other-modifier]`. - -### Why mapping style components to the host matters - -- **flexible host overrides**: - Imagine we have a style component `.c-alert` and we want to map this to a webcomponent ``. - In our Design system it might be a good practice to give all our block components a default bottom - margin of 16px. An [Application Developer](./definitions.md) might need an instance of `` where he wants to - set this bottom margin to 0. - If the margin-bottom of 16px would not be defined on the host level but one level deeper (the first - div element within the shadow root of ``), the Application Developer needs to apply a - negative margin of -16px. The latter would be a bad practice. - -- **easily map modifiers**: - If we continue with our alert example and we have a flag 'is-closeable', we might need to adjust - styling based on that. In this case we assume the attribute 'is-closeable' serves as a styling - hook for the `.c-alert` component. - -## Css variables - -Css variables will not be added in our white label style components, but adding them in your own -extension layer would be a perfect fit. - -## Parts and themes - -The `::part` and `::theme` specs might currently not be widely adopted enough to be used inside -style components. When they are, we could be consider to add them later to our components as a means -to theme components (changing a whole Design System is not a good idea). - - - - diff --git a/docs/guidelines/10-guidelines-definitions.md b/docs/guidelines/10-guidelines-definitions.md new file mode 100644 index 000000000..d44cc3312 --- /dev/null +++ b/docs/guidelines/10-guidelines-definitions.md @@ -0,0 +1,63 @@ +# Guidelines definitions and terms + +```js script +export default { + title: 'Guidelines/Definitions', +}; +``` + +Below you will find a list of definitions and terms that will be used throughout our code +documentation. + +## Application Developer + +Developers consuming our web components inside an application (not extending them). +Application Developers are only allowed to interact with `public` properties and methods. +Can be abbreviated as `AD`. Sometimes also called `Consuming Developer`. + +## Subclasser + +Developers extending our web components. For instance: `class MaterialInput extends LionInput`. +Subclassers have access to protected methods (prefixed with an underscore or marked as protected), +but not to private methods. + +## public + +Methods and properties are public when they are not prefixed by an underscore. +They can be used by Application Developers. + +```js +class SoccerPlayer { + kickBall() { + // Soccer player can kick a ball + } +} +``` + +## protected + +Methods and properties are protected when they contain one underscore or are explicitly marked as +protected in the code. +They can be used by Subclassers. + +```js +class SoccerPlayer { + _catchBall() { + // Soccer player usually do not need to catch a ball (with it's hands) + } +} +``` + +## private + +Methods and properties are protected when they contain two underscores or are explicitly marked as +private in the code. +They can be only used within the class where they are defined (developers of Lion components). + +```js +class SoccerPlayer { + __score() { + // internally save how many goals have been made + } +} +``` diff --git a/docs/guidelines/20-guidelines-styling.md b/docs/guidelines/20-guidelines-styling.md new file mode 100644 index 000000000..e7a3ea9d4 --- /dev/null +++ b/docs/guidelines/20-guidelines-styling.md @@ -0,0 +1,46 @@ +# Guidelines for Styling + +```js script +export default { + title: 'Guidelines/Styling', +}; +``` + +## Markup and styling + +All Lion web components have white label styling: this means theming is not applied, +but functional styling is. + +### Functional styling + +Functional styling can be divided into defaults for `basic layout` and `accessibility`. +Examples for both categories can be found below: + +- Basic layout examples: + + - A dropdown menu has `position: absolute;` + - A lion-button might behave as an `display: inline-block;` element + - A suffix attached to an input is horizontally positioned (instead of vertically stacked) + +- Accessibility examples: + - content (for instance a caption in a table) can be `visually hidden`: it will be + readable by screen readers, but invisible for end users + - when an html table is used, we allow [subclassers](?path=/docs/guidelines-definitions--page#subclasser) to override the display + property (`table-cell`) to `flex`. By putting the proper accessible roles (`role="cell"`) in the + markup, we guarantee our markup stays accessible + +Although Lion components try to stay as unbiased as possible with regard to styling, defaults will +be needed. In these cases we try to follow the platform as much as possible. If the platform +doesn't provide defaults, the largest common denominator across existing UI frameworks is taken as +a lead. + +## Css variables + +Css variables will not be added in our white label style components, but adding them in your own +extension layer would be a perfect fit. + +## Parts and themes + +The `::part` and `::theme` specs might currently not be widely adopted enough to be used inside +style components. When they are, we could be consider to add them later to our components as a means +to theme components (changing a whole Design System is not a good idea). diff --git a/docs/guidelines/30-guidelines-scoped-elements.md b/docs/guidelines/30-guidelines-scoped-elements.md new file mode 100644 index 000000000..74f616ed7 --- /dev/null +++ b/docs/guidelines/30-guidelines-scoped-elements.md @@ -0,0 +1,107 @@ +# Guidelines Scoped Elements + +```js script +export default { + title: 'Guidelines/Scoped Elements', +}; +``` + +The [CustomElementRegistry](https://developer.mozilla.org/en-US/docs/Web/API/CustomElementRegistry) provides methods for registering custom elements. One of the limitations of working with this global registry is that multiple versions of the same element cannot co-exist. This causes bottlenecks in software delivery that should be managed by the teams and complex build systems. [Scoped Custom Element Registries](https://github.com/w3c/webcomponents/issues/716) is a proposal that will solve the problem. Since this functionality won't be available (especially not cross browser) anytime soon, we've adopted [OpenWC's Scoped Elements](https://open-wc.org/scoped-element). + +Whenever a lion component uses composition (meaning it uses another lion component inside), we +apply ScopedElementsMixin to make sure it uses the right version of this internal component. + +```js +import { ScopedElementsMixin, LitElement, html } from '@lion/core'; + +import { LionInput } from '@lion/input'; +import { LionButton } from '@lion/button'; + +class MyElement extends ScopedElementsMixin(LitElement) { + static get scopedElements() { + return { + 'lion-input': LionInput, + 'lion-button': LionButton, + }; + } + + render() { + return html` + + Save + `; + } +} +``` + +## Query selectors + +Since Scoped Elements changes tagnames under the hood, a tagname querySelector should be written +like this: + +```js +this.querySelector(getTagName('lion-input', this.constructor.scopedElements)); +``` + +## CSS selectors + +Avoid tagname css selectors. +We already avoid query selectors internally in lion, but just be aware that a selector like + +```css +lion-input { + padding: 20px; +} +``` + +will stop working. + +## Edge cases + +Sometimes we need to render parts of a template to light dom for [accessibility](https://wicg.github.io/aom/explainer.html). For instance we render a node via lit-html that we append to the host element, so +it gets slotted in the right position. +In this case, we should also make sure that we also scope the rendered element. + +We can do this as follows: + +```js +_myLightTemplate() { + return html` + This template may be overridden by a Subclasser. + Even I don't end up in shadow root, I need to be scoped to constructor.scopedElements as well. +
+ True + +
+ `; +} + +__getLightDomNode() { + const renderParent = document.createElement('div'); + this.constructor.render(this._myLightTemplate(), renderParent, { + scopeName: this.localName, + eventContext: this, + }); + // this node will be appended to the host + return renderParent.firstElementChild; +} + +connectedCallback() { + super.connectedCallback(); + this.appendChild(this.__getLightDomNode()); +} +``` + +In a less complex case, we might just want to add a child node to the dom. + +```js +import { ScopedElementsMixin, LitElement, getScopedTagNamegetScopedTagName } from '@lion/core'; + +... + +__getLightDomNode() { + return document.createElement(getScopedTagName('lion-input', this.constructor.scopedElements)); +} +``` + +We encourage you to have a look at [OpenWC's Scoped elements](https://open-wc.org/scoped-elements). diff --git a/docs/subclasser-apis.md b/docs/guidelines/40-guidelines-subclasser-apis.md similarity index 67% rename from docs/subclasser-apis.md rename to docs/guidelines/40-guidelines-subclasser-apis.md index 41bfe1022..207e8ea01 100644 --- a/docs/subclasser-apis.md +++ b/docs/guidelines/40-guidelines-subclasser-apis.md @@ -1,5 +1,11 @@ # Subclasser apis +```js script +export default { + title: 'Guidelines/Subclasser APIs', +}; +``` + In order to make it easy for Subclassers to extend our components, we follow a certain set of best practices naming conventions to make our code predictable. @@ -7,20 +13,19 @@ of best practices naming conventions to make our code predictable. ### Template naming conventions -For template, we have the naming convention that every overridable template starts with an -underscore and ends with +For template, that do need access to the instance of the web component there is a prefix `_render/__render`. +Examples are `__renderHeader` and `__renderData`. -### Seperation of concerns +### Separation of concerns Our components should make it possible to override markup and styling, without having to redefine functionality. -By using the spread directive, we can achieve this. For more info, see: -[https://github.com/ing-bank/lion/issues/591](explanation). +By using the spread directive, we can achieve this. For more info, see [explanation](https://github.com/ing-bank/lion/issues/591). ## Node references As a Subclasser, you sometimes need access to a protected node inside the shadow dom. -Most functional nodes have their own getters. A Subclasser can acces those in his extension and +Most functional nodes have their own getters. A Subclasser can access those in his extension and in some cases, override these getters. ### Node naming conventions diff --git a/docs/intros/intros-buttons.md b/docs/intros/intros-buttons.md new file mode 100644 index 000000000..37f17609d --- /dev/null +++ b/docs/intros/intros-buttons.md @@ -0,0 +1,22 @@ +# Buttons + +Buttons are clickable elements. + +## Features + +- fully accessible + +## Packages + +The following buttons area published. + +| Package | Version | Description | +| --------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | ----------- | +| [button](?path=/docs/buttons-button--default-story) | [![button](https://img.shields.io/npm/v/@lion/button.svg)](https://www.npmjs.com/package/@lion/button) | Button | +| [switch](?path=/docs/buttons-switch--default-off) | [![switch](https://img.shields.io/npm/v/@lion/switch.svg)](https://www.npmjs.com/package/@lion/switch) | Switch | + +```js script +export default { + title: 'Buttons/Intro', +}; +``` diff --git a/packages/intros/stories/icon-intro.stories.mdx b/docs/intros/intros-icon.md similarity index 87% rename from packages/intros/stories/icon-intro.stories.mdx rename to docs/intros/intros-icon.md index a878edcee..1b7e7e24b 100644 --- a/packages/intros/stories/icon-intro.stories.mdx +++ b/docs/intros/intros-icon.md @@ -1,7 +1,3 @@ -import { Story, Meta, html } from '@open-wc/demoing-storybook'; - - - # Icons Icon system for managing iconsets, taking into account performance, maintainability and scalability. @@ -13,3 +9,9 @@ Icons are SVGs so they can be easily scaled and styled with CSS. | Package | Version | Description | | --------------------------------------------- | ------------------------------------------------------------------------------------------------ | ----------- | | [icon](?path=/docs/icons-icon--default-story) | [![icon](https://img.shields.io/npm/v/@lion/icon.svg)](https://www.npmjs.com/package/@lion/icon) | Icon | + +```js script +export default { + title: 'Icons/Intro', +}; +``` diff --git a/docs/intros/intros-navigation.md b/docs/intros/intros-navigation.md new file mode 100644 index 000000000..c221c9576 --- /dev/null +++ b/docs/intros/intros-navigation.md @@ -0,0 +1,20 @@ +# Navigation + +Navigational elements are used to guide users within your page. + +## Features + +- fully accessible + +## Packages + +| Package | Version | Description | +| ---------------------------------------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | +| [steps](?path=/docs/navigation-steps--default-story) | [![steps](https://img.shields.io/npm/v/@lion/steps.svg)](https://www.npmjs.com/package/@lion/steps) | Multi Step System | +| [tabs](?path=/docs/navigation-tabs--default-story) | [![tBS](https://img.shields.io/npm/v/@lion/tabs.svg)](https://www.npmjs.com/package/@lion/tabs) | Move between a small number of equally important views | + +```js script +export default { + title: 'Navigation/Intro', +}; +``` diff --git a/docs/intros/intros-others.md b/docs/intros/intros-others.md new file mode 100644 index 000000000..18a669150 --- /dev/null +++ b/docs/intros/intros-others.md @@ -0,0 +1,17 @@ +# Others + +Features not fitting any other category. + +## Packages + +| Package | Version | Description | +| ------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ | ----------- | +| [ajax](?path=/docs/others-ajax--default-story) | [![ajax](https://img.shields.io/npm/v/@lion/ajax.svg)](https://www.npmjs.com/package/@lion/ajax) | Ajax | +| [calendar](?path=/docs/others-calendar--default-story) | [![calendar](https://img.shields.io/npm/v/@lion/calendar.svg)](https://www.npmjs.com/package/@lion/calendar) | Calendar | +| [core](?path=/docs/others-system-core--page) | [![core](https://img.shields.io/npm/v/@lion/core.svg)](https://www.npmjs.com/package/@lion/core) | Core | + +```js script +export default { + title: 'Others/Intro', +}; +``` diff --git a/docs/rationals/001-side-effects.md b/docs/rationals/001-side-effects.md index d6a84b766..be313baa2 100644 --- a/docs/rationals/001-side-effects.md +++ b/docs/rationals/001-side-effects.md @@ -198,6 +198,12 @@ console.log(somethingElse2); // console.log(ctrl.manager.list); ``` +```js script +export default { + title: 'Rationals/Side Effects', +}; +``` + [1]: https://rollupjs.org/repl/?version=2.10.2&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmltcG9ydCUyMCU3QiUyMHNvbWV0aGluZ0Vsc2UlMkMlMjBvdmVybGF5cyUyMCU3RCUyMGZyb20lMjAnLiUyRm92ZXJsYXlzLmpzJyUzQiU1Q24lNUNuY29uc29sZS5sb2coc29tZXRoaW5nRWxzZSklM0IlMjIlMkMlMjJpc0VudHJ5JTIyJTNBdHJ1ZSU3RCUyQyU3QiUyMm5hbWUlMjIlM0ElMjJvdmVybGF5cy5qcyUyMiUyQyUyMmNvZGUlMjIlM0ElMjJjbGFzcyUyME92ZXJsYXlNYW5hZ2VyJTIwJTdCJTdEJTVDbiU1Q25leHBvcnQlMjBsZXQlMjBvdmVybGF5cyUyMCUzRCUyMG5ldyUyME92ZXJsYXlNYW5hZ2VyKCklM0IlNUNuJTVDbmV4cG9ydCUyMGZ1bmN0aW9uJTIwc2V0T3ZlcmxheXMobmV3T3ZlcmxheXMpJTIwJTdCJTVDbiU1Q3RvdmVybGF5cyUyMCUzRCUyMG5ld092ZXJsYXlzJTNCJTVDbiU3RCU1Q24lNUNuZXhwb3J0JTIwY29uc3QlMjBzb21ldGhpbmdFbHNlJTIwJTNEJTIwJ3NvbWV0aGluZyUyMGVsc2UnJTNCJTIyJTdEJTVEJTJDJTIyb3B0aW9ucyUyMiUzQSU3QiUyMmZvcm1hdCUyMiUzQSUyMmVzJTIyJTJDJTIybmFtZSUyMiUzQSUyMm15QnVuZGxlJTIyJTJDJTIyYW1kJTIyJTNBJTdCJTIyaWQlMjIlM0ElMjIlMjIlN0QlMkMlMjJnbG9iYWxzJTIyJTNBJTdCJTdEJTdEJTJDJTIyZXhhbXBsZSUyMiUzQW51bGwlN0Q= [2]: https://rollupjs.org/repl/?version=2.10.2&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmltcG9ydCUyMCU3QiUyMHNvbWV0aGluZ0Vsc2UlMkMlMjBvdmVybGF5cyUyMCU3RCUyMGZyb20lMjAnLiUyRm92ZXJsYXlzLmpzJyUzQiU1Q25pbXBvcnQlMjAnLiUyRm92ZXJyaWRlLmpzJyUzQiU1Q24lNUNuY29uc29sZS5sb2coc29tZXRoaW5nRWxzZSklM0IlNUNuJTVDbiUyRiUyRiUyMHRoaXMlMjB3aWxsJTIwdHJpZ2dlciUyMGxvYWRpbmclMjBvZiUyMGZ1bGwlMjBvdmVybGF5cy5qcyUyMCUyNiUyMG92ZXJyaWRlLmpzJTIwY29kZSU1Q24lMkYlMkYlMjBjb25zb2xlLmxvZyhvdmVybGF5cy5saXN0KSUzQiUyMiUyQyUyMmlzRW50cnklMjIlM0F0cnVlJTdEJTJDJTdCJTIybmFtZSUyMiUzQSUyMm92ZXJsYXlzLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmNsYXNzJTIwT3ZlcmxheU1hbmFnZXIlMjAlN0IlN0QlNUNuJTVDbmV4cG9ydCUyMGxldCUyMG92ZXJsYXlzJTIwJTNEJTIwbmV3JTIwT3ZlcmxheU1hbmFnZXIoKSUzQiU1Q24lNUNuZXhwb3J0JTIwZnVuY3Rpb24lMjBzZXRPdmVybGF5cyhuZXdPdmVybGF5cyklMjAlN0IlNUNuJTVDdG92ZXJsYXlzJTIwJTNEJTIwbmV3T3ZlcmxheXMlM0IlNUNuJTdEJTVDbiU1Q25leHBvcnQlMjBjb25zdCUyMHNvbWV0aGluZ0Vsc2UlMjAlM0QlMjAnc29tZXRoaW5nJTIwZWxzZSclM0IlMjIlN0QlMkMlN0IlMjJuYW1lJTIyJTNBJTIyb3ZlcnJpZGUuanMlMjIlMkMlMjJjb2RlJTIyJTNBJTIyaW1wb3J0JTIwJTdCJTIwc2V0T3ZlcmxheXMlMjAlN0QlMjBmcm9tJTIwJy4lMkZvdmVybGF5cy5qcyclM0IlNUNuJTVDbnNldE92ZXJsYXlzKG5ldyUyME9iamVjdCgpKSUzQiUyMiU3RCU1RCUyQyUyMm9wdGlvbnMlMjIlM0ElN0IlMjJmb3JtYXQlMjIlM0ElMjJlcyUyMiUyQyUyMm5hbWUlMjIlM0ElMjJteUJ1bmRsZSUyMiUyQyUyMmFtZCUyMiUzQSU3QiUyMmlkJTIyJTNBJTIyJTIyJTdEJTJDJTIyZ2xvYmFscyUyMiUzQSU3QiU3RCU3RCUyQyUyMmV4YW1wbGUlMjIlM0FudWxsJTdE [3]: https://rollupjs.org/repl/?version=2.10.2&shareable=JTdCJTIybW9kdWxlcyUyMiUzQSU1QiU3QiUyMm5hbWUlMjIlM0ElMjJtYWluLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmltcG9ydCUyMCU3QiUyMHNvbWV0aGluZ0Vsc2UlMkMlMjBzZXRPdmVybGF5cyUyQyUyMG92ZXJsYXlzJTIwJTdEJTIwZnJvbSUyMCcuJTJGb3ZlcmxheXMuanMnJTNCJTVDbmltcG9ydCUyMCU3QiUyME92ZXJsYXlDb250cm9sbGVyJTJDJTIwc29tZXRoaW5nRWxzZTIlMjAlN0QlMjBmcm9tJTIwJy4lMkZPdmVybGF5Q29udHJvbGxlci5qcyclM0IlNUNuJTVDbiUyRiUyRiUyMHRoZSUyMGZvbGxvd2luZyUyMGNvZGUlMjB3aWxsJTIwdHJlZSUyMHNoYWtlJTIwb3ZlcmxheXMlMjBhd2F5JTIwaGVuY2UlMjBvdmVybGF5cyUyMGlzJTIwc2lkZSUyMGVmZmVjdCUyMGZyZWUlMjAlNUNuJTVDbnNldE92ZXJsYXlzKG5ldyUyME9iamVjdCgpKSUzQiU1Q25jb25zb2xlLmxvZyhzb21ldGhpbmdFbHNlKSUzQiU1Q25jb25zb2xlLmxvZyhzb21ldGhpbmdFbHNlMiklM0IlNUNuJTVDbiUyRiUyRioqJTIwVGhlJTIwZm9sbG93aW5nJTIwd2lsbCUyMHRvZ2dsZSUyMGltcG9ydGluZyUyMG9mJTIwb3ZlcmxheXMlMjAqJTJGJTVDbiU1Q24lMkYlMkYlMjAxLiUyMGltcG9ydCUyMG92ZXJsYXlzJTIwZGlyZWN0bHklMjBhbmQlMjBhY2Nlc3MlMjBpdCU1Q24lMkYlMkYlMjBjb25zb2xlLmxvZyhvdmVybGF5cy5saXN0KSUzQiUyMCU1Q24lNUNuJTJGJTJGJTIwMi4lMjBjcmVhdGUlMjBhbiUyME92ZXJsYXlDb250cm9sbGVyJTIwd2hpY2glMjBpbnRlcm5hbGx5JTIwYWNjZXNzZXMlMjBvdmVybGF5cyU1Q24lMkYlMkYlMjBjb25zdCUyMGN0cmwlMjAlM0QlMjBuZXclMjBPdmVybGF5Q29udHJvbGxlcigpJTNCJTVDbiUyRiUyRiUyMGNvbnNvbGUubG9nKGN0cmwubWFuYWdlci5saXN0KSUzQiU1Q24lNUNuJTIyJTJDJTIyaXNFbnRyeSUyMiUzQXRydWUlN0QlMkMlN0IlMjJuYW1lJTIyJTNBJTIyb3ZlcmxheXMuanMlMjIlMkMlMjJjb2RlJTIyJTNBJTIyY2xhc3MlMjBPdmVybGF5TWFuYWdlciUyMCU3QiU1Q24lNUN0Y29uc3RydWN0b3IoKSUyMCU3QiU1Q24lNUN0JTVDdHRoaXMubGlzdCUyMCUzRCUyMCU1QiU1RCUzQiU1Q24lNUN0JTdEJTVDbiUyMCUyMGFkZChhKSUyMCU3QiU1Q24lMjAlMjAlMjAlMjB0aGlzLmxpc3QucHVzaChhKSUzQiU1Q24lNUN0JTdEJTVDbiU3RCU1Q24lNUNuZXhwb3J0JTIwbGV0JTIwb3ZlcmxheXMlMjAlM0QlMjBuZXclMjBPdmVybGF5TWFuYWdlcigpJTNCJTVDbiU1Q25leHBvcnQlMjBmdW5jdGlvbiUyMHNldE92ZXJsYXlzKG5ld092ZXJsYXlzKSUyMCU3QiU1Q24lNUN0b3ZlcmxheXMlMjAlM0QlMjBuZXdPdmVybGF5cyUzQiU1Q24lN0QlNUNuJTVDbmV4cG9ydCUyMGNvbnN0JTIwc29tZXRoaW5nRWxzZSUyMCUzRCUyMCdzb21ldGhpbmclMjBlbHNlJyUzQiU1Q24lNUNuJTJGJTJGJTIwdGhlJTIwZm9sbG93aW5nJTIwbGluZSUyMGlzJTIwYSUyMHNpZGUlMjBlZmZlY3QlMjBhcyUyMGl0JTIwYWx3YXlzJTIwd2lsbCUyMGJlJTIwaW5jbHVkZWQlNUNuY29uc29sZS5sb2coJ292ZXJsYXlzJTIwc2lkZSUyMGVmZmVjdCcpJTNCJTIyJTJDJTIyaXNFbnRyeSUyMiUzQWZhbHNlJTdEJTJDJTdCJTIybmFtZSUyMiUzQSUyMk92ZXJsYXlDb250cm9sbGVyLmpzJTIyJTJDJTIyY29kZSUyMiUzQSUyMmltcG9ydCUyMCU3QiUyMG92ZXJsYXlzJTIwJTdEJTIwZnJvbSUyMCcuJTJGb3ZlcmxheXMuanMnJTNCJTVDbiU1Q25leHBvcnQlMjBjbGFzcyUyME92ZXJsYXlDb250cm9sbGVyJTIwJTdCJTVDbiUyMCUyMCUyMGNvbnN0cnVjdG9yKGNvbmZpZyUyMCUzRCUyMCU3QiU3RCUyQyUyMG1hbmFnZXIlMjAlM0QlMjBvdmVybGF5cyklMjAlN0IlNUNuJTIwJTIwJTIwJTIwJTIwdGhpcy5tYW5hZ2VyJTIwJTNEJTIwbWFuYWdlciUzQiU1Q24lNUN0JTVDdCUyMHRoaXMubWFuYWdlci5hZGQodGhpcyklM0IlNUNuJTVDdCUyMCU3RCU1Q24lN0QlNUNuJTVDbmV4cG9ydCUyMGNvbnN0JTIwc29tZXRoaW5nRWxzZTIlMjAlM0QlMjAnc29tZXRoaW5nJTIwZWxzZSclM0IlMjIlN0QlNUQlMkMlMjJvcHRpb25zJTIyJTNBJTdCJTIyZm9ybWF0JTIyJTNBJTIyZXMlMjIlMkMlMjJuYW1lJTIyJTNBJTIybXlCdW5kbGUlMjIlMkMlMjJhbWQlMjIlM0ElN0IlMjJpZCUyMiUzQSUyMiUyMiU3RCUyQyUyMmdsb2JhbHMlMjIlM0ElN0IlN0QlN0QlMkMlMjJleGFtcGxlJTIyJTNBbnVsbCU3RA== diff --git a/es-dev-server.config.js b/es-dev-server.config.js new file mode 100644 index 000000000..c12d13415 --- /dev/null +++ b/es-dev-server.config.js @@ -0,0 +1,8 @@ +const { mdjsTransformer } = require('@mdjs/core'); + +module.exports = { + nodeResolve: true, + // open: 'packages/button/README.md', + watch: true, + responseTransformers: [mdjsTransformer], +}; diff --git a/package.json b/package.json index de00ac6fa..53f66ce57 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,8 @@ "@open-wc/building-rollup": "^1.2.1", "@commitlint/cli": "^7.0.0", "@commitlint/config-conventional": "^7.0.0", - "@open-wc/demoing-storybook": "^2.0.0", + "@mdjs/core": "^0.3.1", + "@open-wc/demoing-storybook": "^2.0.2", "@open-wc/eslint-config": "^1.0.0", "@open-wc/testing": "^2.5.0", "@open-wc/testing-helpers": "^1.0.0", @@ -39,6 +40,7 @@ "whatwg-fetch": "^3.0.0" }, "scripts": { + "dev-server": "es-dev-server", "start": "npm run storybook", "storybook": "start-storybook -p 9001", "storybook:build": "build-storybook", diff --git a/packages/ajax/README.md b/packages/ajax/README.md index 5023298d3..2bd7151e2 100644 --- a/packages/ajax/README.md +++ b/packages/ajax/README.md @@ -3,10 +3,26 @@ `ajax` is the global manager for handling all ajax requests. It is a promise based system for fetching data, based on [axios](https://github.com/axios/axios) +```js script +import { html } from 'lit-html'; +import { ajax } from './src/ajax.js'; +import { AjaxClass } from './src/AjaxClass.js'; + +export default { + title: 'Others/Ajax', +}; +``` + ## Live Demo/Documentation > See our [storybook](http://lion-web-components.netlify.com/?path=/docs/fetch-system-ajax) for a live demo and documentation +## Features + +- only JS functions, no (unnecessarily expensive) web components +- supports GET, POST, PUT, DELETE, REQUEST, PATCH and HEAD methods +- can be used with or without XSRF token + ## How to use ### Installation @@ -15,6 +31,10 @@ It is a promise based system for fetching data, based on [axios](https://github. npm i --save @lion/ajax ``` +```js +import { ajax, AjaxClass } from '@lion/ajax'; +``` + ### Example ```js @@ -22,3 +42,161 @@ import { ajax } from '@lion/ajax'; ajax.get('data.json').then(response => console.log(response)); ``` + +### Performing requests + +Performing a `GET` request: + +```js preview-story +export const performingGetRequests = () => html` + +`; +``` + +To post data to the server, pass the data as the second argument in the `POST` request: + +```js +const body = { + ant: { + type: 'insect', + limbs: 6, + }, +}; +ajax + .post('zooApi/animals/addAnimal', body) + .then(response => { + console.log(`POST successful: ${response.status} ${response.statusText}`); + }) + .catch(error => { + console.log(error); + }); +``` + +## Configuration + +### JSON prefix + +The called API might add a JSON prefix to the response in order to prevent hijacking. +The prefix renders the string syntactically invalid as a script so that it cannot be hijacked. +This prefix should be stripped before parsing the string as JSON. +Pass the prefix with the `jsonPrefix` option. + +```js +const myAjax = AjaxClass.getNewInstance({ jsonPrefix: ")]}'," }); +myAjax + .get('./packages/ajax/docs/assets/data.json') + .then(response => { + console.log(response.data); + }) + .catch(error => { + console.log(error); + }); +``` + +### Additional headers + +Add additional headers to the requests with the `headers` option. + +```js preview-story +export const additionalHeaders = () => html` + +`; +``` + +When executing the request above, check the Network tab in the Browser's dev tools and look for the Request Header on the GET call. + +### Cancelable Request + +It is possible to make an Ajax request cancelable, and then call `cancel()` to make the request provide a custom error once fired. + +```js preview-story +export const cancelableRequests = () => html` + +`; +``` + +### Cancel concurrent requests + +You can cancel concurrent requests with the `cancelPreviousOnNewRequest` option. + +```js preview-story +export const cancelConcurrentRequests = () => html` + +`; +``` + +## Considerations + +Due to a [bug in axios](https://github.com/axios/axios/issues/385) options may leak in to other instances. +So please avoid setting global options in axios. Interceptors have no issues. + +## Future plans + +- Eventually we want to remove axios and replace it with [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) +- This wrapper exist to prevent this switch from causing breaking changes for our users diff --git a/packages/ajax/stories/data.json b/packages/ajax/docs/assets/data.json similarity index 100% rename from packages/ajax/stories/data.json rename to packages/ajax/docs/assets/data.json diff --git a/packages/ajax/package.json b/packages/ajax/package.json index efd600042..518f9762e 100644 --- a/packages/ajax/package.json +++ b/packages/ajax/package.json @@ -14,6 +14,7 @@ "directory": "packages/ajax" }, "scripts": { + "start": "cd ../../ && yarn dev-server --open packages/ajax/README.md", "prepublishOnly": "../../scripts/npm-prepublish.js", "test": "cd ../../ && yarn test:browser --grep \"packages/ajax/test/**/*.test.js\"", "test:watch": "cd ../../ && yarn test:browser:watch --grep \"packages/ajax/test/**/*.test.js\"" diff --git a/packages/ajax/stories/index.stories.mdx b/packages/ajax/stories/index.stories.mdx deleted file mode 100644 index 4648fd231..000000000 --- a/packages/ajax/stories/index.stories.mdx +++ /dev/null @@ -1,279 +0,0 @@ -import { - Story, - Meta, - html, -} from '@open-wc/demoing-storybook'; - -import { ajax } from '../src/ajax.js'; -import { AjaxClass } from '../src/AjaxClass.js'; - - - -# Ajax - -`lion-ajax` is the global manager for handling all ajax requests. -It is a promise based system for fetching data, based on -axios - - - {html` - - `} - - -```js -ajax.get('./packages/ajax/stories/data.json').then(response => console.log(response.data)); -``` - -## Features - -- only JS functions, no (unnecessarily expensive) web components -- supports GET, POST, PUT, DELETE, REQUEST, PATCH and HEAD methods -- can be used with or without XSRF token - -## How to use - -### Installation - -```sh -npm i --save @lion/ajax -``` - -```js -import { ajax, AjaxClass } from '@lion/ajax'; -``` - -### Performing requests - -Performing a `GET` request: - - - {html` - - `} - - -```js -ajax - .get('./packages/ajax/stories/data.json') - .then(response => { - console.log(response.data); - }) - .catch(error => { - console.log(error); - }); -``` - -To post data to the server, pass the data as the second argument in the `POST` request: - -```js -const body = { - ant: { - type: "insect", - limbs: 6, - } -}; - -ajax - .post('zooApi/animals/addAnimal', body) - .then(response => { - console.log(`POST successful: ${response.status} ${response.statusText}`); - }) - .catch(error => { - console.log(error); - }); -``` - -## Configuration - -### JSON prefix - -The called API might add a JSON prefix to the response in order to prevent hijacking. -The prefix renders the string syntactically invalid as a script so that it cannot be hijacked. -This prefix should be stripped before parsing the string as JSON. -Pass the prefix with the `jsonPrefix` option. - -```js -const myAjax = AjaxClass.getNewInstance({ jsonPrefix: ")]}'," }); -myAjax - .get('./packages/ajax/stories/data.json') - .then(response => { - console.log(response.data); - }) - .catch(error => { - console.log(error); - }); -``` - -### Additional headers - -Add additional headers to the requests with the `headers` option. - - - {html` - - `} - - -```js -const myAjax = AjaxClass.getNewInstance({ headers: { 'X-CUSTOM-HEADER': 'SOME-HEADER-VALUE' } }); -myAjax - .get('./packages/ajax/stories/data.json') - .then(response => { - console.log(response); - }) - .catch(error => { - console.log(error); - }); -``` - -When executing the request above, check the Network tab in the Browser's dev tools and look for the Request Header on the GET call. - -### Cancelable Request - -It is possible to make an Ajax request cancelable, and then call `cancel()` to make the request provide a custom error once fired. - - - {html` - - `} - - -```js -const myAjax = AjaxClass.getNewInstance({ cancelable: true }); - -requestAnimationFrame(() => { - myAjax.cancel('too slow'); -}); - -myAjax - .get('./packages/ajax/stories/data.json') - .then(response => { - console.log(response.data); - }) - .catch(error => { - console.log(error); - }); -``` - -### Cancel concurrent requests - -You can cancel concurrent requests with the `cancelPreviousOnNewRequest` option. - - - {html` - - `} - - -```js -const myAjax = AjaxClass.getNewInstance({ cancelPreviousOnNewRequest: true }); - -myAjax - .get('./packages/ajax/stories/data.json') - .then(response => { - console.log(response.data); - }) - .catch(error => { - console.log(error.message); - }); - -myAjax - .get('./packages/ajax/stories/data.json') - .then(response => { - console.log(response.data); - }) - .catch(error => { - console.log(error.message); - }); -``` - -## Considerations - -Due to a bug in axios options may leak in to other instances. -So please avoid setting global options in axios. Interceptors have no issues. - -## Future plans - -- Eventually we want to remove axios and replace it with -Fetch -- This wrapper exist to prevent this switch from causing breaking changes for our users diff --git a/packages/babel-plugin-extend-docs/README.md b/packages/babel-plugin-extend-docs/README.md index 36d5780f0..d44315876 100644 --- a/packages/babel-plugin-extend-docs/README.md +++ b/packages/babel-plugin-extend-docs/README.md @@ -223,3 +223,9 @@ module.exports = { ], }; ``` + +```js script +export default { + title: 'Tools/BabelPluginExtendDocs', +}; +``` diff --git a/packages/button/README.md b/packages/button/README.md index 9e81bc177..5c43bb195 100644 --- a/packages/button/README.md +++ b/packages/button/README.md @@ -1,11 +1,34 @@ +[//]: # 'AUTO INSERT HEADER PREPUBLISH' + # Button -`lion-button` provides a button component that is easily stylable and is accessible. +`lion-button` provides a button component that is easily styleable and is accessible. + +```js script +import { html } from 'lit-html'; + +import './lion-button.js'; +import iconSvg from './docs/assets/icon.svg.js'; + +export default { + title: 'Buttons/Button', +}; +``` + +```js story +export const main = () => html` Default `; +``` ## Live Demo/Documentation > See our [storybook](http://lion-web-components.netlify.com/?path=/docs/buttons-button) for a live demo and API documentation +## Features + +- Clickable area that is bigger than visual size +- Works with native form / inputs +- Has integration for implicit form submission similar to how native `
`, `` and `
+ + +

+ `; +}; +``` + +## 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` + + + `; +}; +``` + +### 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` + + + `; +}; +``` + +### 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` + + day.getDay() === 6 || day.getDay() === 0} + > +`; +``` + +### 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` + + day.getDay() === 6 || day.getDay() === 0} + .minDate="${new Date()}" + .maxDate="${maxDate}" + > + `; +}; +``` diff --git a/packages/calendar/package.json b/packages/calendar/package.json index 0d3191e04..b4a1910c6 100644 --- a/packages/calendar/package.json +++ b/packages/calendar/package.json @@ -15,6 +15,7 @@ }, "scripts": { "prepublishOnly": "../../scripts/npm-prepublish.js", + "start": "cd ../../ && yarn dev-server --open packages/calendar/README.md", "test": "cd ../../ && yarn test:browser --grep \"packages/calendar/test/**/*.test.js\"", "test:watch": "cd ../../ && yarn test:browser:watch --grep \"packages/calendar/test/**/*.test.js\"" }, diff --git a/packages/calendar/stories/index.stories.mdx b/packages/calendar/stories/index.stories.mdx deleted file mode 100644 index ca9483051..000000000 --- a/packages/calendar/stories/index.stories.mdx +++ /dev/null @@ -1,257 +0,0 @@ -import { - Story, - Meta, - html, -} from '@open-wc/demoing-storybook'; -import { css } from '@lion/core'; - -import '../lion-calendar.js'; - - - -# Calendar - -`lion-calendar` is a reusable and accessible calendar view. - -export const calendarDemoStyle = css` - .demo-calendar { - border: 1px solid #adadad; - box-shadow: 0 0 16px #ccc; - max-width: 500px; - } -`; - - - {html` - - - `} - - -```html - -``` - -## 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 - -## How to use - -### Installation - -```sh -npm i --save @lion/calendar -``` - -```js -import '@lion/calendar/lion-calendar.js'; -``` - -## Move to the 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. - - - {html` - - - `} - - -```html - -``` - -## 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`. - - - {() => { - const today = new Date(); - const centralDate = new Date(today.getFullYear(), today.getMonth() + 1, today.getDate()); - return html` - - - `; - }} - - -```html - -``` - -## 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. - - - {() => { - const today = new Date(); - const selectedDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 1); - const centralDate = new Date(today.getFullYear(), today.getMonth() + 1, today.getDate()); - return html` - - -

- Focus - - - -

- `; - }} -
- -## Limiting selectable values - -### Providing a lower limit - -To give a lower limit you can bind a date to the `minDate` property. - - - {() => { - const minDate = new Date(); - return html` - - - `; - }} - - -```html - -``` - -### 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. - - - {() => { - const today = new Date(); - const maxDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 2); - return html` - - - `; - }} - - -```js -const today = new Date(); -const maxDate = new Date(today.getFullYear(), today.getMonth(), today.getDate() + 2); -``` - -```html - -``` - -### 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. - - - {html` - - day.getDay() === 6 || day.getDay() === 0} - > - `} - - -```html - -``` - -### Combined disable dates - -To limit the scope of possible dates further, combine the methods mentioned above. - - - {() => { - const today = new Date(); - const maxDate = new Date(today.getFullYear(), today.getMonth() + 2, today.getDate()); - return html` - - day.getDay() === 6 || day.getDay() === 0} - .minDate="${new Date()}" - .maxDate="${maxDate}" - > - `; - }} - - -```js -const today = new Date(); -const maxDate = new Date(today.getFullYear(), today.getMonth() + 2, today.getDate()); -``` - -```html - day.getDay() === 6 || day.getDay() === 0} - .minDate="${new Date()}" - .maxDate="${maxDate}" -> -``` diff --git a/packages/checkbox-group/README.md b/packages/checkbox-group/README.md index b424858a9..631b11f38 100644 --- a/packages/checkbox-group/README.md +++ b/packages/checkbox-group/README.md @@ -1,13 +1,45 @@ +[//]: # 'AUTO INSERT HEADER PREPUBLISH' + # Checkbox Group -`lion-checkbox-group` component enhances the functionality of the native `` element. Its purpose is to provide a way for users to check **multiple** options amongst a set of choices, or to function as a single toggle. +`lion-checkbox-group` component enhances the functionality of the native `` element. +Its purpose is to provide a way for users to check **multiple** options amongst a set of choices, or to function as a single toggle. -You should use `lion-checkbox` inside this element. +> You should use [lion-checkbox](https://github.com/ing-bank/lion/tree/master/packages/checkbox) elements as the children of the ``. + +```js script +import { html } from 'lit-html'; +import { Required, Validator, loadDefaultFeedbackMessages } from '@lion/validate'; +import './lion-checkbox-group.js'; +import './lion-checkbox.js'; + +export default { + title: 'Forms/Checkbox Group', +}; + +loadDefaultFeedbackMessages(); +``` + +```js story +export const main = () => html` + + + + + +`; +``` + +> Make sure that the checkbox-group also has a name attribute, this is necessary for the [lion-form](?path=/docs/forms-form-overview--page)'s serialization result. ## Live Demo/Documentation > See our [storybook](http://lion-web-components.netlify.com/?path=/docs/forms-checkbox-group--default-story) for a live demo and API documentation +## Features + +Since it extends from [lion-fieldset](?path=/docs/forms-fieldset-overview--page), it has all the features a fieldset has. + ## How to use ### Installation @@ -21,6 +53,26 @@ import '@lion/checkbox-group/lion-checkbox-group.js'; import '@lion/checkbox-group/lion-checkbox.js'; ``` +### Model value + +The `modelValue` of a `lion-checkbox-group` is an array containing the `choiceValues` of the `lion-checkbox` elements that have been checked. + +Given the scientists example above, say that we were to select the first and last options (Archimedes & Marie Curie). + +Then the `modelValue` of the `lion-checkbox-group` will look as follows: + +```js +const groupElement = [parent].querySelector('lion-checkbox-group'); +groupElement.modelValue; + => ["Archimedes", "Marie Curie"]; +``` + +### The `name` attribute + +The `name` attribute of a `lion-checkbox-group` automatically gets assigned to its `lion-checkbox` children. You can also specify names for the `lion-checkbox` elements, but if this name is different from the name assigned to `lion-checkbox-group`, then an exception will be thrown. + +Our recommendation would be to set the `name` attribute only on the `lion-checkbox-group` and not on the `lion-checkbox` elements. + ### Example ```html @@ -33,3 +85,102 @@ import '@lion/checkbox-group/lion-checkbox.js'; ``` + +### Pre-select + +You can pre-select options by targeting the `modelValue` object of the option and setting the `checked` property to `true`. + +```js preview-story +export const preselect = () => html` + + + + + +`; +``` + +### Disabled + +You can disable the entire group by setting the `disabled` attribute on the ``. + +```js preview-story +export const disabled = () => html` + + + + + +`; +``` + +### Validation + +You can apply validation to the ``, similar to how you would do so in any fieldset. +The interaction states of the `` are evaluated in order to hide or show feedback messages. + +```js preview-story +export const validation = () => { + const validate = () => { + const checkboxGroup = document.querySelector('#scientists'); + checkboxGroup.submitted = !checkboxGroup.submitted; + }; + return html` + + + + + + + `; +}; +``` + +### Validation advanced + +Below is a more advanced validator on the group that evaluates the children checkboxes' checked states. + +```js preview-story +export const validationAdvanced = () => { + class HasMinTwoChecked extends Validator { + execute(value) { + return value.length < 2; + } + static get validatorName() { + return 'HasMinTwoChecked'; + } + static async getMessage() { + return 'You need to select at least 2 values.'; + } + } + const validate = () => { + const checkboxGroup = document.querySelector('#scientists2'); + checkboxGroup.submitted = !checkboxGroup.submitted; + }; + return html` + + + + + + + `; +}; +``` diff --git a/packages/checkbox-group/package.json b/packages/checkbox-group/package.json index 19454e352..02616e5da 100644 --- a/packages/checkbox-group/package.json +++ b/packages/checkbox-group/package.json @@ -15,6 +15,7 @@ }, "scripts": { "prepublishOnly": "../../scripts/npm-prepublish.js", + "start": "cd ../../ && yarn dev-server --open packages/checkbox-group/README.md", "test": "cd ../../ && yarn test:browser --grep \"packages/checkbox-group/test/**/*.test.js\"", "test:watch": "cd ../../ && yarn test:browser:watch --grep \"packages/checkbox-group/test/**/*.test.js\"" }, diff --git a/packages/checkbox-group/stories/index.stories.mdx b/packages/checkbox-group/stories/index.stories.mdx deleted file mode 100644 index 1736b9e37..000000000 --- a/packages/checkbox-group/stories/index.stories.mdx +++ /dev/null @@ -1,328 +0,0 @@ -import { Story, Meta, html } from '@open-wc/demoing-storybook'; -import { Required, Validator, loadDefaultFeedbackMessages } from '@lion/validate'; - -import '../lion-checkbox-group.js'; -import '../lion-checkbox.js'; - - - -# Checkbox Group - -`lion-checkbox-group` component enhances the functionality of the native `` element. -Its purpose is to provide a way for users to check **multiple** options amongst a set of choices, or to function as a single toggle. - -> You should use `` elements as the children of the ``. - - - {html` - - - - - - `} - - -```html - - - - - -``` - -> Make sure that the checkbox-group also has a name attribute, this is necessary for the [lion-form](?path=/docs/forms-form-overview--page)'s serialization result. - -## Features - -Since it extends from [lion-fieldset](?path=/docs/forms-fieldset-overview--page), it has all the features a fieldset has. - -## How to use - -### Installation - -```sh -npm i --save @lion/checkbox-group -``` - -```js -import '@lion/checkbox-group/lion-checkbox-group.js'; -import '@lion/checkbox-group/lion-checkbox.js'; -``` - -### Model value - -The `modelValue` of a `lion-checkbox-group` is an array containing the `choiceValues` of the `lion-checkbox` elements that have been checked. - -Given the scientists example above, say that we were to select the first and last options (Archimedes & Marie Curie). - -Then the `modelValue` of the `lion-checkbox-group` will look as follows: - -```js -const groupElement = [parent].querySelector('lion-checkbox-group'); -groupElement.modelValue; - => ["Archimedes", "Marie Curie"]; -``` - -### The `name` attribute - -The `name` attribute of a `lion-checkbox-group` automatically gets assigned to its `lion-checkbox` children. You can also specify names for the `lion-checkbox` elements, but if this name is different from the name assigned to `lion-checkbox-group`, then an exception will be thrown. - -Our recommendation would be to set the `name` attribute only on the `lion-checkbox-group` and not on the `lion-checkbox` elements. - -## Examples - -### Pre-select - -You can pre-select options by targeting the `modelValue` object of the option and setting the `checked` property to `true`. - - - {html` - - - - - - `} - - -```html - - - - - -``` - -### Disabled - -You can disable the entire group by setting the `disabled` attribute on the ``. - - - {html` - - - - - - `} - - -```html - - - - - -``` - -### Validation - -You can apply validation to the ``, similar to how you would do so in any fieldset. -The interaction states of the `` are evaluated in order to hide or show feedback messages. - - - {() => { - loadDefaultFeedbackMessages(); - const validate = () => { - const checkboxGroup = document.querySelector('#scientists'); - checkboxGroup.submitted = !checkboxGroup.submitted; - }; - return html` - - - - - - - `; - }} - - -```js -import { Required, loadDefaultFeedbackMessages } from '@lion/validate'; -loadDefaultFeedbackMessages(); -const validate = () => { - const checkboxGroup = document.querySelector('#scientists'); - checkboxGroup.submitted = !checkboxGroup.submitted; -}; -``` - -```html - - - - - - -``` - -### Validation advanced - -Below is a more advanced validator on the group that evaluates the children checkboxes' checked states. - - - {() => { - loadDefaultFeedbackMessages(); - class HasMinTwoChecked extends Validator { - execute(value) { - return value.length < 2; - } - static get validatorName() { - return 'HasMinTwoChecked'; - } - static async getMessage() { - return 'You need to select at least 2 values.'; - } - } - const validate = () => { - const checkboxGroup = document.querySelector('#scientists2'); - checkboxGroup.submitted = !checkboxGroup.submitted; - }; - return html` - - - - - - - `; - }} - - -```js -import { Required, Validator, loadDefaultFeedbackMessages } from '@lion/validate'; - -loadDefaultFeedbackMessages(); - -class HasMinTwoChecked extends Validator { - - execute(value) { - return value.length < 2; - } - - static get validatorName() { - return 'HasMinTwoChecked'; - } - - static async getMessage() { - return 'You need to select at least 2 values.'; - } -} - -const validate = () => { - const checkboxGroup = document.querySelector('#scientists2'); - checkboxGroup.submitted = !checkboxGroup.submitted; -}; -``` - -```html - - - - - - -``` diff --git a/packages/choice-input/README.md b/packages/choice-input/README.md index dcd4e7012..00d8ba714 100644 --- a/packages/choice-input/README.md +++ b/packages/choice-input/README.md @@ -1,11 +1,19 @@ +[//]: # 'AUTO INSERT HEADER PREPUBLISH' + # ChoiceInputMixin +```js script +export default { + title: 'Forms/System/Choice', +}; +``` + `lion-choice-input` mixin is a fundamental building block of form controls which return a checked-state. It is used in: - [lion-checkbox](../checkbox/) -- [lion-option](../option/)) -- [lion-radio](../radio/)) -- [lion-switch](../switch/)) +- [lion-option](../option/) +- [lion-radio](../radio/) +- [lion-switch](../switch/) ## Features diff --git a/packages/core/README.md b/packages/core/README.md index d379cda9f..7e03a51b7 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -1,11 +1,35 @@ +[//]: # 'AUTO INSERT HEADER PREPUBLISH' + # Core -`lion-input-amount` component is based on the generic text input field. Its purpose is to provide a way for users to fill in an amount. +The `@lion/core` package is mostly for in depth usage. +It handles the version of `lit-element` and `lit-html`. + +In order to be sure a compatible version is used import it via this package. + +```js script +export default { + title: 'Others/System/Core', +}; +``` + +```js +import { LitElement, html, render } from '@lion/core'; +``` ## Live Demo/Documentation > See our [storybook](http://lion-web-components.netlify.com/?path=/docs/core) for a live demo and API documentation +## Features + +- [function to deduplicate mixins (dedupeMixin)](#deduping-of-mixins) +- Mixin to handle disabled (DisabledMixin) +- Mixin to handle disabled AND tabIndex (DisabledWithTabIndexMixin) +- Mixin to manage auto generated needed slot elements in light dom (SlotMixin) + +> These features are not well documented - care to help out? + ## How to use ### Installation @@ -25,3 +49,46 @@ const BaseMixin = dedupeMixin((superClass) => { return class extends superClass { ... }; }); ``` + +## Deduping of mixins + +### Why is deduping of mixins necessary? + +Imagine you are developing web components and creating ES classes for Custom Elements. You have two generic mixins (let's say `M1` and `M2`) which require independently the same even more generic mixin (`BaseMixin`). `M1` and `M2` can be used independently, that means they have to inherit from `BaseMixin` also independently. But they can be also used in combination. Sometimes `M1` and `M2` are used in the same component and can mess up the inheritance chain if `BaseMixin` is applied twice. +In other words, this may happen to the protoype chain `... -> M2 -> BaseMixin -> M1 -> BaseMixin -> ...`. + +An example of this may be a `LocalizeMixin` used across different components and mixins. Some mixins may need it and many components need it too and can not rely on other mixins to have it by default, so must inherit from it independently. + +The more generic the mixin is, the higher the chance of being appliend more than once. As a mixin author you can't control how it is used, and can't always predict it. So as a safety measure it is always recommended to create deduping mixins. + +### Usage of dedupeMixin() + +This is an example of how to make a conventional ES mixin deduping. + +```js +const BaseMixin = dedupeMixin((superClass) => { + return class extends superClass { ... }; +}); + +// inherits from BaseMixin +const M1 = dedupeMixin((superClass) => { + return class extends BaseMixin(superClass) { ... }; +}); + +// inherits from BaseMixin +const M2 = dedupeMixin((superClass) => { + return class extends BaseMixin(superClass) { ... }; +}); + +// component inherits from M1 +// MyCustomElement -> M1 -> BaseMixin -> BaseCustomElement; +class MyCustomElement extends M1(BaseCustomElement) { ... } + +// component inherits from M2 +// MyCustomElement -> M2 -> BaseMixin -> BaseCustomElement; +class MyCustomElement extends M2(BaseCustomElement) { ... } + +// component inherits from both M1 and M2 +// MyCustomElement -> M2 -> M1 -> BaseMixin -> BaseCustomElement; +class MyCustomElement extends M2(M1(BaseCustomElement)) { ... } +``` diff --git a/packages/core/stories/index.stories.mdx b/packages/core/stories/index.stories.mdx deleted file mode 100644 index bf1981cdf..000000000 --- a/packages/core/stories/index.stories.mdx +++ /dev/null @@ -1,67 +0,0 @@ -import { Story, Meta, html } from '@open-wc/demoing-storybook'; - - - -# Core - -The `@lion/core` package is mostly for in depth usage. -It handles the version of `lit-element` and `lit-html`. - -In order to be sure a compatible version is used import it via this package. - -```js -import { LitElement, html, render } from '@lion/core'; -``` - -It offers low level functionality for - -- [function to deduplicate mixins (dedupeMixin)](#deduping-of-mixins) -- Mixin to handle disabled (DisabledMixin) -- Mixin to handle disabled AND tabIndex (DisabledWithTabIndexMixin) -- Mixin to manage auto generated needed slot elements in light dom (SlotMixin) - - -> These features are not well documented - care to help out? - -## Deduping of mixins - -### Why is deduping of mixins necessary? - -Imagine you are developing web components and creating ES classes for Custom Elements. You have two generic mixins (let's say `M1` and `M2`) which require independently the same even more generic mixin (`BaseMixin`). `M1` and `M2` can be used independently, that means they have to inherit from `BaseMixin` also independently. But they can be also used in combination. Sometimes `M1` and `M2` are used in the same component and can mess up the inheritance chain if `BaseMixin` is applied twice. -In other words, this may happen to the protoype chain `... -> M2 -> BaseMixin -> M1 -> BaseMixin -> ...`. - -An example of this may be a `LocalizeMixin` used across different components and mixins. Some mixins may need it and many components need it too and can not rely on other mixins to have it by default, so must inherit from it independently. - -The more generic the mixin is, the higher the chance of being appliend more than once. As a mixin author you can't control how it is used, and can't always predict it. So as a safety measure it is always recommended to create deduping mixins. - -### Usage of dedupeMixin() - -This is an example of how to make a conventional ES mixin deduping. - -```js -const BaseMixin = dedupeMixin((superClass) => { - return class extends superClass { ... }; -}); - -// inherits from BaseMixin -const M1 = dedupeMixin((superClass) => { - return class extends BaseMixin(superClass) { ... }; -}); - -// inherits from BaseMixin -const M2 = dedupeMixin((superClass) => { - return class extends BaseMixin(superClass) { ... }; -}); - -// component inherits from M1 -// MyCustomElement -> M1 -> BaseMixin -> BaseCustomElement; -class MyCustomElement extends M1(BaseCustomElement) { ... } - -// component inherits from M2 -// MyCustomElement -> M2 -> BaseMixin -> BaseCustomElement; -class MyCustomElement extends M2(BaseCustomElement) { ... } - -// component inherits from both M1 and M2 -// MyCustomElement -> M2 -> M1 -> BaseMixin -> BaseCustomElement; -class MyCustomElement extends M2(M1(BaseCustomElement)) { ... } -``` diff --git a/packages/dialog/README.md b/packages/dialog/README.md index a2f968e23..82ef8b28a 100644 --- a/packages/dialog/README.md +++ b/packages/dialog/README.md @@ -1,12 +1,54 @@ +<<<<<<< HEAD +======= +[//]: # 'AUTO INSERT HEADER PREPUBLISH' + +>>>>>>> feat: use markdown javascript (mdjs) for documentation # Dialog `lion-dialog` is a component wrapping a modal dialog controller. Its purpose is to make it easy to use our Overlay System declaratively. +```js script +import { html } from 'lit-html'; +import demoStyle from './docs/demo-dialog-style.js'; +import './docs/styled-dialog-content.js'; +import './lion-dialog.js'; + +export default { + title: 'Overlays/Dialog', +}; +``` + +```js story +export const main = () => html` + + + +
+ Hello! You can close this dialog here: + +
+
+`; +``` + ## Live Demo/Documentation > See our [storybook](http://lion-web-components.netlify.com/?path=/docs/overlays-specific-wc-dialog) for a live demo and documentation +## Features + +- Show content when clicking the invoker +- Respond to close event in the slot="content" element, to close the content +- Have a `.config` object to set or update the OverlayController's configuration + ## How to use ### Installation @@ -16,9 +58,27 @@ npm i --save @lion/dialog ``` ```js +import { LionDialog } from '@lion/dialog'; +// or import '@lion/dialog/lion-dialog.js'; ``` +## Usage notes + +- Your `slot="content"` node will be moved to the global overlay container during initialization. + After, your content node is no longer a child of `lion-dialog`. + If you still need to access it from the `lion-dialog` you can do so by using the `._overlayContentNode` property. +- To close the overlay from within the content node, you need to dispatch a `close-overlay` event that bubbles. + It has to be able to reach the content node. +- If you need to traverse shadow boundaries, you will have to add `composed: true` as well, although this is discouraged as a practice. + +## Changing the configuration + +You can use the `config` property on the dialog to change the configuration. +The documentation of the full config object can be found in the `lion/overlay` package or here in [Overlay System - Configuration](/?path=/docs/overlays-system-configuration--placement-mode-local). + +The `config` property uses a setter to merge the passed configuration with the current, so you only **overwrite what you pass** when updating `config`. + ### Example ```html @@ -30,3 +90,118 @@ import '@lion/dialog/lion-dialog.js'; ``` + +### Styling content + +It's not possible to style content from the dialog component. This is because the content slot is moved to the global root node. This is why a custom component should be created and slotted in as the content. This ensures style encapsulation on the dialog content. + +```js preview-story +export const stylingContent = () => html` + + + + + +`; +``` + +### Close overlay from component slotted as content + +The overlay cannot be closed by dispatching the `close-overlay` from a button in a styled component that is slotted in as content, because it will not cross the shadow boundary of the component. A method should be created that will dispatch the `close-overlay` event from the component. + +```js preview-story +export const closeOverlayFromComponent = () => html` + + + + + +`; +``` + +### Placement overrides + +```js preview-story +export const placementOverrides = () => { + const dialog = placement => html` + + +
+ Hello! You can close this notification here: + +
+
+ `; + return html` + +
+ ${dialog('center')} ${dialog('top-left')} ${dialog('top-right')} ${dialog('bottom-left')} ${dialog( + 'bottom-right', + )} +
+ `; +}; +``` + +Configuration passed to `config` property: + +```js +{ + viewportConfig: { + placement: ... // <-- choose a position + } +} +``` + +### Other overrides + +No backdrop, hides on escape, prevents scrolling while opened, and focuses the body when hiding. + +```js preview-story +export const otherOverrides = () => html` + + + +
+ Hello! You can close this dialog here: + +
+
+`; +``` + +Configuration passed to `config` property: + +```js +{ + hasBackdrop: false, + hidesOnEscape: true, + preventsScroll: true, + elementToFocusAfterHide: document.body +} +``` diff --git a/packages/dialog/stories/demo-dialog-style.js b/packages/dialog/docs/demo-dialog-style.js similarity index 100% rename from packages/dialog/stories/demo-dialog-style.js rename to packages/dialog/docs/demo-dialog-style.js diff --git a/packages/dialog/stories/styled-dialog-content.js b/packages/dialog/docs/styled-dialog-content.js similarity index 100% rename from packages/dialog/stories/styled-dialog-content.js rename to packages/dialog/docs/styled-dialog-content.js diff --git a/packages/dialog/package.json b/packages/dialog/package.json index f4684a189..5e95aa774 100644 --- a/packages/dialog/package.json +++ b/packages/dialog/package.json @@ -15,6 +15,7 @@ }, "scripts": { "prepublishOnly": "../../scripts/npm-prepublish.js", + "start": "cd ../../ && yarn dev-server --open packages/dialog/README.md", "test": "cd ../../ && yarn test:browser --grep \"packages/dialog/test/**/*.test.js\"", "test:watch": "cd ../../ && yarn test:browser:watch --grep \"packages/dialog/test/**/*.test.js\"" }, diff --git a/packages/dialog/stories/index.stories.mdx b/packages/dialog/stories/index.stories.mdx deleted file mode 100644 index 5ea69d905..000000000 --- a/packages/dialog/stories/index.stories.mdx +++ /dev/null @@ -1,279 +0,0 @@ -import { Story, Meta, html } from '@open-wc/demoing-storybook'; -import demoStyle from './demo-dialog-style.js'; -import './styled-dialog-content.js'; -import '../lion-dialog.js'; - - - -# Dialog - -`lion-dialog` is a component wrapping a modal dialog controller. -Its purpose is to make it easy to use our Overlay System declaratively. - - - {html` - - - -
- Hello! You can close this dialog here: - -
-
- `} -
- -```html - - -
- Hello! You can close this dialog here: - -
-
-``` - -## Features - -- Show content when clicking the invoker -- Respond to close event in the slot="content" element, to close the content -- Have a `.config` object to set or update the OverlayController's configuration - -## How to use - -### Installation - -```sh -npm i --save @lion/dialog -``` - -```js -import '@lion/dialog/lion-dialog.js'; -``` - -## Usage notes - -- Your `slot="content"` node will be moved to the global overlay container during initialization. - After, your content node is no longer a child of `lion-dialog`. - If you still need to access it from the `lion-dialog` you can do so by using the `._overlayContentNode` property. -- To close the overlay from within the content node, you need to dispatch a `close-overlay` event that bubbles. - It has to be able to reach the content node. -- If you need to traverse shadow boundaries, you will have to add `composed: true` as well, although this is discouraged as a practice. - -## Changing the configuration - -You can use the `config` property on the dialog to change the configuration. -The documentation of the full config object can be found in the `lion/overlay` package or here in [Overlay System - Configuration](/?path=/docs/overlays-system-configuration--placement-mode-local). - -The `config` property uses a setter to merge the passed configuration with the current, so you only **overwrite what you pass** when updating `config`. - -### Styling content - -It's not possible to style content from the dialog component. This is because the content slot is moved to the global root node. This is why a custom component should be created and slotted in as the content. This ensures style encapsulation on the dialog content. - - - {() => { - return html` - - - - - - `; - }} - - -```html - - - - -``` - -```js -class StyledDialogContent extends LitElement { - static get styles() { - return [ - css` - :host { - background-color: #fff; - } - .nice { - font-weight: bold; - color: green; - } - .close-button { - color: black; - font-size: 28px; - line-height: 28px; - } - ` - ]; - } - - _closeOverlay() { - this.dispatchEvent(new Event('close-overlay', { bubbles: true })); - } - - render() { - return html` -

Hello person who opened the dialog!

-

Look how nice this dialog looks!

/div> - - `; - } -} - -customElements.define('styled-dialog-content',StyledDialogContent); -``` - -### Close overlay from component slotted as content - -The overlay cannot be closed by dispatching the `close-overlay` from a button in a styled component that is slotted in as content, because it will not cross the shadow boundary of the component. A method should be created that will dispatch the `close-overlay` event from the component. - - - {() => { - return html` - - - - - - `; - }} - - -```js -_closeOverlay() { - this.dispatchEvent(new Event('close-overlay', { bubbles: true })); -} - -render() { - return html` -

Hello person who opened the dialog!

-

Look how nice this dialog looks!

/div> - - `; -} -``` -### Placement overrides - - - {() => { - const dialog = placement => html` - - -
- Hello! You can close this notification here: - -
-
- `; - return html` - -
- ${dialog('center')} ${dialog('top-left')} ${dialog('top-right')} ${dialog('bottom-left')} - ${dialog('bottom-right')} -
- `; - }} -
- -```html - - -
- Hello! You can close this notification here: - -
-
-``` - -Configuration passed to `config` property: -```js -{ - viewportConfig: { - placement: ... // <-- choose a position - } -} -``` - -### Other overrides - -No backdrop, hides on escape, prevents scrolling while opened, and focuses the body when hiding. - - - {html` - - - -
- Hello! You can close this dialog here: - -
-
- `} -
- -```html - - -
- Hello! You can close this notification here: - -
-
-``` - -Configuration passed to `config` property: -```js -{ - hasBackdrop: false, - hidesOnEscape: true, - preventsScroll: true, - elementToFocusAfterHide: document.body -} -``` diff --git a/packages/field/README.md b/packages/field/README.md index 01c8762ef..cc94cb649 100644 --- a/packages/field/README.md +++ b/packages/field/README.md @@ -1,5 +1,13 @@ +[//]: # 'AUTO INSERT HEADER PREPUBLISH' + # Form Fundaments +```js script +export default { + title: 'Forms/Field/Overview', +}; +``` + `Form control`s are the most fundamental building block of the Forms. They are the basis of both `field`s and `fieldset`s, and the `form` itself. @@ -21,17 +29,15 @@ On top of this, they feature: ### Platform fields (wrappers) -- [`LionInput`](../input/), a wrapper for `` -- [`LionTextarea`](../textarea/), a wrapper for `