news 2026/9/12 2:30:46

Label Studio 前端设计系统完全指南:从 Design Tokens 到 @humansignal/ui 组件库的工程化实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Label Studio 前端设计系统完全指南:从 Design Tokens 到 @humansignal/ui 组件库的工程化实践

Label Studio 前端设计系统完全指南:从 Design Tokens 到 @humansignal/ui 组件库的工程化实践

【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio

本指南以 Label Studio 仓库根目录的 DESIGN.md 为骨架,系统讲解该标注平台前端的设计体系:品牌原则、内容规范、WCAG 2.1 AA 无障碍标准、语义化 Design Tokens、@humansignal/ui共享组件库的用法与开发规范、常见交互模式与反模式清单。读完你将掌握 Label Studio 前端(web/目录下的 React 应用)从"写样式"到"写组件"的完整规范,并能在源码层面理解令牌体系与组件是如何落地实现的。


品牌与设计原则

Label Studio 的设计人格(Personality)被定义为:人性化(Human)、乐观(Optimistic)、轻松(Lighthearted)、可靠(Reliable)、适应性强(Adaptable)、精工细作(Fine-crafting)

在此基础上,产品设计遵循五条核心原则:

  • 解决人的问题(Solve human problems):一切功能围绕标注员、审核员的真实工作流展开;
  • 增强人的能力(Enhance human ability):界面让标注与审核更快、更准确,而不是替人做决定;
  • 可信赖(Trustworthy):数据、状态与操作结果透明可预期;
  • 透明(Transparent):系统行为与数据流向对用户可见;
  • 可预测(Predictive):交互符合直觉,减少意外。

这五条原则与 Label Studio 的核心业务(多类型数据标注、标准化输出格式)直接对应——标注工作强调精确与信任,因此界面规范处处体现"状态可感知、操作可撤销、层级可预期"。


内容规范(Content Guidelines)

语气与语调(Voice and Tone)

面向用户的文案应当:口语化(Conversational)、开放(Open)、清晰(Clear)、实用(Practical),整体风格非正式但积极(Informal, optimistic, positive, friendly),让用户在使用时感到被鼓励和有动力。

写作风格(Writing Style)

  • 短句:目标阅读水平为七年级及以下(约等于中文通俗易懂的表述),降低认知负担;
  • 命名一致性:同一个元素在整个应用中使用同一名称——例如标注业务中用了 "category",就不要再混用 "type" 或 "group";
  • 多用主动语态:如写 "Reviewers review and update annotations",而不是 "Annotations are reviewed by reviewers";
  • 标题、输入标签与控件使用 Sentence Case:如 "Selection details"、"Email address"、"Enable notifications";
  • 按钮与导航项使用 Title Case:如 "Save Changes"、"Upload Dataset"、"View Documentation";
  • 使用缩略形式让语言更口语化:如 "can't"、"don't"、"it's"。

UI 文案规则

  • 错误消息(Error Messages):清晰、具体、有帮助——告诉用户发生了什么以及如何修复;
  • 反馈消息(Feedback Messages):积极、鼓励、信息充分;
  • 标签与按钮(Labels and Buttons):按钮用动作动词(Save、Cancel、Upload);标签保持简洁但具描述性;按钮用 Title Case,标签用 Sentence Case;
  • 链接(Links):使用能指示目标位置的描述性链接文本。

词汇表

领域术语(Project、Task、Annotation 等)由terminology.mdcCursor 规则维护。需要说明的是,DESIGN.md 中引用的react.mdctailwind.mdctypescript.mdcfrontend-unit-tests.mdcterminology.mdc属于配套的编辑器规则文档,当前仓库中未包含这些文件,本文将在相关章节给出等价的可执行规范。


无障碍标准(Accessibility Standards)

Label Studio 前端要求满足WCAG 2.1 Level AA。结合 web/libs/ui/src/lib/empty-state/empty-state.tsx 等组件实现可以看到,无障碍不是口号而是落到代码里的硬性要求。

