Storybook и документация (references/storybook.md)

Источник: ds-skills/core-ui-development-skills/src/skills/build-core-ui-components/references/storybook.md — справочник скилла build-core-ui-components

  • Использовать StoryFn и Meta из storybook-react-rsbuild по примеру ближайших актуальных историй.
  • Добавлять Default; добавлять Common, если полезно показать матрицу вариантов.
  • Исключать из controls технические пропсы.
  • Подключать docs.mdx и сохранять русскоязычную структуру соседних компонентов.
  • Использовать служебные story-пропсы с префиксом _ и русским argTypes.name.
  • Для нового компонента задавать tags: ["version:1.0.0"]. Не копировать версию соседнего компонента или текущую версию пакета core-ui.
  • При изменении существующего компонента сохранять его текущий version-тег, если повышение версии явно не согласовано.
  • Для нетривиальных примеров использовать механизм src/storybook-docs/write-story-with-code: хранить исполняемый .tsx в storybook/examples/ и импортировать этот же файл через ?raw для панели Code.
  • Давать вложенному компоненту отдельную Storybook-страницу только при самостоятельном публичном контракте и после согласования.
  • Брать title, параметры и структуру документации у ближайшего компонента того же раздела.

Локальные компоненты историй

Если для истории JSX-фрагмент выносится в константу или функцию ради повторного использования либо разгрузки stories.tsx, оформлять его React-компонентом в storybook/components/. Не хранить в stories.tsx конструкции вида const content = (<div>...</div>) или const heading = (<Component />).

Для каждого такого компонента создавать отдельную kebab-case директорию с реализацией и локальным index.ts; относящиеся только к нему стили хранить рядом:

storybook/components/
├── index.ts
├── common-content/
│   ├── common-content.tsx
│   ├── styles.module.scss
│   └── index.ts
└── common-section-heading/
    ├── common-section-heading.tsx
    ├── styles.module.scss
    └── index.ts

В корневом storybook/components/index.ts собирать экспорты локальных story- компонентов, а в stories.tsx импортировать их через подтверждённый alias репозитория. Не экспортировать эти компоненты из публичного API библиотеки и не создавать для них отдельные Storybook-страницы.

Canvas в разделе «Описание»

В разделе ## Описание показывать только одну обзорную историю:

  • если компонент имеет Common, использовать <Canvas of={ComponentStories.Common} />;
  • если Common отсутствует, использовать <Canvas of={ComponentStories.Default} />;
  • не выводить Default и Common одновременно в разделе «Описание».

Ссылки на код и дизайн в docs.mdx

При создании документации компонента сразу после заголовка первого уровня добавлять ссылки на код компонента в GitLab и его макет в Figma по паттерну актуальных компонентов:

# ComponentName

[Код](https://gitlab.rshbdev.ru/rshbintech/crft/ckof/ownfin/frontend/core/core-ui/-/tree/master/src/component-name)
&nbsp;|&nbsp;
[Дизайн](https://www.figma.com/design/<figma-file>/<design-system>?node-id=<node-id>&p=f&m=dev)
  • Для ссылки Код подставлять kebab-case директорию компонента из src/ и всегда указывать стабильную ветку master.
  • Для ссылки Дизайн использовать URL переданного макета или ссылку из документации ближайшего актуального компонента только тогда, когда она относится к тому же макету.
  • Не придумывать Figma URL или node-id. Если ссылка на дизайн неизвестна, явно сообщить об этом пользователю и не подставлять фиктивное значение. Исключение — контракт компонента: его раздел source даёт ключ файла и node-id, см. истории из контракта.
  • Сохранять разделитель &nbsp;|&nbsp; между ссылками.

Пример с отображением исходного кода

Создавать для примера единственный исполняемый источник:

storybook/examples/
├── index.ts
└── default/
    ├── default.tsx
    ├── index.ts
    └── styles.module.scss # при наличии локальных стилей примера

Называть директорию, файл, example-компонент и raw-экспорт по сценарию истории. Для Default использовать default/default.tsx, компонент UsingDefault и raw-экспорт defaultCode; для других сценариев использовать соответствующие пары UsingSublist/sublistCode, UsingList/listCode и аналогичные осмысленные имена. Не называть example-компонент по production-компоненту (UsingCustomLayer, UsingBasicList) и не использовать общие имена вроде UsingExample или exampleCode.

В локальном index.ts экспортировать компонент, типы и константы примера, которые используются историей или тестами, и прочитать тот же исполняемый файл через ?raw:

export {
  UsingDefault,
  DEFAULT_STORY_ITEM,
  type ItemType,
} from "./default";
import defaultCode from "./default.tsx?raw";

export { defaultCode };

В examples/index.ts собрать код и публичный компонент примера:

import { defaultCode } from "./default";

export const Examples = { defaultCode };
export { UsingDefault, type ItemType } from "./default";

В stories.tsx передать исходник истории в parameters.docs.source.code:

/**
 * Default Story
 */
export const Default: StoryFn<ComponentProps<ItemType> & StoryArgs> = (args) => (
  <UsingDefault {...args} />
);

Default.parameters = {
  docs: {
    source: {
      code: Examples.defaultCode,
    },
  },
};

Не дублировать исполняемый пример строкой в stories.tsx или docs.mdx: код панели должен поступать из того же .tsx, который рендерит история.

Стили историй и examples

  • Стили, относящиеся только к конкретному исполняемому примеру, хранить рядом с ним: storybook/examples/<scenario>/styles.module.scss.
  • Импортировать локальные стили непосредственно из <scenario>.tsx; пример должен оставаться самостоятельным источником разметки и оформления для панели Code.
  • В storybook/styles.module.scss преимущественно хранить оформление самой истории: grid/flex-раскладку Common, размеры демонстрационной области, расстояния между вариантами, подписи и общие story-обёртки.
  • Не переносить в общий storybook/styles.module.scss стили содержимого Default, Sublist или другого отдельного example только ради повторного использования файла.
  • Если один стиль действительно используется несколькими историями, оставить его общим и явно отделить от локальных стилей examples.

Расстояние между вариантами в Common

При вертикальном, горизонтальном или grid-отображении нескольких вариантов задавать между соседними вариантами расстояние не меньше var(--space-xl).

Использовать gap, row-gap и column-gap, а не padding дочерних компонентов:

.common {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xl);
}

Если расстояния по осям задаются отдельно, каждое должно быть не меньше var(--space-xl):

.common {
  display: grid;
  row-gap: var(--space-xl);
  column-gap: var(--space-xl);
}

Не считать внутренний padding демонстрируемого компонента расстоянием между вариантами. Не уменьшать gap без явного требования дизайна.