Nango 设计系统(@nangohq/design-system)深度指南:设计 Token、Storybook 与 React 组件实战 📅 发布时间:2026/9/15 22:16:39 👁 浏览次数: Nango 设计系统nangohq/design-system深度指南设计 Token、Storybook 与 React 组件实战【免费下载链接】nangoBuild product integrations with AI.项目地址: https://gitcode.com/GitHub_Trending/na/nango导读本文以 Nango 开源仓库中的packages/design-system包为核心系统讲解这套共享设计系统的三大支柱设计 Token 流水线Figma → Tokens Studio → Style Dictionary → CSS 变量 → Tailwind v4 工具类、Storybook 组件工作台含 MCP 服务与无障碍审计以及React 组件库Radix UI CVA tailwind-merge 模式。读完本文你将掌握如何在本地启动 Storybook、如何同步并重建设计 Token、如何按约定新增一个组件变体或新组件以及这套流水线在 Nango Web 应用中的消费方式。本文所有路径均以仓库根目录为基准涉及的核心文件见 packages/design-system/README.md。一、包结构与定位nangohq/design-system是 Nango 应用packages/webapp共享的前端设计系统涵盖三部分内容设计 Tokendesign tokens由 Figma 中的 Tokens Studio 插件创作编译为 CSS 自定义属性custom propertiesReact 组件按需添加、开箱即用的 UI 组件Storybook承载上述 token 与组件的“活样式指南”living style guide。包的导出配置定义在 packages/design-system/package.json主入口与 token CSS 通过exports字段暴露exports: { .: { import: ./src/index.ts, types: ./src/index.ts }, ./tokens/tokens.generated.css: ./tokens/tokens.generated.css }包名对外暴露两样东西组件从src/index.ts这个 barrel 文件导出和编译好的 token CSS。所有公开导出集中在 packages/design-system/src/index.ts包括Button、IconButton、buttonVariants、Alert、Badge、Dialog、Field、Input、InputGroup、Textarea、Tooltip、Card等组件及其variants对象以及供消费方复用的dsTwMergeConfig。从源码结构看组件全部平铺在src/components/ui/目录下shadcn 惯例配合同名的*.stories.tsx故事文件src/lib/cn.ts提供类名合并工具tokens/目录存放 token 的“双源文件”。二、Storybook本地运行、主题切换与无障碍审计Storybook 是这套设计系统的活样式指南可在本地启动后浏览 token 与组件在亮色/暗色两种主题下的表现。2.1 启动方式# 从仓库根目录 npm run storybook # 或者直接在包目录内 cd packages/design-system npm run storybook启动后访问http://localhost:6006。点击右上角的Themes工具栏按钮即可在亮色与暗色主题之间切换。注意storybook脚本使用NODE_PATH./node_modules来规避 Vite 7 的 CJS 模块解析问题脚本定义见 packages/design-system/package.json。该设置安全无害应予以保留不要移除。仓库还提供了静态构建命令npm run build-storybook对应build-storybook脚本。与storybook dev不同的是build-storybook会急切eagerly转换每一个故事因此任何损坏的 import 都会导致构建失败——这在 dev server 下可能不会被加载到。AGENTS.md建议当某个故事的 import 发生变化时推送前先在本地运行npm run -w nangohq/design-system build-storybook验证。2.2 Storybook MCP让 AI 助手直接读懂组件库Storybook 自带 MCP 服务器storybook/addon-mcp见 package.json 的 devDependencies把故事的文档暴露给 AI 助手。这样可以让 Claude 在充分了解现有 stories、props 与用法示例的前提下构建或修改组件无需手动复制粘贴文档。MCP 服务默认关闭以避免未运行 Storybook 的工程师遇到连接错误。需要启用时在仓库根目录执行一次claude mcp add --transport http storybook http://localhost:6006/mcp该命令把配置写入.claude/settings.local.json已被 gitignore。然后启动 Storybooknpm run storybook并重载 Claude Code下面的工具就会自动可用工具作用list-all-documentation列出所有 story ID 与组件名get-documentation返回某个组件的 props、变体与用法preview-stories渲染一个 story 并返回预览 URL2.3 无障碍Accessibility审计storybook/addon-a11y会对每一个 story运行基于 axe-core 的自动化无障碍审计依赖版本axe-core 4.12.0记录在 packages/design-system/package.json。打开 Storybook UI 底部的Accessibility面板即可看到当前渲染 story 的违规项violations、未完成检查incomplete与通过规则passing。组件发布前应修复所有违规项。三、设计 Token从 Figma 到 CSS 变量再到 Tailwind 工具类3.1 创作与同步链路设计 Token 在 Figma 中通过 Tokens Studio 插件创作随后编译为 CSS 自定义属性。Tokens Studio 配置了GitHub sync指向本仓库的design/tokens分支——这意味着设计师可以直接从 Figma 插件推送 token 变更任何连接到同一 sync 配置的 Figma 文件都共享同一套 token。3.2 目录结构packages/design-system/ tokens/ tokens.json Tokens Studio 导出事实源提交到 git tokens.generated.css 生成的 CSS 自定义属性提交到 git scripts/ tokens-fetch.mjs token 流水线脚本tokens.json是 Tokens Studio 的原始导出tokens.generated.css是编译产物。两者都提交到 git。除 README 中列出的结构外实际目录中还包含tokens/types.ts与tokens/stories/ColorPalette.stories.tsx、Typography.stories.tsx用于在 Storybook 中可视化展示色板与字体scripts/tokens-check-removed.mjs对应npm run tokens:check用于检查 token 是否被移除。3.3 同步工作流Designer → Code设计师 → 代码在 Figma 中通过 Tokens Studio 插件编辑 token推送到design/tokens分支插件 Settings → Sync provider → GitHub通知开发者运行npm run tokens:fetch。开发者拉取最新 tokencd packages/design-system npm run tokens:fetch git add tokens/ git commit -m chore(design-system): update tokens仅重建 CSS、不拉取例如解决了tokens.json的合并冲突之后npm run tokens:build这两个命令对应 packages/design-system/package.json 中的脚本tokens:fetch: node scripts/tokens-fetch.mjs, tokens:build: node scripts/tokens-fetch.mjs --build-only, tokens:check: node scripts/tokens-check-removed.mjs3.4 流水线底层实现源码解读packages/design-system/scripts/tokens-fetch.mjs 是整个 token 流水线的核心它用 Style Dictionary v5style-dictionary 5.4.4配合tokens-studio/sd-transforms完成编译。几个关键实现细节值得注意拉取来源tokens:fetch直接从 GitHub raw 地址https://raw.githubusercontent.com/NangoHQ/nango/design/tokens/packages/design-system/tokens/tokens.json拉取最新tokens.json--build-only模式tokens:build从本地已有的tokens.json读取不访问网络若tokens.json不存在会直接报错并提示先运行tokens:fetch--strict模式脚本支持--strict参数遇到未解析的 token 别名SD 会保留为原始{alias}字符串时直接抛错而不是静默跳过避免产出无效 CSSboxShadow 序列化SD v5 的 DTCG token 把处理后的值放在$value中内置css/variables格式对 boxShadow 数组会退化为[object Object]因此脚本自定义了formatTokenValue把innerShadow/outerShadow的x/y/blur/spread/color逐项拼成 CSSbox-shadow字符串原子化写入脚本先构建 CSS若 Style Dictionary 抛错则保持磁盘上的tokens.json原封不动保证工作区始终处于“旧 tokens.json 旧 tokens.generated.css”的一致状态。从脚本的PRIM_MAPPINGS常量可以看出原始 token 到 Tailwind 命名空间的映射策略这也是生成 CSS 中各类工具类的前缀来源原始 token 前缀CSS 变量Tailwind 工具类radius---ds-radius-*rounded-ds-*border-width---ds-border-width-*border-ds-*typography-font-size---ds-typography-font-size-*text-ds-*typography-font-weight---ds-typography-font-weight-*font-ds-*typography-line-height---ds-typography-line-height-*leading-ds-*typography-letter-spacing---ds-typography-letter-spacing-*tracking-ds-*间距spacing被刻意排除在映射之外Tailwind 默认的 4px 间距刻度与--ds-space-*token 完全一致所以gap-2就等于--ds-space-28px无需额外注册。3.5 权威方向Canonical directionToken 变更应当始终发源于 Figma——设计师是事实源的拥有者。直接编辑tokens.json并推送到design/tokens在技术上可行GitHub sync 是双向的但这不是预期工作流且存在与 Figma 文件产生分叉的风险。3.6 生成的 CSS 结构tokens.generated.css由五段内容组成真实文件见 packages/design-system/tokens/tokens.generated.css/* Primitives — --ds- 前缀原始刻度值 */ :root { --ds-color-neutral-50: #f9fafb; --ds-radius-sm: 4px; --ds-typography-font-size-md: 14px; ... } /* Semantic tokens — light (默认) */ :root { --surface-canvas: #f9fafb; --text-strong: #111827; ... } /* Semantic tokens — dark */ [data-themedark] { --surface-canvas: #0f172a; --text-strong: #f8fafc; ... } /* Tailwind theme — 语义 token → bg-*、text-*、border-*、shadow-* 工具类 */ theme { --color-surface-canvas: var(--surface-canvas); --shadow-focus-outline-default: var(--focus-outline-default); ... } /* Tailwind theme — 原始 token → rounded-ds-*、text-ds-*、font-ds-* 等 */ theme { --radius-ds-sm: var(--ds-radius-sm); --text-ds-md: var(--ds-typography-font-size-md); --font-weight-ds-medium: var(--ds-typography-font-weight-medium); ... }对照真实文件可以看到完整的分层原始 token 段--ds-*前缀包含颜色neutral/brand/info/success/warning/danger 全色阶、alpha 透明度、icon stroke、间距、圆角、边框宽度、排版、动效时长与缓动曲线、阴影、透明度、模糊、布局断点等语义 token 段按 light:root与 dark[data-themedark]分别定义--icon-*、--surface-*、--text-*、--border-*、--interactive-*、--status-*、--chart-*、--focus-ring-*等随后是theme注册段与.type-*复合排版类例如.type-heading-lg一次性设置 font-family、font-size、font-weight、line-height、letter-spacing。关于 boxShadow 的注册有一个细节语义阴影 token 使用theme inline注册使生成的工具类直接引用语义变量如var(--focus-outline-default)而不是经过中间--shadow-*CSS 属性从而保证暗色主题对底层语义变量的覆盖始终生效。3.7 Token 命名与工具类映射TokenCSS 变量Tailwind 工具类Primitives.color.neutral.50--ds-color-neutral-50—Primitives.radius.sm--ds-radius-smrounded-ds-smPrimitives.typography.font-size.md--ds-typography-font-size-mdtext-ds-mdPrimitives.typography.font-weight.medium--ds-typography-font-weight-mediumfont-ds-mediumSemantic/Light.surface.canvas--surface-canvasbg-surface-canvasSemantic/Light.text.strong--text-strongtext-text-strongSemantic/Light.focus-outline-default--focus-outline-defaultshadow-focus-outline-default原始颜色 token--ds-color-*被刻意排除在theme之外目的是强制组件只使用语义 token而原始尺寸/排版 token 则以ds-前缀进入theme使它们可以作为普通工具类使用无需[var(...)]这种任意值写法。3.8 在 webapp 中消费packages/webapp/src/index.css通过包名直接引入生成的 CSSimport nangohq/design-system/tokens/tokens.generated.css;同时 packages/webapp/package.json 以nangohq/design-system: file:../design-system的形式本地引用该包。搜索packages/webapp可以看到大量组件消费示例providers.tsx引入TooltipProvidercomponents/patterns/下的CriticalErrorAlert.tsx、DestructiveActionModal.tsx、SecretInput.tsx、ScopesInput.tsx、EditableInput.tsx、FilterMultiSelect.tsx、KeyValueInput.tsx、PeriodSelector.tsx、ConditionalTooltip.tsx等模式组件都从nangohq/design-system导入Button、IconButton、Badge、Alert、InputGroup、Tooltip等。四、组件按需添加遵循统一模式组件按需添加——只有当产品页面真正需要时才新增不做投机性添加AGENTS.md中明确写明。添加新组件的完整指南见 packages/design-system/AGENTS.md。4.1 消费方式与约束import { Button, IconButton, buttonVariants } from nangohq/design-system;消费者还必须在应用根部导入一次 token CSS见 3.8 节。组件只使用语义 CSS 变量——不允许出现裸 hex 色值、硬编码尺寸或硬编码间距。消费方应用不能直接给组件套className/style做外观定制有 lint 规则拦截因此当某个页面需要现有 props/变体覆盖不到的外观时修复点就在本包内新增或扩展一个变体。动手前应先与设计师确认该变体确实缺失并在Figma 设计系统中同步添加对应变体保持代码与设计一致详见stories/StylingAndCustomization.mdx。4.2 以 Button 为参照的组件模式packages/design-system/src/components/ui/button.tsx 是仓库中的参照实现完整展示了这套模式导出cva变体对象供消费者组合复用buttonVariants导出 props 接口继承React.HTMLAttributes与VariantPropstypeof variantsforwardRef保证消费方可以挂 refasChild基于radix-ui/react-slot的Slot支持把组件渲染为链接、路由Link等任意元素cn()合并类名cn(variants(...), className)。buttonVariants定义了 8 个变体——primary、secondary、outline、ghost、danger以及三个链接类变体link-accent、link-danger、link-neutral——每个变体都严格走“Figma token → CSS 变量 → Tailwind 类”的映射例如primary: [ bg-interactive-primary text-text-on-accent border-transparent, hover:bg-interactive-primary-hover, active:bg-interactive-primary-active, disabled:bg-interactive-disabled disabled:text-text-disabled disabled:border-transparent, focus-visible:shadow-focus-outline-default ]尺寸变体覆盖2xs20px 方形图标按钮配合IconButton到lgButton还支持loading属性加载时渲染内部Spinner并隐藏行内图标同时设置aria-busyIconButton则要求必传label作为可访问名称同时应用为aria-label与title。新增组件时可以用 shadcn CLI 生成基础文件cd packages/design-system npx shadcnlatest add component-name生成的文件落在src/components/ui/component-name.tsx但其中使用的 shadcn 默认 CSS 变量bg-primary、text-muted-foreground等在本包中不存在必须替换为tokens/tokens.generated.css中的 token 工具类或var(--token-name)。4.3 用 token 工具类还是原生 Tailwind规则一句话总结外观appearance——设计师拥有决策权的值——必须来自 DS token 工具类布局、尺寸与动效使用原生 Tailwind其默认刻度与 token 一一对应。设计师指定的值用ds-*/ 语义工具类类别用法示例颜色语义工具类bg-surface-canvas、text-text-default、border-border-default焦点环shadow-*语义类shadow-focus-outline-default字号text-ds-*text-ds-md而非text-sm字重font-ds-*font-ds-medium而非font-medium行高leading-ds-*leading-ds-normal而非leading-normal字距tracking-ds-*tracking-ds-tight而非tracking-tight圆角rounded-ds-*rounded-ds-sm而非rounded边框宽度border-ds-*border-ds-1而非border允许直接使用原生 Tailwind 的类别默认刻度与 token 相等无需 DS 工具类类别用法示例间距原生刻度gap-2、px-3对应--ds-space-*4px 刻度图标尺寸原生刻度size-416px、size-3.514px动效原生刻度duration-100--ds-motion-duration-fastease-in-out--ds-motion-easing-standard布局/结构原生flex、grid、items-center、relative、truncate、z-10等禁止在className中以[var(--ds-*)]任意值形式内联 token——应优先使用已注册的工具类或上述原生类若某个 token 没有对应工具类则把它加进theme块以生成工具类而不是退回var()。另外有一个已知陷阱border-ds-*工具类只设置四边边框方向形式border-t-ds-1、border-b-ds-hairline在 Tailwind v4 下不会渲染根因未解。单边边框的正确做法是1px 用原生border-t等加颜色工具类如border-t border-border-default0.5px hairline 用任意值border-t-[0.5px]。4.4 焦点环Focus rings组件通过box-shadow应用焦点环使用--focus-outline-default破坏性操作使用--focus-outline-danger并自行用focus-visible:outline-none抑制原生 outlinefocus-visible:outline-none focus-visible:shadow-focus-outline-default // 破坏性操作 focus-visible:outline-none focus-visible:shadow-focus-outline-danger不需要全局*:focus-visiblereset——webapp 通过其focus-default工具类在组件级别作用相同的行为。真实文件中的语义阴影变量--focus-outline-default、--focus-outline-danger、--container-inset等都定义在tokens.generated.css的语义段中。4.5cn()类名合并助手所有类名合并都经过 packages/design-system/src/lib/cn.ts 的cn()它把clsx条件/数组语法与tailwind-merge冲突消解组合起来例如cn(h-8, h-10)会得到h-10而不是h-8 h-10。其中dsTwMergeConfig定义于 packages/design-system/src/lib/twMergeConfig.ts并从 barrel 导出教会tailwind-merge识别本包theme生成的text-ds-*、border-ds-*等 token 工具类使它们被归入正确的冲突组、正确地去重——消费方可以在自己的cn中复用同一份配置。4.6 新增组件五步法来自 AGENTS.mdshadcn CLI 生成基础npx shadcnlatest add component-name写入src/components/ui/。注意components.json的/*别名在 tsconfig 中刻意缺失会与 Storybook 的→ webapp 别名冲突脚手架期间可临时添加、完成后移除替换 shadcn CSS 变量为设计 token所有颜色/圆角/间距/动效必须来自tokens.generated.css遵循组件模式cva变体对象 forwardRefasChildcn() 导出variants添加 Storybook 故事与组件同目录的name.stories.tsx标题为Design System/Components/ComponentName展示所有需要“冻结”的变体与状态默认、hover、disabledfocus 状态无需专门 story评审者直接在默认/交互故事中点击即可触发从 barrel 导出在src/index.ts追加export { MyComponent, type MyProps, myVariants } from ./components/ui/my-component;。4.7 暗色模式token 文件同时定义了亮色与暗色两套值亮色是:root暗色是[data-themedark]。组件不需要暗色变体——CSS 变量自动完成主题切换。因此在 Storybook 中用Themes按钮切换后务必在两种主题下逐一检查每个组件。五、Tokens Studio GitHub sync 配置5.1 配置项字段值仓库RepositoryNangoHQ/nango分支Branchdesign/tokens文件路径File pathpackages/design-system/tokens/tokens.json5.2 Figma 插件首次设置安装 Tokens Studio for Figma 插件插件应能检测到已有 GitHub sync 并预填除 access token 外的所有字段对于Personal Access Token字段从 1Password 获取Vault保险库EngItem条目GitHub PAT - Figma Tokens Studio Sync点击Save——插件会从design/tokens分支加载既有 token。六、工程实践小结设计单一事实源在 Figma代码侧以tokens.json提交入库、tokens.generated.css由流水线产出并提交二者缺一不可同步纪律npm run tokens:fetch拉取 重建npm run tokens:build仅重建合并冲突后优先用tokens:build组件纪律只使用语义 token 工具类禁止硬编码外观值新外观通过新增变体解决且需与 Figma 设计系统同步Storybook 是验收现场每个组件都要有 story每个 story 都要过 axe 审计PR 级联的托管 Storybook 便于分享 WIP 组件AI 友好通过storybook/addon-mcp启用 MCP 后AI 助手可以直接查询组件文档与 props降低跨包开发的上下文成本。这套设计系统以Figma 出 token、Style Dictionary 编译、Tailwind v4 生成工具类、Radix CVA tailwind-merge 产出组件、Storybook 统一验收的闭环为 Nango 的 Web 应用packages/webapp提供了跨页面一致的外观基础。需要深入某一环节时建议直接阅读 packages/design-system/AGENTS.md组件新增全指南、packages/design-system/scripts/tokens-fetch.mjstoken 流水线源码与 packages/design-system/tokens/tokens.generated.csstoken 全量清单。【免费下载链接】nangoBuild product integrations with AI.项目地址: https://gitcode.com/GitHub_Trending/na/nango创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考