键盘导航(Keyboard Navigation)

  • 所有交互元素必须键盘可达;
  • Tab 顺序正确贯穿整个界面;
  • 可见焦点指示器,与背景的对比度最低3:1
  • 支持 ESC、Enter、Space、方向键;
  • 无焦点陷阱(模态框除外);
  • 模态框/对话框关闭后,焦点回到合适的原始位置。

视觉(Visual)

  • 文本对比度最低4.5:1
  • 颜色不能作为传递信息的唯一手段(必须辅以图标、文字或形状);
  • 界面可放大到200%且不丢失内容;
  • 所有图片必须有 alt 文本。

结构(Structure)

  • 全程使用语义化 HTML;
  • 必要时使用 ARIA 属性;
  • 标题层级正确(H1 → H2 → H3);
  • 表单标签与输入控件关联;
  • 错误消息通过aria-describedby与字段关联;
  • 动态内容使用 ARIA live regions。

EmptyState组件为例,其实现会自动为标题和描述生成唯一 ID,并通过aria-labelledby引用标题、aria-describedby引用描述,同时支持传入aria-label覆盖无障碍名称——"开箱即用的无障碍"在 empty-state.tsx 中有完整体现。


Design Tokens:语义化的视觉地基

设计令牌是整个设计系统的核心。DESIGN.md 明确其位置在web/libs/ui/src/tokens/tokens.prefix.css,并强调一条铁律:

始终使用语义令牌(semantic tokens),禁止使用数值令牌(numeric tokens)。

类别✅ 使用语义令牌❌ 不要用数值令牌
间距 Spacingp-tightm-basegap-widep-200m-400gap-600
排版 Typographytext-body-mediumtext-label-smalltext-16text-14
颜色 Colorsbg-primary-surfacetext-neutral-contentbg-grape-600text-sand-800

令牌的文件层级与生成链路

从源码看,这套令牌体系有一条清晰的生成链路:

  1. 设计源:web/design-tokens.json(6 千余行的 JSON,携带 Figma Variable 元数据$variable_metadata、明暗双 mode);
  2. 构建产物:web/libs/ui/src/tokens/tokens.prefix.css(文件头注明 "Generated from design-tokens.json - DO NOT EDIT DIRECTLY");
  3. 运行时桥接:web/libs/ui/src/tokens/tokens.js 被 web/libs/ui/src/tailwind.config.js 通过createRequire加载,把 colors、fontSize、lineHeight、letterSpacing、fontFamily、fontWeight、spacing、cornerRadius 全部展开为 Tailwind 的可用工具类。

因此,你在 JSX 里写的bg-primary-surface最终会解析到 tokens.prefix.css 里的--color-primary-surface,而后者又引用自基础色板(如--color-grape-700)。一旦某个组件想跳过语义层直接写bg-grape-600,暗黑模式与后续品牌调整都会失效——这正是"永远用语义令牌"的根本原因。

颜色令牌(Color Tokens)

语义颜色分为六大类:

  • Primary(品牌色):grape / blue;
  • Neutral(灰阶):sand;
  • Positive(成功态):kale / green;
  • Negative(错误态):persimmon / red;
  • Warning(警告态):canteloupe / orange;
  • Accent(装饰色):grape、blueberry、kale、kiwi、mango、canteloupe、persimmon、plum、fig、sand。

颜色令牌按用途结构化命名,在 tokens.prefix.css 中可看到完整定义:

/* Surface colors(交互元素的背景) */ --color-primary-surface --color-primary-surface-hover --color-primary-surface-active /* Content colors(文本) */ --color-neutral-content --color-neutral-content-subtle --color-neutral-content-subtler --color-neutral-content-subtlest /* 用于禁用文本 */ /* Background colors(页面/容器背景) */ --color-neutral-background --color-primary-background /* Border colors(边框) */ --color-neutral-border --color-primary-border-subtle /* Icon colors(图标) */ --color-primary-icon --color-negative-icon

Accent 色(用于标签、图表、分类)按状态阶梯使用:

  • 默认:-bold文本 +-subtlest背景;
  • 悬停:-bold文本 +-subtle背景;
  • 激活:-subtlest文本 +-base背景;
  • 图表:-base背景。

