StencilJS и Storybook

StencilJS — отличный инструмент для создания веб-компонентов, а Storybook — для создания дизайнерских систем, но интеграция этих двух инструментов не кажется очень естественной, потому что нет единого правильного способа сделать это.
После долгих исследований я покажу вам простой способ осуществить эту интеграцию и не умереть, пытаясь 😁.

Создайте проект трафарета

npm init stencil
Войдите в полноэкранный режим Выйти из полноэкранного режима

Появится несколько вопросов. Ответьте на них следующим образом

✔ Pick a starter > component
✔ Project name > storybook-wc-stencil
Войти в полноэкранный режим Выйти из полноэкранного режима

После этого у вас будет трафаретный проект с базовым примером компонента внутри.

Установите зависимости

cd storybook-wc-stencil
yarn install
Войти в полноэкранный режим Выйти из полноэкранного режима

Игнорировать код node_modules при проверке

Добавьте свойство skipLibCheck для исключения кода node_modules

tsconfig.json

{
  "compilerOptions": {
    ...
    "skipLibCheck": true,
  },
  ...
Войти в полноэкранный режим Выйти из полноэкранного режима

Создание файла типизации для импорта tsx

Наш линтер может давать нам проблемы при попытке импортировать md файлы, мы также можем использовать этот файл для другого типа расширений.

src/typings.d.ts

declare module '*.jpg';

declare module '*.md' {
  const value: string; // markdown is just a string
  export default value;
}

declare module '*.css' {
  const content: { [className: string]: string };
  export default content;
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Добавить сюжетную книгу

npx -p @storybook/cli sb init --type html 
Войти в полноэкранный режим Выйдите из полноэкранного режима

В результате будет создан проект сборника рассказов

Добавить аддон для заметок

yarn add -D @storybook/addon-notes
Войти в полноэкранный режим Выйти из полноэкранного режима

.storybook/main.js

module.exports = {
  stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
  addons: [
    '@storybook/addon-links',
    '@storybook/addon-essentials',
    '@storybook/addon-notes',
  ],
  framework: '@storybook/html',
};

Войти в полноэкранный режим Выйти из полноэкранного режима

Конфигурация для загрузки компонентов Stencil в Storybook

.storybook/preview.js

import { defineCustomElements } from '../dist/esm/loader';

defineCustomElements();

export const parameters = {
  actions: { argTypesRegex: '^on[A-Z].*' },
  controls: {
    matchers: {
      color: /(background|color)$/i,
      date: /Date$/,
    },
  },
};

Войти в полноэкранный режим Выход из полноэкранного режима

Очистка историй

Давайте удалим все содержимое из каталога stories

Структура проекта

Создайте новый файл my-component.stories.tsx в каталоге src/stories.

Структура вашего проекта должна выглядеть следующим образом

./storybook-wc-stencil/
|
|---- .storybook/
|     |---- main.js
|     |---- preview.js
|---- src/
|     |---- components/
|     |     |---- my-component/
|     |           |---- my-component.css
|     |           |---- my-component.e2e.ts
|     |           |---- my-component.spec.ts
|     |           |---- my-component.tsx
|     |           |---- readme.md
|     |---- stories/
|     |     |---- components/
|     |           |---- my-component.stories.tsx
|     |---- typings.d.ts
|---- .editorconfig
|---- .gitignore
|---- .prettierrc.json
|---- LICENSE
|---- package.json
|---- readme.md
|---- stencil.config.ts
|---- tsconfig.json
|---- yarn.lock
Вход в полноэкранный режим Выход из полноэкранного режима

Генерация компонентов

Мы можем использовать следующую команду для автоматической генерации наших компонентов в каталоге компонентов

yarn generate component-name
Войти в полноэкранный режим Выйти из полноэкранного режима

Запустить проект

Для горячей перезагрузки мы должны выполнить эти две команды параллельно, поэтому мы можем использовать два терминала или создать новый скрипт

yarn build -- --watch
Войти в полноэкранный режим Выйти из полноэкранного режима
yarn storybook
Войти в полноэкранный режим Выйти из полноэкранного режима

Первая команда сгенерирует сборку наших компонентов, мы используем флаг --watch, чтобы всегда генерировать эту сборку при любом изменении.

Структура кода Story

Мы столкнемся с некоторыми недостатками при работе с storybook с помощью трафарета

  • Нам нужно определить свойства, которые мы хотим использовать в элементах управления
    • Нам нужно определить реквизиты по умолчанию для элементов управления
  • Нам нужно добавить описание и типы реквизитов для страниц Docs
  • Свойство defaultValue не работает для страниц документов
  • Нам нужно передать значения args в шаблоне
// This md file is generated by stencil, and we are going to use it as a note page
import notes from '../../components/my-component/readme.md';

export default {
  title: 'UI/My Component',
  args: {
    // Here we define default values that we want to show on controls
    // Also, only props defined here are going to be shown
    first: 'Juan Fernando',
    middle: 'Gómez',
    last: 'Maldonado',
  },
  argTypes: {
    // Here we can add description and prop value type
    first: {
      description: 'First name',
      // First way to define type
      table: {
        type: {
          summary: 'string',
        },
      },
    },
    middle: {
      // Second and shorter way to define type
      type: {
        summary: 'string',
      },
    },
    last: {
      // We can disable the property
      // This will hide it in controls and Doc page
      table: {
        disable: true,
      },
    },
  },
  parameters: {
    // This will create a note page for our story component
    notes,
  },
};

const Template = args =>
  `<my-component first="${args.first}" middle="${args.middle}" last="${args.last}"></my-component>`;

export const Basic = Template.bind({});

export const Another = Template.bind({});
Another.args = {
  first: 'John',
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Более чистый способ добавления значений и описания для историй

Чтобы избежать шаблонного кода, я создал простую библиотеку, которая возвращает args, argTypes и пользовательский шаблон для нашего компонента. Эта библиотека — story-wc-generator.

yarn add story-wc-generator
Вход в полноэкранный режим Выход из полноэкранного режима
import notes from '../../components/cool-button/readme.md';
import storyGenerator from 'story-wc-generator';

const { args, argTypes, Template } = storyGenerator('cool-button', {
  text: { value: 'Click me!', description: 'Text label', type: 'string' },
  color: {
    value: 'primary',
    description: 'Color of button',
    control: 'select',
    options: ['primary', 'secondary', 'dark'],
    type: 'primary | secondary | dark',
  },
});

export default {
  title: 'UI/Cool Button',
  args,
  argTypes,
  parameters: {
    notes,
  },
};

export const Primary = Template.bind({});

export const Secondary = Template.bind({});
Secondary.args = {
  color: 'secondary',
};

...
Вход в полноэкранный режим Выход из полноэкранного режима

Этот пример включает все свойства, которые могут быть использованы, но вы можете обратиться к
документацию для получения дополнительной информации о библиотеке

После создания наших компонентов и историй мы должны получить результат, подобный этому

Вы можете посмотреть репозиторий здесь, а живой проект здесь

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *