加入直播会话:东部夏令时周四上午 11 点,Storybook 9 版本发布与 AMA

Storybook Addon SDC

将 Drupal 单一目录组件 (SDC) 用作 Storybook 故事

在 Github 上查看

Storybook SDC 插件

此插件简化了将 Drupal 单一目录组件 (SDC) 集成到 Storybook 的过程,允许将 YAML 配置的组件(例如 *.component.yml)动态加载为 Storybook 中的故事。

Demo GIF

目录


概述

这个 Storybook 插件使得使用 YAML 配置和 Twig 模板轻松地将 Drupal 单一目录组件 (SDC) 集成到 Storybook 中。它动态加载组件,让您无需太多配置即可快速创建和管理故事。

它仍然是常规的 Storybook,但现在增加了导入和管理 Drupal 单一目录组件 (SDC) 的选项。

Storybook 实时示例

您可以查看一个Storybook 中 SDC 插件的实时示例,该示例托管在 GitHub Pages 上,展示了该仓库中 /components 目录下的组件。

插件特性

SDC Storybook 插件简化了将 Drupal 单一目录组件 (SDC) 集成到 Storybook 的过程,并提供以下几个主要特性:

  • Vite 插件集成:利用 vite-plugin-twig-drupal 插件无缝加载和处理 SDC 组件中使用的 Twig 模板。
  • 动态路径解析:利用命名空间动态发现项目结构中的组件,无需手动配置。
  • 故事生成:根据 SDC 组件的 YAML 配置自动创建故事,简化故事创建过程。
  • JSON Schema 支持:支持 props 和 slots 的 JSON Schema,能够为缺失值生成模拟数据并确保数据一致性。
  • 嵌入 Drupal 行为:允许您将 Drupal.attachBehaviors() 等 Drupal 行为直接嵌入到 Storybook 预览中,确保组件行为与其在 Drupal 中一致。
  • 自定义和外部 Schema 定义:支持自定义和外部 JSON schema 定义,用于根据 Drupal 特定配置(例如 UI 模式、Experience Builder)验证组件。

为何选择 SDC Storybook 而非其他替代方案?

虽然 SDC StyleguideDrupal Storybook 等解决方案很有价值,但 SDC Storybook 插件提供了明显的优势:

1. 组件独立性和模块化

  • 遵循 BEM(块、元素、修饰符)方法论,组件应能在不同环境中独立工作。
  • 组件的功能不应依赖于 Drupal 版本或当前激活的 Drupal 主题——它应该能移植到任何系统。

2. 无需复杂的 Drupal 设置

  • 进行组件开发无需安装或配置 Drupal 依赖项。
  • 在 Storybook 中开发前端组件,无需运行繁重的 Drupal 实例,从而提高开发效率。

3. 简化 DevOps 和 CI/CD 流水线

  • 由于组件是独立的,测试和部署变得更简单。
  • 您可以在 CI 流水线中避免使用 Drupal 特定配置,从而实现更高效和易于维护的工作流程。

4. 结合 Faker.js 和 JSON Schema 提高可伸缩性和灵活性

  • Faker.js 这样的工具允许您为组件生成测试数据,而无需真实的网站内容。
  • JSON Schema 清晰且一致地定义组件数据,有助于维护数据完整性。

5. 前端开发的行业标准工具

  • Storybook 在前端开发中被广泛采用,这使得新开发者入职更容易,即使他们不熟悉 Drupal。
  • JSON Schema 使得即使没有深入的 Drupal 知识也能进行组件开发,将项目开放给更广泛的开发者群体。

6. 组件中嵌入 Drupal 特定行为

  • Drupal 行为(例如 Drupal.attachBehaviors())直接嵌入 Storybook 预览中,确保 Storybook 和生产环境中的组件行为一致。
  • 支持 drupalSettingsonce.js,使得 Storybook 中的组件行为与其在 Drupal 中完全一致。

7. Twig.js 与 Drupal Twig 的对比

虽然使用 Drupal 渲染组件提供了更紧密的集成,但在许多场景下继续使用 Twig.js 具有充分的理由:

  • 许多组件不需要完整的 Drupal 逻辑。基本组件(按钮、卡片、列表)依赖于简单的 HTML 和 CSS,而非复杂的模板逻辑。对于这类组件,Twig.js 提供足够的渲染能力,无需完整的 Drupal 预处理。
  • Twig.js 非常适用于以前端为中心的用例。
  • 样式和行为不一致问题可以在 Drupal 实现阶段单独管理。

快速入门指南

  1. 在主题或模块目录中,或者只是一个空目录中(如果 package.json 尚不存在):

    npm init
    echo "node_modules/" >> .gitignore
    
  2. 安装依赖项:

    npm i vite twig storybook-addon-sdc --save-dev
    
  3. 初始化 Storybook:

    npx storybook@latest init --builder vite --type html --no-dev
    
  4. 移除默认的 Storybook 样板故事(可选):

    rm -rf ./stories
    
  5. 按照配置中的说明进行配置.

  6. 将组件添加到 components 目录(或者从这个仓库复制)。

  7. 在 package.json 中设置 type: module

    {
      "type": "module"
    }
    
  8. 启动 Storybook:

    npm run storybook
    

配置

要配置插件,请更新 .storybook/main.js,如下所示:

import { join } from 'node:path' // 1. Add dependencies.
import { cwd } from 'node:process'