间距令牌(Spacing Tokens)

语义间距刻度(同时在 CSS 变量与 Tailwind 工具类两个层面生效):

  • --spacing-tightest/tightest:2px
  • --spacing-tighter/tighter:4px
  • --spacing-tight/tight:8px
  • --spacing-base/base:16px
  • --spacing-wide/wide:24px
  • --spacing-wider/wider:32px
  • --spacing-widest/widest:40px

以源码为证,tokens.prefix.css 中语义变量通过var(--spacing-*)引用基础刻度(如--spacing-tight: var(--spacing-200),而--spacing-200: 0.5rem),做到了"语义层 + 数值层"的解耦。

排版令牌(Typography Tokens)

  • text-body-smallest/--font-size-body-smallest:10px
  • text-body-smaller/--font-size-body-smaller:12px
  • text-body-small/--font-size-body-small:14px
  • text-body-medium/--font-size-body-medium:16px
  • text-label-small/--font-size-label-small:14px
  • text-label-medium/--font-size-label-medium:16px
  • text-title-small/--font-size-title-small:18px
  • text-title-medium/--font-size-title-medium:20px
  • text-title-large/--font-size-title-large:24px

此外 tokens.prefix.css 还定义了headline-*display-*等更大的展示层级,以及配套的--line-height-*行高、--font-weight-*字重、--font-family-*字体族(正文使用 "Figtree",等宽使用 "IBM Plex Mono",字体文件位于 web/libs/ui/src/fonts)。

暗黑模式(Dark Mode)

暗黑模式在使用语义令牌的前提下自动生效,无需任何额外处理。源码层面,tokens.prefix.css 通过[data-color-scheme="dark"]选择器整体覆写语义变量的取值(例如--color-neutral-surfacesand-100切换为sand-850),同时 tokens.prefix.css 还内置了max-width: 767px下的移动端字号降级方案。

硬性禁令:永远不要硬编码颜色、数值令牌(如grape-600)或内联颜色样式,否则会破坏暗黑模式。


组件库:@humansignal/ui

位置与导入

Label Studio 的所有共享 UI 组件集中在@humansignal/ui包:

  • 源码目录:web/libs/ui/src/lib/
  • 导入方式:import { Button, Badge } from '@humansignal/ui';

从 web/libs/ui/src/index.ts 可以看到组件库的公开面:Button、Badge、Message、Tooltip、Modal、EmptyState、Drawer、Tabs、Toast、Toggle、Spinner、Skeleton、Typography、Dropdown、Select、Checkbox、DataTable、Pagination、AI Chat 等数十个组件均从这里统一导出;其中MultiTreeSelect特意使用具名导出而非export *,以避免与公开的TreeSelect发生命名冲突——这个注释细节(index.ts)提示了组件库对公共 API 稳定性的重视。

组件发现(Component Discovery)

  • 源码web/libs/ui/src/lib/
  • Storybook:运行yarn nx storybook storybook(端口4400)浏览全部组件与交互文档。

关键纪律:创建新组件之前,务必先检查@humansignal/ui是否已有现成实现。规范要求:信息提示框用Message,空状态用EmptyState,按钮一律用Button而不是原生<button>

导入模式(Import Patterns)

// UI 组件 import { Button, Badge, Message } from '@humansignal/ui'; // 图标 import { IconCheck, IconCross } from '@humansignal/icons'; // 核心工具 import { cn } from '@humansignal/core';

图标资源位于web/libs/ui/src/assets/icons/(SVG 集合),由@humansignal/icons统一暴露。

shadcn/ui 集成

部分组件基于 shadcn/ui 构建,但一律通过@humansignal/ui导入,严禁从/src/shad/直接导入(底层 shad 组件位于web/libs/ui/src/shad/components/,属于内部实现细节)。


样式指南(Styling Guidelines)

Tailwind CSS

使用语义工具类,这是整套规范的最高频实践:

  • p-tightbg-primary-surfacetext-body-medium
  • p-200bg-grape-600text-16

