发布于 2026-01-06 0 阅读
0

使用 Storybook、Tailwind 和 Typescript 创建组件库。

使用 Storybook、Tailwind 和 Typescript 创建组件库。

更快地为你的 React 项目构建组件。
看看最终效果。

什么是故事书?

Storybook 是一个用于独立开发 UI 组件的工具,这意味着我们可以将这些组件放在主应用程序之外,进行必要的更改,然后将它们导入到我们的应用程序中,并知道它们的外观。

设计系统已成为产品开发流程的重要组成部分,您很可能已经在使用某种设计系统。该系统为设计师和开发人员提供风格指南。您可能有很多具有不同模式和变体的 UI 组件,而 Storybook 正是解决此类问题的理想选择。

Tailwind的优势

Tailwind CSS 是一个高度可定制的底层 CSS 框架。它不像许多其他框架那样是一个 UI 工具包,而是让你完全通过 CSS 类来控制网站的外观。


搭建一个 React 应用并安装 Tailwind。

我将从零开始创建一个项目create-react-appp

npx create-react-app storybook-ts --template typescript
Enter fullscreen mode Exit fullscreen mode

让我们安装依赖项。

npm install tailwindcss postcss-cli autoprefixer
Enter fullscreen mode Exit fullscreen mode

postcss.config.js在应用程序根目录下创建一个名为 `.htm` 的新文件,并添加以下代码。

module.exports = {
  plugins: [require('tailwindcss'), require('autoprefixer')],
};
Enter fullscreen mode Exit fullscreen mode

我们将进行处理tailwindpostcssautoprefixer解析 CSS 并添加浏览器支持的厂商前缀。

现在将此脚本添加到package.json文件中。

{
    "scripts": {
        ...
    "build:tailwind": "postcss src/scss/base.scss -o src/scss/tailwind.scss"
  },
  ...
}
Enter fullscreen mode Exit fullscreen mode

scss在内部创建一个新文件夹src。我将使用 sass 文件,因为我将用它base.scss来编写更多类,但您也可以使用其他格式的文件css

如果你决定使用 sass,别忘了安装node-sass

base.scss在文件夹内创建一个文件scss,内容如下。

@tailwind base;
@tailwind components;
@tailwind utilities;
Enter fullscreen mode Exit fullscreen mode

在控制台上运行此命令,即可生成 Tailwind 文件。

npm run build:tailwind
Enter fullscreen mode Exit fullscreen mode

将生成的 Tailwind 文件放入您的 App 组件中。

// App.tsx

import './scss/tailwind.scss';
Enter fullscreen mode Exit fullscreen mode

本教程将使用 Tailwind 的默认配置,您可以根据需要进行调整。运行此命令npx tailwind init将生成一个 Tailwind 配置文件,您可以添加更适合您的值。这是 Tailwind 的默认配置,仅供参考。

components在文件夹内创建一个新文件夹src,并添加一个button.tsx文件。

import React, { FC } from 'react';

type ButtonTypes = {
  /**
   * Label of the button
  */
  label: string;
  /**
   * Boolean value to define the button style 
  */
  outlined?: boolean;
  /**
   * Button click action
  */
  onClick(): void;
}

const BASE_BUTTON = 'rounded outline-none shadow py-3 px-12 font-normal uppercase tracking-wider text-lg'
const CONTAINED_BUTTON = `${BASE_BUTTON} bg-teal-400 border border-teal-400 text-white`
const OUTLINED_BUTTON = `${BASE_BUTTON} border border-teal-400 text-teal-400`

export const Button:FC<ButtonTypes> = ({ onClick, label = "Some label", outlined }) => {
  return (
    <button
      onClick={onClick}
      className={outlined ? OUTLINED_BUTTON : CONTAINED_BUTTON}
    >
      <span>{label}</span>
    </button>
  )
};
Enter fullscreen mode Exit fullscreen mode

让我们一起深入故事书吧!

为了使用 Storybook 处理 TypeScript 文件,我们需要扩展 webpack 配置。让我们在项目根目录下创建一个名为 `<path>` 的新文件夹.storybook,并在其中创建一个main.js文件。

但首先,让我们安装所需的依赖项。

npm install --save-dev @storybook/react @storybook/preset-create-react-app babel-loader react-docgen-typescript-loader @storybook/addon-actions @storybook/addon-info @storybook/addon-knobs @storybook/addon-notes @storybook/addons
Enter fullscreen mode Exit fullscreen mode

我们将使用插件为我们的故事启用高级功能。

main.js文件中添加以下代码。

