{"id":14990233,"url":"https://github.com/lwc-essentials/storybook","last_synced_at":"2025-04-12T02:06:20.303Z","repository":{"id":77164898,"uuid":"279144135","full_name":"LWC-Essentials/storybook","owner":"LWC-Essentials","description":"Shows how to use Storybook with LWC Web Components","archived":false,"fork":false,"pushed_at":"2020-09-07T22:23:33.000Z","size":17325,"stargazers_count":19,"open_issues_count":2,"forks_count":8,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-04-12T02:06:15.535Z","etag":null,"topics":["lwc","storybook","webcomponent"],"latest_commit_sha":null,"homepage":"","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LWC-Essentials.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-12T20:38:33.000Z","updated_at":"2025-03-24T11:45:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"2dc2cddf-4e90-435b-9f08-1982366ae3a7","html_url":"https://github.com/LWC-Essentials/storybook","commit_stats":{"total_commits":27,"total_committers":3,"mean_commits":9.0,"dds":"0.14814814814814814","last_synced_commit":"b6b2fb4f2468b3e6bf270c2f6800c662701cd051"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LWC-Essentials%2Fstorybook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LWC-Essentials%2Fstorybook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LWC-Essentials%2Fstorybook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LWC-Essentials%2Fstorybook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LWC-Essentials","download_url":"https://codeload.github.com/LWC-Essentials/storybook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248505862,"owners_count":21115354,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["lwc","storybook","webcomponent"],"created_at":"2024-09-24T14:19:45.109Z","updated_at":"2025-04-12T02:06:20.270Z","avatar_url":"https://github.com/LWC-Essentials.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LWC Storybook\n\n## What is Storybook?\nAccording to the documentation, [Documentation](https://storybook.js.org/), Storybook is a user interface development environment and playground for UI components. The tool enables developers to create components independently and showcase components interactively in an isolated development environment.  \n\nThe two deployed Storybook sites are available at the following URLs:\n[https://lwc-essentials.github.io/storybook/](https://lwc-essentials.github.io/storybook/)\n\n\n![./docs/screenshot.png](./assets/Storybook-screenshot.png)\n\nGithub repo: [https://github.com/LWC-Essentials/storybook](https://github.com/LWC-Essentials/storybook)\n\n\n## About\nThis project offers a sample LWC application, with a library, that shows how to integrate with Storybook. It covers different aspects of Storybook:  \n\n- Component showcase  \n  Shows the components in action in a dedicated, simple UI (stories).  \n- Component documentation  \n  Provide the full components documentation, which can be generated out of the components' source code and/or manually written.  \n- Composition  \n  The application Storybook aggregates the components provided by its dependencies (the library).  \n- Static deployment  \n  The resulting Storybook instance is deployed to a static server, typically on Github pages, so it becomes easily available.  \n- Others  \n  There are much more capabilities, like testing, accessibility reporting, ...\n  \n\n## Demo project layout\nThis project is a mono repo, powered by lerna, which currently contains two packages:  \n\n- A reusable library of components, `lwc-library`  \n- An application, `lwc-app`, consuming the library  \n\nThe demo is based on Storybook version 6.0+ version which implements the composition mechanism, and thus allows the main app to render the stories coming from the library.\n\n\n## Getting started\n\nThe sample application is itself very basic, and not that exciting, but you can execute it with the following commands:  \n\n```sh\nyarn\nyarn build \nyarn start\n```\n\nMore interesting are the Storybooks.  \nYou can execute the library one, only showing the stories part of the library:  \n\n```sh\ncd packages/lwc-library/\nyarn storybook\n```\n\nOr you can execute it from the application, which will include both the library and the application stories:  \n\n```sh\ncd packages/lwc-app/\nyarn storybook\n```\n\nNote: in order for the composition to work, the library's Storybook must be deployed as a static site (see below for the instructions).\n\n\n### Project commands\nA series of commands is defined for each project (application and library) within `package.json`.  \n\nIn development mode, starting Storybook is done with the following commands:\n\n- `storybook`\n  Generate all the metadata files, compile the LWC components and run the development server.  \n  This is the command to use at least when running Storybook for the first time. Going forward, and depending on what changes were made to the project, more optimized commands can be used (see; package.json).  \n\n  \nThere are also some root commands to deploy the static site to Github Pages.  \n\n- `build-static`\n  Build the the static site, including the generation of `stories.json`, for both the application and the library.  \n- `deploy-static`\n  Deploy the static site built above to Github pages\n\n\n## Projects Setup\n\n### Application bundler\nStorybook is using Webpack as the application bundler. Unfortunately, LWC is generally using Rollup and there is currently no supported Webpack plugin. As a result, we'll use Rollup to build the components and Webpack to build Storybook. This has several consequences:  \n\n- There are 2 build steps, one for the components and one for Storybook itself  \n  The `.storybook/` folder contains a rollup configuration that is used to compile the LWC components. The result is a single JavaScript file, generated to `.storybook/build`, referenced and loaded by Webpack.  \n- The components displayed as part of a story must be custom elements.  \n  All exposed LWC components should be registered as custom elements. In practice, this should not be an issue as naming conflicts between libraries should be very rare.\n\n\n### Storybook folders\nBoth the library (`lwc-library`) and the application (`lwc-app`) feature 2 Storybook related directories:  \n\n- `.storybook`  \n  Contains the Storybook configuration files (`main.js`, `preview.js`...) as well as the LWC files needed for Storybook, like the rollup configuration.  \n- `.stories`  \n  Contains all the stories, for all the components. After several discussions, we decided to isolate the stories in their own folder rather than co-locating them with the components. It makes it easier for a developer to find the stories when working on them.  \n  Note that this folder also contains an `index.js` file that references and registers all the components as custom elements. This is the entry point for the Rollup build.\n\n\n### Composition\nThe main application is exposing its own stories as well as the stories defined in the library. For that, it uses the [Composition](https://medium.com/storybookjs/storybook-composition-af0da9084fba) mechanism. To enable composition, the library must be deployed as a static site with a properly generated `stories.json` file. Then, the application can either explicitly include it (see: `main.js - refs`) or implicitly if the library it includes features an entry in its `package.json` (automatic loading). This sample project uses the later, which makes it trivial to use.\n\n\n## Implementing Storybook\n\n### Creating a story for a component\nAs there is no dedicated LWC support in Storybook, this project uses the generic Web Component integration. As such, all the components that are exposed within the stories must be registered as custom elements. This is done in `/stories/index.js`.  \nStories use the [CSF](https://storybook.js.org/docs/formats/component-story-format/) format, using the `html` tag from [LitElement](https://lit-element.polymer-project.org/guide/templates) when including the markup. Omitting the tag could change the rendering, and limit how attributes/properties are passed to the components.  \n\nHere is an example:  \n\n``` js\nimport { html } from 'lit-html';\nexport const default_ = () =\u003e html`\n    \u003chello-greetings\u003e\u003c/hello-greetings\u003e\n`;\n```\n\n### Documenting Web Components\nDocumentation which is a great strengh of Storybook, can be at least partially generated. The WebComponent organization comes with a meta-data format to desbribe web components: [custom-elements.json](https://github.com/webcomponents/custom-elements-json). Warning: this format is not yet a standard and can evolve in the near future. It currently contains enough information to describe a component, its attributes, properties, events, CSS variables...  \n\nWriting or maintaining such a file manually is cumbersome, so we better generate it from the component source files. This task is achieved by a third party library: [web-component-analyzer](https://github.com/runem/web-component-analyzer#readme). Version 1.2.0+ of the library now understands LWC so it can find the LWC components based on common constructs including the LWC specific decorators, like @api. see: [web-component-analyzer for LWC](https://github.com/runem/web-component-analyzer/blob/master/ANALYZE.md#lwc).\nIn order to refine the Javascript metadata, the source code can be enriched with [JSDoc](https://jsdoc.app/) information. See how web-component-analyzer supports a set of web components specific tags described [here](https://www.npmjs.com/package/web-component-analyzer#%E2%9E%A4-how-to-document-your-components-using-jsdoc). \n\n```js\n/**\n * LWC Component taggeg with JSDoc comments.\n */\nexport default class MyComponent extends LightningElement {\n    /**\n     * name is a public attribute\n     */\n    @api name = ''\n    /**\n     * message is a private property\n     */\n    message = ''\n    \n    ...\n}\n```\n\n#### Generating documentation files\n`web-component-analyzer` can also generate a markdown file describing the full list of components.  To experiment it, run:  \n```sh\nyarn storybook:meta-doc\n```\nThe resulting documentation file is generated in the `.stories/build` folder.\n\n\n### Story types\nThis sample application shows different story types.  \n\n#### Component story\nComponent stories are defined using the [CSF](https://storybook.js.org/docs/formats/component-story-format/) format within `xxx.stories.js` files. Simply add the file to the `/stories` folder in the project root, or one of its subdirectories. Storybook is configured to automatically load all of them.\n\nMake sure that the HTML markup uses the [LitElement](https://lit-element.polymer-project.org/guide/templates) `html` tag.  \n\nHere is an example: [https://github.com/LWC-Essentials/storybook/blob/master/packages/lwc-library/stories/hello-greetings.stories.js](https://github.com/LWC-Essentials/storybook/blob/master/packages/lwc-library/stories/hello-greetings.stories.js).  \n\n#### Documentation story\nStorybook also uses [MDX](https://storybook.js.org/docs/formats/mdx-syntax/) files to provide a customizable documentation for the components. An MDX file contains a mix of markdown and React JSX. Documentation stories are defined within `xxx.stories.mdx` files that are also automatically loaded. Similarly to the component stories, it uses the LitElement `html` tag for the component markup.  \n\nHere is an example: [https://github.com/LWC-Essentials/storybook/blob/master/packages/lwc-library/stories/doc-greetings.stories.mdx](https://github.com/LWC-Essentials/storybook/blob/master/packages/lwc-library/stories/doc-greetings.stories.mdx).  \n\n#### Static content\nWithout creating the documentation, a static story only displaying content can easily be created using HTML.  \n\nHere is an example: [https://github.com/LWC-Essentials/storybook/blob/master/packages/lwc-app/stories/welcome.stories.js](https://github.com/LWC-Essentials/storybook/blob/master/packages/lwc-app/stories/welcome.stories.js).  \n\n#### Interacting with the components\nThe project shows how to display component attributes \u0026 properties using [Controls](https://github.com/storybookjs/storybook/blob/next/addons/controls/README.md#writing-stories). The stories for the `hello-greetings` demonstrate different variations.\n\nSee this example: [https://github.com/LWC-Essentials/storybook/blob/master/packages/lwc-library/stories/hello-greetings.stories.js](https://github.com/LWC-Essentials/storybook/blob/master/packages/lwc-library/stories/hello-greetings.stories.js)\n\n\n### Developer experience\nOne of the value of Storybook is the component development experience, where code changea are reflected automatically in the Storybook UI. For this, Storybook relies on Webpack watchers. But this is not sufficient as the components are built using Rollup. Rollup is thus started with its own watchers to rebuild when a component is changed. Then Webpack watches the changes to the Rollup built file and rebuilds itself.  \n\nAs both Webpack and Rollup have watchers, the 2 processes must run in parallel. To make this reliable, we use [npm-run-all](https://www.npmjs.com/package/npm-run-all) instead of the simple `\u0026` operator when launching processes. This better manages the termination of the background processes.  \n\n\n### Deploying the static sites\nThe sites are deployed by default to Gihub pages, using using [gh-pages](https://www.npmjs.com/package/gh-pages). An easy solution would use [storybook-deployer](https://github.com/storybookjs/storybook-deployer), but is is less flexible in particular when deploying multiple Storybook sites from a mono repo.  \n\nDeploying the static sites involves the following commands from the project root:\n\n```sh\nyarn build-static\nyarn deploy-static\n```\n\n## LWC Specific\n\n### Complex properties\nLWC components can consume complex property values, like objects. Unfortunately, the custom element specification does not allow such values to ba passed through HTML markup.  \n\nThere are multiple solutions: \n\n- Use LitElement template syntax  \n  The `html` syntax allows properties to be passed as any value when the its name starts with a dot `.`. Here is an example, where the time is passed as an object:  \n  \n  ```\n  export const staticTime = () =\u003e html`\n    \u003chello-time .time=${{hours:1,minutes:3,seconds:4}}\u003e\u003c/hello-time\u003e\n  `;\n  ```\n\n- Create a technical Web Component that wraps the desired one, and pass it complex parameters via the template  \n  The library demo defines these components in the `wc` namespace located in `stories`. Note that the syntax above should be preferred in most cases, as it is simpler. Such a wrapper can be useful when an LWC template is required, for example when dealing with slots without Shadow DOM.  \n\n\n### Provided add-ons\nThe sample app configures a set of add-ons\n\n- [@storybook/addon-docs](https://www.npmjs.com/package/@storybook/addon-docs)  \n   Docs transforms your Storybook stories into world-class component documentation.\n- [@storybook/addon-a11y](https://www.npmjs.com/package/@storybook/addon-a11y)  \n  Check the accessibility of a component. It shows any potential issue in a panel.  \n- [@storybook/addon-storysource](https://www.npmjs.com/package/@storybook/addon-storysource)  \n  Storysource show stories source in the addon panel\n- [@storybook/addon-actions](https://www.npmjs.com/package/@storybook/addon-actions)  \n  Display data received by event handlers.  \n- [@storybook/addon-controls](https://www.npmjs.com/package/@storybook/addon-controls)  \n  Controls gives you UI to interact with a component's inputs dynamically, without needing to code.    \n- [@storybook/addon-events](https://www.npmjs.com/package/@storybook/addon-events)  \n  Events allows you to add events for your stories.    \n- [@storybook/addon-jest](https://www.npmjs.com/package/@storybook/addon-jest)  \n  Brings Jest results in storybook.\n- [@storybook/addon-viewport](https://www.npmjs.com/package/@storybook/addon-viewport)  \n  Viewport allows your stories to be displayed in different sizes and layouts in Storybook.\n- [@storybook/addon-backgrounds](https://www.npmjs.com/package/@storybook/addon-backgrounds)  \n  Let a user change the background color within the preview window.  \n- [@storybook/addon-storyshots](https://www.npmjs.com/package/@storybook/addon-storyshots)  \n  StoryShots adds automatic Jest Snapshot Testing for Storybook.\n- [@storybook/addon-links](https://www.npmjs.com/package/@storybook/addon-links)  \n  Links can be used to create links that navigate between stories in Storybook.\n\nThe WebComponent organization is also coming with extra add-ons, like [storybook-addon-web-components-knobs](https://www.npmjs.com/package/storybook-addon-web-components-knobs), but they have not been integrated with this sample project yet.\n\n\n\n## TODOs\nYes there are TODOs...  \n\n- Decrease the build time  \n  One solution is to provide a prebuilt-version of Storybook, see: [https://github.com/open-wc/storybook-prebuilt](https://github.com/open-wc/storybook-prebuilt)\n  \n- Use the LWC compiler to extract meta-data  \n  The Stencil compiler provides such a feature, although it missed some of the meta-data. The LWC has an RFC for a canonical meta-data format: [https://github.com/salesforce/lwc-rfcs/pull/33/files?short_path=2648c38#diff-2648c38fced96da2e0c183fd293d54eb](https://github.com/salesforce/lwc-rfcs/pull/33/files?short_path=2648c38#diff-2648c38fced96da2e0c183fd293d54eb).  \n  \n- Extend web-component-analyzer to better support LWC  \n  [https://github.com/runem/web-component-analyzer/issues/150 ](https://github.com/runem/web-component-analyzer/issues/150)\n  - Scan the lwc.config.json to enumerate the components\n  - Deduce the element name from the directory of a component\n  - Handle @api and other decorators  \n  - ...\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flwc-essentials%2Fstorybook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flwc-essentials%2Fstorybook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flwc-essentials%2Fstorybook/lists"}