Некоторое время мы использовали Storybook для документирования нашей библиотеки компонентов React, и, хотя нам это нравится, нам пришлось использовать различные пакеты дополнений и делать некоторые хитрые вещи, чтобы заставить компоненты показать то, что мы хотели. Storybook недавно претерпел большие изменения в управлении версиями, поэтому я сел обновить все с 5.0 до последней версии и посмотреть, что изменилось.

После обновления всех пакетов npm сборника рассказов я вижу, что файлы конфигурации полностью изменились. Я могу удалить .storybook/addons.js и .storybook/config.js

Вместо этого мне нужно:

// .storybook/main.js
module.exports = {
    stories: ['../_stories/**/*.stories.@(js|mdx)'], // adding mdx support here
    addons: [
        '@storybook/addon-knobs/register',
        {
            name: '@storybook/addon-docs', // new addon for docs
            options: {
                configureJSX: true,
                babelOptions: {},
                sourceLoaderOptions: null
            }
        },
    ]
};

а также

// .storybook/preview.js
import React from 'react';
import { configure, addDecorator, addParameters } from '@storybook/react';
import { DocsPage, DocsContainer } from '@storybook/addon-docs/blocks';
import { withInfo } from '@storybook/addon-info';
import { create } from '@storybook/theming';
import './index.scss';
addParameters({
    // This whole section needs to be added for docs support
    docs: {
        container: DocsContainer,
        page: DocsPage
    }
});
function loadStories() {
    require('../_stories/');
}
const storyWrapper = story => <div style={{ margin: 35 }}>{story()}</div>;
addDecorator(
    withInfo({
        inline: true,
        header: false,
        source: true,
        maxPropsIntoLine: 1
    })
);
addDecorator(storyWrapper);
configure(loadStories, module);

Ладно неплохо, после этого вроде все заработало.

Дополнение к Документам

Затем я пытаюсь разобраться в новом аддоне документации, который, похоже, теперь обрабатывает документацию из коробки, И допускает уценку, которую мы в настоящее время реализуем через аддон сообщества под названием storybook-readme. (Технически этот новый аддон документации поддерживает mdx, который позволяет комбинировать разметку и jsx.) В идеале, я бы подумал, что могу удалить сборник рассказов-ридми и использовать официальный аддон прямо сейчас!

Мы используем аддон readme, потому что у нас есть несколько более сложных компонентов, и мы хотели для простоты написать их документацию в разметке.

Я узнал, что в последней версии Storybook, в самой простой версии, документы автоматически создаются для вас, что не совсем то, что нам нужно.

Поскольку вместо этого мы хотим использовать mdx для написания нашей документации, нам нужно использовать подход CSF-истории с произвольным mdx.

Примечание.

  • Storybook также предоставляет вам способ сказать это просто для использования mdx, но поскольку мы также используем другие надстройки (в первую очередь, нам очень нравится использовать ручки), мы также не хотим использовать этот подход.

Вот чем закончилась одна из наших самых простых историй ...

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

// Badge.stories.js
import React from 'react';
import { withKnobs, object, text, boolean, select } from '@storybook/addon-knobs/react';
import mdx from './Badge.mdx';
import Badge from '../../../components/atoms/Badge';
const options = {
    'No Value': '',
    inverse: 'inverse',
    success: 'success',
    'success-inverse': 'success-inverse',
    info: 'info',
    'info-inverse': 'info-inverse',
    warning: 'warning',
    'warning-inverse': 'warning-inverse',
    danger: 'danger',
    'danger-inverse': 'danger-inverse'
};
export default {
    component: Badge,
    title: 'Atoms/Badge',
    decorators: [withKnobs],
    parameters: {
        docs: { page: mdx }, // Need to add this param to show the mdx docs
    }
};
export const Default = () => {
    return (
        <Badge
            text={text('Text', '2')}
            context={select('Context', options, '')}
            empty={boolean('Empty', false)}
            className={text('ClassName', '')}
            style={object('Style', {})}
        />
    );
};

Примечания:

  • Я сохранил информацию об аддоне, чтобы отображать источник каждой истории. Если история встраивается непосредственно в файл MDX, источник не будет отображаться при переносе встроенного <Story> в <Preview>. Чтобы этот исходный код появился, нам нужно добавить source: true в пример файла .storybook/preview.js в верхней части этой статьи. Я считаю, что показ источника очень полезен, поскольку вы можете скопировать и вставить его для использования в своем коде.
  • По умолчанию в export const Default - это то, что у вас есть компонент под названием, как на боковой панели навигации. При желании здесь может отображаться несколько версий компонентов. Обычно мы просто используем ручки, чтобы показать разные варианты, но мы используем их в нашем компоненте разбивки на страницы, чтобы показывать разные конфигурации.

