返回面向开发者的设计系统
React
章节
  • 简介
  • 架构
  • 构建
  • 评审
  • 测试
  • 文档
  • 分发
  • 工作流程
  • 结论

构建 UI 组件

设置 Storybook 以构建和编目设计系统组件
此社区翻译尚未更新至最新版本的 Storybook。请帮助我们将英文指南中的更改应用于此翻译,以更新此翻译。 欢迎提交 Pull Request.

在第 3 章中,我们将从最流行的组件浏览器 Storybook 开始,设置必要的设计系统工具。本指南的目标是向您展示专业团队如何构建设计系统,因此我们还将关注更精细的细节,例如代码卫生、节省时间的 Storybook 插件和目录结构。

Where Storybook fits in

代码格式化和代码检查以保证代码卫生

设计系统是协作性的,因此修复语法和标准化格式的工具可以提高贡献质量。与手动检查代码相比,使用工具强制执行代码一致性所需的工作量要少得多,这对足智多谋的设计系统作者来说是一个好处。

在本教程中,我们将使用 VSCode 作为我们的编辑器,但您可以将相同的原则应用于其他现代编辑器,如 AtomSublimeIntelliJ

为了确保一致的代码风格,我们将使用 Prettier。这个代码格式化工具被广泛使用,并支持多种语言。它可以与大多数编辑器无缝集成,包括我们正在使用的编辑器,并且在我们初始化设计系统时,它已包含在我们之前在本指南中克隆的模板中。如果您是 Prettier 的初次用户,您可能需要为您的编辑器配置它。对于 VSCode,请安装 Prettier 插件。

Prettier addon for VSCode

如果您尚未启用“保存时格式化”editor.formatOnSave,请启用它。安装 Prettier 后,您应该会发现它会在您每次保存文件时自动格式化您的代码。

安装 Storybook

Storybook 是行业标准的 组件浏览器,用于隔离开发 UI 组件。由于设计系统专注于 UI 组件,因此 Storybook 是此用例的理想工具。我们将依赖以下功能

  • 📕编目 UI 组件
  • 📄将组件变体另存为 stories
  • ⚡️开发者体验工具,如热模块重载
  • 🛠支持多种视图层,包括 React

使用以下命令安装并运行 Storybook

# Installs Storybook
npx storybook@latest init

# Starts Storybook in development mode
yarn storybook

您应该看到这个

Initial Storybook UI

不错,我们已经设置了一个组件浏览器!

每次您将 Storybook 安装到应用程序中时,它都会在 stories 文件夹中添加一些示例。如果您愿意,可以花一些时间探索它们。但我们的设计系统不需要它们,因此可以安全地删除 stories 目录。

现在您的 Storybook 应该看起来像这样(请注意,字体样式有点偏差,例如,请参阅“Avatar: Initials” story)

添加全局样式

我们的设计系统需要将一些全局样式(CSS reset)应用于文档,以正确渲染我们的组件。我们可以使用 Emotion 的 global style prop 轻松添加它们。将您的 src/shared/global.js 文件更新为以下内容

复制
src/shared/global.js
import { css } from '@emotion/react';

import { color, typography } from './styles';

+ export const fontUrl = 'https://fonts.googleapis.com/css?family=Nunito+Sans:400,700,800,900';

export const bodyStyles = css`
  /* Same as before */
`;

export const GlobalStyle = css`
  body {
    ${bodyStyles}
  }
`;

要在 Storybook 中使用 Global “组件”,我们可以使用 decorator(组件包装器)。在应用程序中,我们会将该组件放置在顶层应用程序布局中,但在 Storybook 中,我们使用预览配置文件 .storybook/preview.js 包装所有 stories。将文件重命名为 .storybook/preview.jsx 并将其更新为以下内容

复制
.storybook/preview.jsx
+ import { Global } from '@emotion/react';

+ import { GlobalStyle } from '../src/shared/global';

/** @type { import('@storybook/react').Preview } */
const preview = {
+ decorators: [
+   (Story) => (
+     <>
+       <Global styles={GlobalStyle} />
+       <Story />
+     </>
+   ),
+ ],
  parameters: {
    actions: { argTypesRegex: '^on[A-Z].*' },
    controls: {
      matchers: {
        color: /(background|color)$/i,
        date: /Date$/,
      },
    },
  },
};

export default preview;
💡 decorator 中的 <> 不是错别字,它是一个 React Fragment,我们在此处使用它以避免向输出添加不必要的额外 HTML 标签。

decorator 确保无论选择哪个 story,GlobalStyle 都会渲染。

Storybook with global styles loaded

使用插件增强 Storybook 功能