const config = {
  stories: ['../components/**/*.component.yml'], // 2. Set components glob.
  addons: [
    {
      name: 'storybook-addon-sdc', // 3. Configure addon.
      options: {
        sdcStorybookOptions: {
          namespace: 'umami', // Your namespace.
        },
        vitePluginTwigDrupalOptions: {
          // vite-plugin-twig-drupal options.
          namespaces: {
            umami: join(cwd(), './components'), // Your namespace and path to components.
          },
        },
        jsonSchemaFakerOptions: {}, // json-schema-faker options.
      },
    },
    // Any other addons.
    '@storybook/addon-essentials',
    '@chromatic-com/storybook',
    '@storybook/addon-interactions',
  ],
  framework: {
    name: '@storybook/html-vite',
    options: {},
  },
}
export default config

设置默认值

为了让 json-schema-faker 生成可靠数据,请在 SDC schema 中使用 defaultexamples

props:
  type: object
  properties:
    html_tag:
      type: string
      enum:
        - article
        - div
      default: article
slots:
  content:
    title: Content
    examples:
      - Hello! I'm card content

请参阅

创建实验性故事

SDC YAML 文件中的 sdcStorybook 配置提供了一种灵活的方式来为组件定义自定义故事。此功能允许您使用预定义 props、自定义 slots,甚至重用在其他地方定义的故事。其工作原理如下:

配置示例

thirdPartySettings:
  sdcStorybook:
    stories:
      grid:
        props:
          label: Paragraph with grid
          extra_classes:
            - m-paragraph--grid
        slots:
          content:
            # 1. Basic Props and Slots
            # This card uses only the basic default props and slots defined in the component YAML.
            - type: component
              component: 'umami:card'

            # 2. Predefined Story
            # This card references an existing story (e.g., "Preview")
            # from the component YAML, which includes predefined props and slots.
            - type: component
              component: 'umami:card'
              story: Preview

            # 3. Custom Props and Slots
            # This card defines custom props to modify its behavior (e.g., setting
            # the HTML tag to 'div') and custom slots to override specific content.
            - type: component
              component: 'umami:card'
              props:
                html_tag: 'div' # Custom HTML tag for the card container
              slots:
                content: 'Hello from third grid card!'

实际工作原理

插件会根据定义动态渲染组件和故事:

  • 基本 Args: 使用 umami:card 组件的默认 Basic.args
  • 现有故事: 加载 Preview 故事,确保 Storybook 环境中的一致性。
  • 自定义 Slots 和 Props: 用该实例的独特内容覆盖默认 slots 和 props 行为。

Stories

为何故事是实验性的?

社区需要决定 YAML 故事应采用何种格式。

常规 Storybook

所有 Storybook 功能照常工作,您可以将 SDC YAML 导入到 .stories.js 中。

示例

import header, {
  Preview as HeaderPreview,
} from '../components/header/header.component.yml'
import banner, {
  Preview as BannerPreview,
} from '../components/banner/banner.component.yml'

export default {
  title: 'Regular Storybook Page',
  render: () => {
    return `
      ${header.component({ ...HeaderPreview.args })}
      ${banner.component({ ...BannerPreview.args })}
    `
  },
  play: async ({ canvasElement }) => {
    Drupal.attachBehaviors(canvasElement, window.drupalSettings)
  },
}

export const Basic = {}

配置选项

除了标准配置选项外,您还可以指定 customDefs 和 externalDefs 来提供额外的 schema 定义。这些选项是可选的,可用于扩展或覆盖默认定义。

customDefs

customDefs 选项允许您直接在配置中定义自定义 schema 定义。这可以是一个包含自定义定义的对象。

示例

const options = {
  sdcStorybookOptions: {
    customDefs: {
      'json-schema-definitions://experience_builder.module/column-width': {
        title: 'Column Width',
        type: 'integer',
        enum: [25, 33, 50],
      },
    },
  },
}

externalDefs

externalDefs 选项允许您指定一个外部定义文件的路径数组。这些路径可以是 CDN 托管文件的 URL 或本地文件路径。

示例

const options = {
  sdcStorybookOptions: {
    externalDefs: [
      'https://cdn.jsdelivr.net.cn/gh/iberdinsky-skilld/sdc-addon@v0.4.3/drupal-defs/uiPatternsSchema.yml',
      'https://example.com/path/to/definitions.yml',
      './local/path/to/definitions.yml',
    ],
  },
}

使用 externalDefs 时,定义将自动获取并注册。

validate

validate 选项使用 JSON Schema 验证器为 SDC 组件启用 schema 验证。默认情况下,验证器会对照位于以下位置的全局 schema 检查组件配置:

$schema: https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json

工作原理

  • 全局 Schema 验证(默认): 插件使用默认的全局 schema 进行验证。此 schema 由 Drupal 提供,确保 SDC 组件符合预期的结构以及正确的数据类型和属性。

  • 自定义组件 Schema: 如果某个特定的 SDC 组件包含指向自定义 schema 的 $schema 字段,则验证器将使用该 schema 进行验证,而非全局 schema。这提供了更大的灵活性和组件特定的验证能力,特别是在组件有自定义要求时。

  • 验证警告: 验证错误或警告将记录到控制台,帮助开发者识别组件配置中的任何问题。注意: 验证不会中断组件的渲染。即使发生验证错误,组件仍会显示在 Storybook 中,并且警告将被记录供查看。

要启用验证,请设置 validate: schema 的 URL

const config = {
  stories: ['../components/**/*.component.yml'],
  addons: [
    {
      name: 'storybook-addon-sdc',
      options: {
        sdcStorybookOptions: {
          validate:
            'https://git.drupalcode.org/project/drupal/-/raw/HEAD/core/assets/schemas/v1/metadata.schema.json',
        },
      },
    },
  ],
}

依赖项

已知问题

UI 模式

作者:
  • finnsky
    finnsky
支持
    HTML
标签