Original address: medium.com/storybookjs…

Original author: medium.com/stijn.koop…

Published: March 16, 2018-4 minutes to read

So, you’ve been designing and implementing beautiful standalone Web Components. However, you can only see them working in your application itself, in combination with other components. Doesn’t that defeat the purpose of standalone components? Wouldn’t it be easier if you could implement the components one by one? Meet the Storybook.

Storybook allows you to develop and test your components in isolation. Quote them on Github.

Storybook is a UI component development environment that allows you to browse through a component library, see the different states of each component, and develop and test components interactively. It allows you to browse component libraries, see the different states of each component, and develop and test components interactively.

In this case, a UI component is framework-independent. Storybook supports React(+Native), Angular, Vue and, starting with V3.4.0, Polymer 2! Go Web Components ✨ ✨

Among my current clients, we are using Polymer 2.5 and Storybook, which works like a sunshine! This article will show you what this setup looks like. On this GitHub repo, you can find the source code.

In this article, I hope you have some knowledge of the Web Components standard.

An introduction to

Let’s get started! Storybook comes with a CLI that detects the framework being used in the current working directory. We need this CLI as a global dependency and at least version V.3.4.0 is required. We need this CLI as a global dependency, and we need at least version V.3.4.0. After installing the CLI, the getStoryBook command will install Storybook for your project. Run the following command from the command line.

NPM i-g@storybook /[email protected] CD my-polymer-app getStorybookCopy the code

This will install the Storybook via NPM (even if you install Polymer with Bower). It also generates a.storybook directory that contains the Storybook configuration.

To start storybook, run NPM storybook and open http://localhost:6006.

Your first story

Well, that’s easy. It’s time to build our first story.

A simple progress bar story

Suppose we have a Web ComponentsProgress-bar with several properties.

  • value: Percentage of filling bar chart; A number between 0 and 100.
  • reverse: Whether from right to left.
  • hidePercentage: Whether to hide percentage text.

To add a storybook to this component, we add a file progress-bar.stories.js, which looks like this.

import {storiesOf} from '@storybook/polymer';
import './progress-bar.html';

storiesOf('Progress bar'.module)
  .add('default view'.() = > '<progress-bar value="50"></progress-bar>');
Copy the code

There are two important things to note here. We import the HTML file of the component itself. This can also be a JS file if you plan to use the template() function.

Notice that we return the component as an HTML string. This is the first and easiest way to render Web Components that Storybook supports.

Dynamic component states and events

The second option supported in Storybook is to render an instantiated Element. We can create an element using document.createElement. It will create an element based on the tag name you gave it. In our example, we can provide progress-bar as the tag name.

import {storiesOf} from '@storybook/polymer';
import './progress-bar.html';

storiesOf('Progress bar'.module)
  .add('default view'.() = > {
    const el = document.createElement('progress-bar');
    el.value = 50;
    return el;
  });
Copy the code

This example will produce exactly the same result as our simple scenario where we provide an HTML string.

The document.createElement story is more verbose and cumbersome, but it offers more flexibility. We can now not only pass more complex types to attributes, but also attach event handlers.

Let’s explore a more complex example using Storybook actions and knobs.

import {storiesOf} from '@storybook/polymer';
import {withKnobs, number, boolean} from '@storybook/addon-knobs/polymer';
import {action} from '@storybook/addon-actions';

import './progress-bar.html';

const percentageRange = {
  range: true.min: 0.max: 100.step: 1}; storiesOf('Progress bar'.module)
  .addDecorator(withKnobs)
  .add('with Knobs! '.() = > {
    const el = document.createElement('progress-bar');
    el.value = number('Percentage'.50, percentageRange);
    el.reverse = boolean('Reversed'.false);
    el.hidePercentage = boolean('Hide percentage'.false);
    el.addEventListener('value-change'.e= > action('value-change')(e.detail));
    return el;
  });
Copy the code

This story provides buttons and sliders in the Storybook to configure the displayed components. It also displays a panel with actions dispatched from the component. More specifically, in this case, it listens for the value-change event.

The story of a progress bar with a knob.

Modelling design

Our Progress-Bar component can be styled from outside the component by utilizing CSS custom properties. To set these variables from the story, use the following code.

const cssVariables = ({
  '--progress-bar-background-color': color('Background color'.'red'.'colors'),
  '--progress-bar-font-color': color('Font color'.'white'.'colors'),
  '--progress-bar-color': color('Foreground color'.'black'.'colors')});Object.keys(properties).forEach(key= > el.style.setProperty(key, properties[key]));
Copy the code

Stylize the progress bar

slot

Slots are part of the Web Component standard. They are placeholders in the component that can be filled with tags from outside the component. Think of the child components in React. Using the method above, we must create an element for each slot we need to fill. You can find an example below. Notice that we assign the slot attribute to the child element that fills a particular slot.

import {storiesOf} from '@storybook/polymer';

import './with-slots.html';

storiesOf('Withs slots'.module)
  .add('default view'.() = > {
    const el = document.createElement('with-slots');

    const header = document.createElement('h1');
    header.slot = 'header';
    header.innerHTML = 'Injected header! ';
    el.appendChild(header);

    const paragraph = document.createElement('p');
    paragraph.innerHTML = 'Injected paragraph! ';
    el.appendChild(paragraph);

    return el;
  });
Copy the code

Creating a component configured with slots and CSS custom attributes can be quite tedious. But don’t grieve, there is a solution!

Additional: lit – HTML

Along with the introduction of Polymer 3 (preview) comes the introduction of lit-HTML.

Lit-html lets you write HTML templates in JavaScript template literals and effectively render and re-render those templates into the DOM.

Since V4.0.0-alpha4, lit-HTML has been integrated into the core of Storybook. Take a look at the following example.

import {storiesOf} from '@storybook/polymer';
import {html} from 'lit-html';
import {withKnobs, color} from '@storybook/addon-knobs/polymer';

import './with-slots.html';

storiesOf('Withs slots'.module)
  .addDecorator(withKnobs)
  .add('bonus: with lit-html'.() = > html`
    <style>
      with-slots {
        --some-css-variable: ${color('Some color'.'red')};
      }
    </style>
    <with-slots>
      <h1 slot="header">Injected header!</h1>
      <p>Injected paragraph</p>
    </with-slots>
  `);
Copy the code

Whoop, this is a big improvement over the previous example! Simpler and less verbose, we’ve also added some CSS custom properties and slots. Well done:)


That’s it! If you want to experiment on your own, find some examples on GitHub and try them out for yourself.

Github.com/stijnkoopal…


www.deepl.com translation