Storybook 包含一个由庞大社区创建的强大的 插件生态系统。对于务实的开发者来说,使用生态系统构建我们的工作流程比自己创建自定义工具(这可能很耗时)更容易。

Actions 插件用于验证交互性

actions 插件 在 Storybook 中,当对 Button 或 Link 等交互元素执行操作时,为您提供 UI 反馈。Actions 默认安装在 Storybook 中,您只需将“action”作为回调 prop 传递给组件即可使用它。

让我们看看如何在我们的 Button 元素中使用它,该元素可以选择性地接受一个包装器组件来响应点击。我们有一个 story 将 action 传递给该包装器

复制
src/Button/Button.stories.jsx
import styled from '@emotion/styled';

import { Button } from './Button';

import { Icon } from '../Icon/Icon';

import { StoryLinkWrapper } from '../LinkWrapper';

// When the user clicks a button, it will trigger the `action()`,
// ultimately showing up in Storybook's addon panel.
function ButtonWrapper(props) {
  return <CustomButton {...props} />;
}

export const buttonWrapper = {
  name: 'button wrapper',
  render: () => (
    <div>
      <ButtonWrapper>Original Button Wrapper</ButtonWrapper>
      <br />
      <Button ButtonWrapper={ButtonWrapper} appearance='primary'>
        Primary
      </Button>
      /* Removed for brevity */
    </div>
  ),
};

Controls 用于压力测试组件

全新安装的 Storybook 包含 Controls 插件,该插件已开箱即用配置完成。

它允许您在 Storybook UI 中动态地与组件输入 (props) 交互。您可以通过 arguments(或简称为 args)向组件 prop 提供多个值,并通过 UI 调整它们。它帮助设计系统创建者通过调整参数值来压力测试组件输入 (props)。它还使设计系统消费者能够在集成组件之前尝试组件,以了解每个输入 (prop) 如何影响它们。

让我们通过在 Avatar 组件(位于 src/Avatar/Avatar.stories.jsx 中)中添加一个新的 story 来看看它们是如何工作的

复制
src/Avatar/Avatar.stories.jsx
import { Avatar } from './Avatar';

export default {
  title: 'Design System/Avatar',
  component: Avatar,
  /*
   * More on Storybook argTypes at:
   * https://storybook.org.cn/docs/react/api/argtypes
   */
  argTypes: {
    size: {
      control: {
        type: 'select',
      },
      options: ['tiny', 'small', 'medium', 'large'],
    },
  },
};

// Other Avatar stories

/*
 * New story using Controls
 * Read more about Storybook templates at:
 * https://storybook.org.cn/docs/react/writing-stories/introduction#using-args
 */
export const Controls = {
  args: {
    loading: false,
    size: 'tiny',
    username: 'Dominic Nguyen',
    src: 'https://avatars.githubusercontent.com/u/263385',
  },
};

请注意插件面板中的“Controls”选项卡。Controls 自动生成图形 UI 以调整 props。例如,“size”选择元素允许我们循环浏览支持的 Avatar 尺寸 tinysmallmediumlarge。同样的方法也应用于其余组件的 props(“loading”、“username”和“src”),从而使我们能够创建一种用户友好的方式来压力测试组件。

话虽如此,Controls 不能取代 stories。它们非常适合探索组件的边缘情况,而 stories 则用于展示假定的状态。

我们将在后面的章节中介绍 Accessibility 和 Docs 插件。

“Storybook 是一个强大的前端工作坊环境工具,它使团队能够设计、构建和组织 UI 组件(甚至包括全屏!),而不会被业务逻辑和底层细节所困扰。” – Brad Frost,《Atomic Design》作者

了解如何自动化维护

现在我们的设计系统组件已在 Storybook 中,我们已经向创建行业标准设计系统迈出了一步。现在是将我们的工作提交到远程仓库的绝佳时机。然后我们可以开始考虑如何设置自动化工具,以简化持续维护。

设计系统与所有软件一样,应该不断发展。挑战在于确保 UI 组件随着设计系统的增长继续保持预期的外观和感觉。

在第 4 章中,我们将学习如何设置持续集成并自动在线发布设计系统以进行协作。

使您的代码与本章保持同步。在 GitHub 上查看 c5f4c8d。
这个免费指南对您有帮助吗?发推文以表示赞赏并帮助其他开发者找到它。
下一章
评审
通过持续集成和视觉评审进行协作
✍️ 在 GitHub 上编辑 – 欢迎提交 PR!
加入社区
6,721位开发者及更多
为什么为什么选择 Storybook组件驱动的 UI
开源软件
Storybook - Storybook 中文

特别感谢 Netlify CircleCI