module.exports = {
  stories: ['../src/stories/**/*.stories.tsx'],
  addons: [
    '@storybook/addon-actions/register',
    '@storybook/addon-knobs/register',
    '@storybook/addon-notes/register',
  ],
  webpackFinal: async config => {
    config.module.rules = [
      ...config.module.rules,
      {
        test: /\.(ts|tsx)$/,
        use: [
          {
            loader: require.resolve("babel-loader"),
            options: {
              presets: [require.resolve("babel-preset-react-app")]
            }
          },
          require.resolve("react-docgen-typescript-loader")
        ]
      }
    ],
    config.resolve.extensions.push('.ts', '.tsx');
    return config;
  },
};
Enter fullscreen mode Exit fullscreen mode

让我们来创作我们的第一个故事。

stories在 `<path>` 内创建一个文件夹src,并在其中创建一个名为 `<filename>` 的文件button.stories.tsx。我们将添加一些插件,以便直接从 Storybook 更改按钮的属性。

import React from "react";
import { Button } from '../components/button';
import { action } from '@storybook/addon-actions';
import { withKnobs, text, boolean } from "@storybook/addon-knobs";

export default {
  title: "Button",
  decorators: [withKnobs]
};

export const primary = () => {
  const label = text("Label", "See now");
  const outlined = boolean("Oultined", false);
  return (
    <Button onClick={action('clicked')} outlined={outlined} label={label} />
  )
};
Enter fullscreen mode Exit fullscreen mode

让我们在package.json文件中添加一个脚本来运行 Storybook。

{
    "scripts": {
        ...
    "build:tailwind": "postcss src/scss/base.scss -o src/scss/tailwind.scss",
    "storybook": "start-storybook -p 5000"
  },
  ...
}
Enter fullscreen mode Exit fullscreen mode

现在如果我们运行程序,npm run storybook就会看到类似这样的内容。

故事书

这是我们的按钮!但是没有样式。我们来创建一个新Layout组件来解决这个问题。从现在开始,我们创建的所有文件都将放在.storybook这个文件夹里。

import React from 'react';
import '../src/scss/tailwind.scss';

const Layout = ({ children }) => {
  return (
    <div className="px-20 py-10">
      {children}
    </div>
  )
}

export default Layout;
Enter fullscreen mode Exit fullscreen mode

创建preview.js文件。

import React from 'react';
import { addDecorator } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
import Layout from './Layout';

addDecorator(storyFn => <Layout>{storyFn()}</Layout>);
addDecorator(withInfo({
  inline: true,
  propTablesExclude: [Layout]
}));
Enter fullscreen mode Exit fullscreen mode

如果再次运行 Storybook,我们的故事现在看起来会是这样。信息插件会生成源代码和一个属性类型表。

故事书

备注

  • 如果导入 Tailwind 文件时遇到问题,需要sass-loader在 webpack 配置中添加一个main.js

  • 如果你看不到任何 proptypes,请检查你的组件文件。确保解构 React 导入,或者像这样导入 React。或者尝试不要export default在你的组件中使用 React。

  import * as React from 'react'; 

  import React, { FC } from 'react';

  export const Button = () => {} //don't use export default.
Enter fullscreen mode Exit fullscreen mode

深色模式。

我们的应用看起来很棒,但你知道怎样才能让它看起来更好吗?没错,使用深色模式。

首先,创建一个manager.js文件并添加以下代码。

import { addons } from '@storybook/addons';
import { themes } from '@storybook/theming';

addons.setConfig({
  theme: themes.dark,
});
Enter fullscreen mode Exit fullscreen mode

这将为您的故事书应用添加深色主题。

在前一个preview.js文件中,添加此代码以更改信息的样式。

import React from 'react';
import { addDecorator } from '@storybook/react';
import { withInfo } from '@storybook/addon-info';
import Layout from './Layout';

addDecorator(storyFn => <Layout>{storyFn()}</Layout>);
addDecorator(withInfo({
  inline: true,
  styles: (base) => ({
    ...base,
    infoBody: {
      ...base.infoBody,
      backgroundColor: '#303030',
      color: 'white',
    },
    source: {
      h1: {
        margin: '20px 0',
        padding: '0 0 5px 0',
        fontSize: '25px',
        borderBottom: '1px solid #EEE',
      },
    },
  }),
  propTablesExclude: [Layout]
}));
Enter fullscreen mode Exit fullscreen mode

我们几乎完成了。但是现在属性类型表格中的文本看起来不太好。

故事书

创建一个preview-body.html并添加这段代码。

<style>
  .info-table, .info-table td, .info-table th{ 
    color: #fff;
  }
</style>
Enter fullscreen mode Exit fullscreen mode

再运行一遍故事书。

现在,Storybook 已经可以在深色模式下运行,并支持 Tailwind 组件和 TypeScript。

请查看此仓库中的代码

文章来源:https://dev.to/elisealcala/start-a-component-library-with-storybook-tailwind-and-typescript-2ofa