Это появится на вкладке Документация:

// Badge.mdx
import { Story } from '@storybook/addon-docs/blocks';
import Badge from '../../../components/atoms/Badge';
# Badge
The `<Badge>` component is a numerical indicator of associated items. For a simple colored circle without a number inside, pass in the "empty" prop. If empty, it will not display any text within the badge.
## Component example
<Story id="atoms-badge--default" /> // see note below on what id to put here

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

Примечание.

Моему компоненту нужно состояние!

У нас есть еще несколько сложных компонентов, которые требуют от нас отслеживания состояния, чтобы они работали должным образом. Лучший подход, который я нашел для этого, можно увидеть в Компоненте разбивки на страницы.

import React from 'react';
import { withKnobs, number, boolean, select } from '@storybook/addon-knobs';
import { action } from '@storybook/addon-actions';                       
import mdx from './Pagination.mdx';
import Pagination from '../../../components/molecules/Pagination'; 
const sizeOptions = {
    xl: 'xl',
    lg: 'lg',
    sm: 'sm',
    xs: 'xs',
    'No Value': ''
};    
export default {
   component: Pagination,
    title: 'Molecules/Pagination',
    decorators: [withKnobs],
    parameters: {
        component: Pagination,
        docs: { page: mdx }
    }
};
class PaginationStory extends React.Component {
    state = {
        activePage: 7,
        lastPage: 70
    };
    handlePageChange = newPage => {
        const activePage = newPage;
        this.setState({ activePage });
        action('Page change')(activePage);
    };
    render() {
        const { activePage, lastPage } = this.state;
        return (
           <Pagination
                activePage={number('Current Page', activePage)}
                lastPage={number('Last Page', lastPage)}
                boundaries={boolean('Show Boundaries', false)}
                justify={boolean('Justify', false)}
                size={select('Size', sizeOptions, '')}
                onChange={this.handlePageChange}
            />
       );
   }
}
PaginationStory.displayName = 'Pagination';
export const Default = () => { return <PaginationStory />; };
Default.story = {
    parameters: {
        info: { source: false }
    }
};

Вы можете видеть здесь, что я определяю компонент класса, а затем экспортирую этот компонент. Здесь следует отметить одну вещь: я переопределил параметры истории, чтобы не отображать источник. Это потому, что, поскольку вы экспортируете <PaginationStory />, вы просто увидите это, что бесполезно. Вместо этого я хотел бы увидеть источник <Pagination>, что невозможно, поэтому я предпочитаю скрыть его. На странице компонента mdx я привожу примеры компонента.

Таблицы опор

Таблицы свойств на страницах документации значительно улучшены. Они заполняются непосредственно из вашего компонента propTypes, но есть несколько дополнительных моментов, на которые следует обратить внимание:

Описание:

  • Используйте комментарий над каждым типом propType, чтобы добавить описание, которое будет отображаться в таблице /** My description here */
  • Использование PropTypes.oneOfType(['optionA', 'optionB']) заполняет таблицу описания с принятыми параметрами.

Обязательно:

  • Добавление .isRequired к вашему propType добавляет к нему * в таблице

По умолчанию:

  • Чтобы указать значение по умолчанию, используйте defaultProps в ваших компонентах.

Реквизиты для подкомпонентов:

// Accordion.stories.js
parameters: {
    component: Accordion,
    subcomponents: { AccordionItem, AccordionItemContent },
    docs: { page: mdx }
}

Документация только рассказы

Наконец, у нас также есть некоторые компоненты только для документации, которые Storybook теперь поддерживает более простым способом с помощью MDX:

// Name any files Name.stories.mdx; this one is Installation.stories.mdx
import { Meta } from '@storybook/addon-docs/blocks';
<Meta title="Getting Started/Installation" /> // This is the path you want it to show at
## Installation
Docs here

С тех пор, как мы начали использовать Storybook более 3 лет назад, было здорово видеть, что он постоянно развивается и улучшается. Их новый аддон Docs упрощает интеграцию части документации ваших компонентов пользовательского интерфейса, даже если это требует небольшой настройки. Надеюсь, эта статья поможет вам понять, как проще интегрировать оба документа с другими пакетами дополнений. Вы можете увидеть всю разницу этого изменения на странице GitHub.

Мы всегда ищем новые таланты! Просмотр вакансий.

Следуйте за нами: Facebook | Твиттер | | Linkedin | Инстаграм