响应式设计通过sm:md:lg:前缀实现。以 web/libs/ui/src/tailwind.config.js 为例,其content覆盖apps/**与全部libs/*/src/**,并把 tokens.js 的配色、字号、行高、字距、字体、字重、间距、圆角全部注入主题,同时保留了若干兼容旧版 shadcn 的 HSL 变量(文件内明确注释 "DO NOT USE THESE COLORS",提醒开发者以 Figma 令牌为准)。

CSS Modules

样式文件与组件同目录放置(.module.css),并使用组件令牌(Component Tokens)模式——组件内部通过局部 CSS 变量引用全局语义令牌,再在具体变体中覆写:

.base { --background-color: var(--color-primary-surface); --text-color: var(--color-primary-surface-content); background-color: var(--background-color); color: var(--text-color); } .variant-neutral { --background-color: var(--color-neutral-surface); --text-color: var(--color-neutral-content); }

这一模式在 web/libs/ui/src/lib/button/button.module.css 中有完整实现:.base定义--background-color--text-color--border-color--focus-outline等局部变量,各.variant-*.look-*只负责覆写这些变量,而.waiting:focus:disabled等状态逻辑全部复用同一套变量,从而把按钮从 primary 到 gradient 的所有形态压缩在约 500 行纯声明式 CSS 中。

CSS 内嵌 Tailwind 写法:@apply flex items-center gap-tight;

Canvas 元素取色

对于无法使用 CSS 变量的 Canvas/JS 渲染场景(如图形编辑器标注层),使用getTokenColor获取颜色值:

import { getTokenColor } from '@humansignal/ui'; ctx.fillStyle = getTokenColor('--color-primary-surface');

其实现位于 web/libs/ui/src/utils/getTokenColor.ts:它从 web/design-tokens.json 中按令牌名解析路径、跟随{@...}引用链解出最终色值,支持hex/rgb/rgba三种格式与可选透明度,若令牌无法解析会返回品红色(#ff00ff)以让缺失立刻暴露。配套的 web/libs/ui/src/hooks/useTokenColor.ts 基于 jotai 的themeAtom自动感知明暗主题并返回主题感知的取色函数,主题切换时自动重渲染——这正是 Canvas 图层正确跟随暗黑模式的关键。


组件开发规范(Component Development)

文件结构

  • @humansignal/ui组件:kebab-case命名(button.tsxempty-state.tsx);
  • 应用层组件:允许 PascalCase(如DataManager.tsx);
  • 同目录聚合.tsx.module.css.stories.tsx.test.tsx放在一起;
  • 每个组件必须有 Storybook stories

web/libs/ui/src/lib/的目录结构看(badge/button/empty-state/modal/tooltip/toast/tabs/等),这一规范已被严格执行,且多数组件同时携带*.module.css与测试文件。


通用模式(Common Patterns)

组件变体(Variants)

  • 状态 Stateprimaryneutralpositivenegativewarninggradient(源码中 Button 另有inverted变体,见 button.tsx);
  • 尺寸 Sizesmaller(24px)、small(32px)、medium(40px),large(48px+);
  • 外观 Lookfilled(实心)、outlined(描边)、string(纯文字)。

禁用状态(Disabled States)

禁用文本使用neutral-content-subtlest

<button disabled className="text-neutral-content-subtlest">

加载状态(Loading States)

使用waiting属性:

<Button waiting={isLoading}>Save</Button>

button.module.css 中的.waiting状态用repeating-linear-gradient绘制斜纹并通过@keyframes button-waiting实现 1s 线性循环动画;配合waitingClickablesecondaryOnClick,可以在等待期间保留可点击的次级动作(实现见 button.tsx)。

空状态(Empty States)

一律使用EmptyState,包含图标、标题、描述与动作:

<EmptyState icon={<IconInbox />} title="No tasks yet" description="..." actions={<Button>Create</Button>} />

组件支持large/medium/small三种尺寸与六种颜色变体,并根据尺寸自动匹配图标大小与排版层级(empty-state.tsx),例如 Data Manager 使用 large(40px 图标 + headline medium),侧边栏使用 small(24px 图标 + body)。

模态框模式(Modal Patterns)

  • 底部动作区(Footer Actions):所有 CTA 与导航按钮放在 footer;默认右对齐,"Previous" 类返回按钮左对齐;
  • 按钮视觉层级:见下文"按钮层级"一节;
  • 破坏性操作(Destructive Actions):必须二次确认;高影响操作要求输入验证(如输入 "DELETE" 或实体名称);
  • 模态框堆叠:避免模态框套模态框,改用多步骤模态框或抽屉(Drawer)。
// 右对齐 footer(默认) <Modal.Footer align="right"> <Button variant="neutral" look="outlined">Cancel</Button> <Button variant="primary" look="filled">Save Changes</Button> </Modal.Footer>

模态框相关实现位于web/libs/ui/src/lib/modal/Modal.tsxModalHeader.tsxModalFooter.tsxModalBody.tsxModalCloseButton.tsx等,其中 ModalFooter.tsx 目前支持barestyleclassName属性)。


组件复用与最佳实践

组件选择(Component Selection)

新建组件前先查@humansignal/ui与 Storybook。必须使用现成组件

  • <Button>而不是<button>
  • <Message>用于信息提示框
  • <Tooltip>用于气泡提示
  • <Modal>用于模态框
  • <EmptyState>用于空状态

命名约定(Naming Conventions)

  • @humansignal/ui:kebab-case(button.tsx);
  • 应用组件:PascalCase(DataManager.tsx);
  • Props 类型:ComponentNameProps(如ButtonProps,见 button.tsx)。

值与令牌(Values & Tokens)

绝不硬编码数值,一律使用语义令牌:

className="text-primary-content p-tight text-body-medium"

组件令牌(Component Tokens)模式:

.component { --component-bg: var(--color-neutral-surface); background: var(--component-bg); }

尺寸优先使用rem,必要时可用px

按钮层级(Button Hierarchy)

每个屏幕只有一个 primary/filled 按钮(单一 CTA)。

视觉层级跟随对齐方向:

  • 右对齐:从右到左排,primary 在最右:[Cancel] [Save]
  • 左对齐:从左到右排,primary 在最左:[Next] [Skip]

响应式设计(Responsive Design)

布局必须自适应:

flex-col md:flex-row p-tight md:p-base text-title-medium md:text-headline-small

保存设置(Saving Settings)

设置/配置页使用显式 Save 按钮(不做自动保存)。例外情况:草稿内容、偏好设置、即时生效的开关(toggle)。


反模式清单(Anti-Patterns to Avoid)

以下行为被明确禁止,是 Code Review 时的红线:

  • ❌ 数值令牌(p-200bg-grape-600
  • ❌ 硬编码颜色(color: #4C5FA9
  • ❌ 内联样式(会破坏暗黑模式)
  • ❌ 已有类似组件却重复造轮子
  • ❌ 使用原生<button>而非<Button>
  • ❌ 直接从/src/shad/导入
  • ❌ 一个屏幕出现多个 primary/filled 按钮
  • ❌ 缺失键盘导航
  • ❌ 缺失焦点指示器
  • ❌ 仅用颜色传递信息
  • ❌ 对比度不足(< 4.5:1)
  • ❌ 非语义化 HTML
  • ❌ 非响应式布局

快速参考(Quick Reference)

关键文件

用途路径/命令
组件源码web/libs/ui/src/lib/
设计令牌web/libs/ui/src/tokens/tokens.prefix.css
令牌设计源web/design-tokens.json
图标@humansignal/icons(资源在web/libs/ui/src/assets/icons/
Storybookyarn nx storybook storybook(端口 4400)
Tailwind 配置web/libs/ui/src/tailwind.config.js

配套文档

DESIGN.md 引用了react.mdc(组件结构、Hooks、状态管理)、tailwind.mdc(工具类与响应式)、typescript.mdc(类型约定)、frontend-unit-tests.mdc(测试模式)、terminology.mdc(领域术语)五份配套规范,它们以编辑器规则(Cursor Rule)形式存在,未包含在当前仓库中;本文的样式、组件、命名与模式章节已给出对应的可执行版本。

常见导入

import { Button, Message, EmptyState } from '@humansignal/ui'; import { IconCheck } from '@humansignal/icons'; import { cn } from '@humansignal/core';

令牌示例

p-tightm-basegap-widetext-body-mediumbg-primary-surfacetext-neutral-contenttext-neutral-content-subtlest(禁用态文本)。


小结

Label Studio 的设计系统是一条从 Figma 变量(design-tokens.json)到 CSS 令牌(tokens.prefix.css)、再到 Tailwind 工具类与@humansignal/ui组件的完整工程链路。开发者日常遵守三条核心纪律即可保持体系健康:只用语义令牌、优先复用@humansignal/ui组件、把无障碍当成默认要求。这套体系既保证了多类型标注界面(图像、文本、音频、视频、时间序列等)的视觉一致性与暗黑模式可用性,也为后续迭代提供了可预测、可维护的扩展基础。

【免费下载链接】label-studioLabel Studio is a multi-type data labeling and annotation tool with standardized output format项目地址: https://gitcode.com/GitHub_Trending/la/label-studio

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 2:30:30

基于U-Net的路面裂缝检测识别系统设计与工程部署实践

简介&#xff1a;这是一套基于MATLAB的路面裂缝检测识别系统设计资源&#xff0c;面向深度学习、图像处理方向的工程实践与课程设计&#xff0c;可用于道路病害自动化检测和算法验证。压缩包内共18个文件&#xff0c;以14个.m源码为主&#xff0c;覆盖主程序、图像处理函数与裂…

作者头像 李华
网站建设 2026/9/12 2:26:56

嵌入式四大方向本质:MCU、Linux应用、驱动与硬件的能力坐标系

1. 嵌入式四大方向到底指什么&#xff1f;先别急着选&#xff0c;得看清每条路的“地基”在哪“嵌入式四大方向&#xff0c;到底怎么选&#xff1f;”——这问题我每天在技术群、面试现场、甚至咖啡馆里被问至少五次。不是因为大家懒&#xff0c;而是刚入行时看到的全是碎片&am…

作者头像 李华
网站建设 2026/9/12 2:24:42

Excel模板与函数实战:从模板筛选改造到财务进销存系统

Excel这个工具用了十几年&#xff0c;我最大的感受是&#xff1a;模板和函数就像两座山&#xff0c;翻过一座还有一座。很多朋友下载了一堆模板&#xff0c;真到要用的时候&#xff0c;不是公式出错&#xff0c;就是对不上自己的业务场景&#xff1b;函数背了一堆&#xff0c;遇…

作者头像 李华
网站建设 2026/9/12 2:23:26

HarmonyOS日记本应用开发:Stage模型、ArkTS与本地存储实践

简介&#xff1a;基于HarmonyOS打造的个人日记本应用完整源码&#xff0c;面向有一定ArkTS基础或对鸿蒙应用开发感兴趣的开发者&#xff0c;覆盖从登录、日记列表、撰写编辑到多媒体记录与关系型数据库存储等核心功能&#xff0c;并展示了跨设备数据同步思路&#xff0c;适合日…

作者头像 李华
网站建设 2026/9/12 2:19:04

Kaggle MNIST ZIP源码本地复现指南:绕过torchvision 404与CUDA适配

简介&#xff1a;本资源是一份面向深度学习初学者与Kaggle入门者的MNIST手写数字识别竞赛实战源码包&#xff0c;聚焦图像分类任务的端到端实现&#xff0c;解决模型构建、训练调优与结果提交等核心问题。压缩包共9个文件&#xff0c;包含3个关键数据/模型压缩包&#xff08;tr…

作者头像 李华
网站建设 2026/9/12 2:18:59

IC烧录:芯片量产的隐形门槛与可靠性核心

1. 这个“烧录”不是烤芯片&#xff0c;而是芯片出厂前的最后一道指纹刻印 IC烧录这个词&#xff0c;乍一听容易让人联想到车间里高温烘烤的流水线——其实完全不是。它更像给新生儿打疫苗时在手臂上留下的那一针&#xff1a;看不见、摸不着&#xff0c;但决定了这个“生命体”…

作者头像 李华