mcpField
F
fluent2-design-system

fluent2-design-system

github.com/fefogarcia设计与 UI277 次安装37 周前更新
代码仓库

关于 fluent2-design-system

fluent2-design-system 是面向 React 开发者的 Fluent 2 设计系统技能,涵盖 @fluentui/react-components v9 的组件、主题与样式规范。它强调使用设计令牌构建一致且可访问的界面。

主要功能

  1. 01Fluent 2 主题与自定义品牌
  2. 02基于 Griffel 的样式指南
  3. 03设计令牌分类与用法
  4. 04v9 组件模式与常用组件
  5. 05布局、排版与颜色规范
  6. 06键盘与高对比度无障碍指南

适用场景

  1. 01为 React 应用设置浅色、深色或品牌主题
  2. 02按设计令牌编写组件样式
  3. 03构建包含输入、导航和反馈组件的界面
  4. 04检查键盘操作与高对比度支持

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/fefogarcia/approved-skills --skill fluent2-design-system

安装后在 Claude Code 中输入/fluent2-design-system确认已加载。

附带文件references/components.mdreferences/tokens.md

详细介绍

Fluent 2 设计系统

使用 Microsoft 的 Fluent 2 设计系统和 @fluentui/react-components(v9)构建可用于生产环境的界面。

快速开始

每个 Fluent 2 React 应用都需要用带主题的 FluentProvider 包裹组件树:

import {
  FluentProvider,
  webLightTheme,
  webDarkTheme,
  Button,
  tokens,
  makeStyles,
  mergeClasses,
} from "@fluentui/react-components";

export default function App() {
  return (
    <FluentProvider theme={webLightTheme}>
      <Button appearance="primary">Hello Fluent 2</Button>
    </FluentProvider>
  );
}

安装:npm install @fluentui/react-components

核心架构

主题
  • 内置主题:webLightTheme、webDarkTheme、teamsLightTheme、teamsDarkTheme、teamsHighContrastTheme
  • 自定义品牌:使用 createLightTheme(brandRamp) / createDarkTheme(brandRamp),并传入 BrandVariants 对象(键为 10–160)
  • 嵌套:FluentProvider 可以嵌套,以便为子树应用不同主题
  • 主题值会作为 CSS 自定义属性输出到 provider 元素上
使用 Griffel 进行样式设置

使用 makeStyles(来自 @fluentui/react-components)——需要支持 token 的样式设置时,切勿使用内联样式或外部 CSS。

const useStyles = makeStyles({
  root: {
    backgroundColor: tokens.colorNeutralBackground1,
    color: tokens.colorNeutralForeground1,
    display: "flex",
    gap: tokens.spacingHorizontalM,
    padding: tokens.spacingVerticalM,
  },
  active: {
    backgroundColor: tokens.colorBrandBackground,
    color: tokens.colorNeutralForegroundOnBrand,
  },
});

function MyComponent({ isActive }) {
  const styles = useStyles();
  return (
    <div className={mergeClasses(styles.root, isActive && styles.active)}>
      Content
    </div>
  );
}

重要规则:

  • 在组件外部(模块作用域)定义 makeStyles
  • 使用 mergeClasses() 组合类名——切勿拼接字符串
  • 所有颜色、间距、排版、圆角和阴影都使用 tokens.*——切勿硬编码十六进制或 px 值
  • 不支持 CSS 简写属性(如 border、borderRadius、padding 等)——请使用 shorthands.* 助手或长属性
  • 伪选择器使用嵌套对象:":hover": { color: tokens.colorBrandForeground1 }
  • 媒体查询使用嵌套对象:"@media (min-width: 768px)": { flexDirection: "row" }
组件模型

所有 v9 组件都遵循一致的模式:

  • 插槽:具名子部分(例如 root、icon、content),可接受属性或 JSX
  • 外观变体:"primary"、"secondary"、"subtle"、"transparent"、"outline"
  • 尺寸变体:"small"、"medium"、"large"
  • 形状变体:"rounded"、"circular"、"square"

通过 className 配合 makeStyles/mergeClasses 覆盖组件样式。

设计 Token

Token 是设计意图与代码之间的桥梁。始终使用 tokens.*——切勿使用原始值。

完整的 Token 参考表(颜色、排版、间距、标高、描边、圆角)请参见 references/tokens.md。

Token 类别一览
类别前缀示例
中性色colorNeutral*tokens.colorNeutralBackground1
品牌色colorBrand*tokens.colorBrandBackground
状态色colorPalette{Color}*tokens.colorPaletteRedForeground1
排版fontFamily*、fontSize*、fontWeight*、lineHeight*tokens.fontSizeBase300
间距spacingHorizontal*、spacingVertical*tokens.spacingHorizontalM
边框圆角borderRadius*tokens.borderRadiusMedium
描边宽度strokeWidth*tokens.strokeWidthThin
阴影shadow*tokens.shadow4
时长duration*tokens.durationNormal
缓动curve*tokens.curveEasyEase
双层 Token 系统
  1. 全局 Token — 与上下文无关的原始值(例如 colorBlue60、fontSize300)
  2. 别名 Token — 应用于全局 Token 的语义含义(例如 colorBrandBackground → 蓝色,colorNeutralForeground1 → 深灰色)

在代码中,通过 tokens 对象使用别名 Token。

布局

  • 网格:使用 CSS Grid/Flexbox——Fluent 2 v9 没有 Stack 组件
  • 间距刻度:基准单位为 4px。取值:XXS(2)、XS(4)、S(8)、M(12)、L(16)、XL(20)、XXL(24)、XXXL(32)
  • 列网格:建议 Web 使用 12 列框架;请使用 CSS grid
  • 对齐:使用 tokens.spacingHorizontal* 和 tokens.spacingVertical* 保持间距一致

字体排版

  • 主字体:Segoe UI(Web)、Segoe UI Variable(Windows)、SF Pro(macOS/iOS)、Roboto(Android)
  • 字体栈:tokens.fontFamilyBase = Segoe UI → 系统回退字体 → sans-serif
  • 等宽字体:tokens.fontFamilyMonospace
  • 文本预设:使用带有预设变体的 <Text> 组件 — Caption1、Body1、Body1Strong、Subtitle1、Subtitle2、Title1、Title2、Title3、LargeTitle、Display
  • 对齐方式:LTR 使用左对齐;Fluent 通过 Griffel 自动处理 RTL

颜色系统

三种调色板:

  1. 中性色 — 黑色、白色和灰色,用于表面、文本和布局
  2. 品牌色 — 强调色,用于强化品牌标识(Microsoft 的默认品牌色为蓝色)
  3. 共享色/状态色 — 跨产品使用的颜色:红色(危险)、绿色(成功)、黄色(警告)、蓝色(信息)

交互状态:常态 → 悬停(更深)→ 按下(最深)。焦点状态会增加描边粗细,而不是改变颜色。

无障碍访问

  • 所有组件均包含 ARIA 角色、键盘导航(通过 Tabster)和焦点管理
  • 高对比度:使用 teamsHighContrastTheme,或通过系统颜色(ButtonText、Highlight 等)处理 @media (forced-colors: active)
  • 默认情况下焦点指示器可见 — 切勿移除
  • 通过语义化令牌配对确保符合 WCAG 对比度要求(例如,在 colorNeutralBackground1 上使用 colorNeutralForeground1)

组件清单

完整的分类组件列表及使用说明,请参阅 references/components.md。

最常用组件

操作:Button、CompoundButton、SplitButton、ToggleButton、MenuButton、Link 输入:Input、Textarea、Select、Combobox、Dropdown、Checkbox、RadioGroup、Switch、Slider、SpinButton、DatePicker、TimePicker 布局:Card、Divider、Drawer、Dialog、Popover、Tooltip 数据显示:Table、DataGrid、Tree、Accordion、Badge、Avatar、AvatarGroup、Tag、Persona 导航:TabList、Breadcrumb、Nav(预览) 反馈:Toast、MessageBar、ProgressBar、Spinner、Skeleton 表面:Menu、Toolbar、Overflow

常见模式

应用外壳布局
const useStyles = makeStyles({
  app: {
    backgroundColor: tokens.colorNeutralBackground1,
    display: "grid",
    gridTemplateColumns: "1fr",
    gridTemplateRows: "auto 1fr auto",
    height: "100vh",
    width: "100%",
  },
  header: {
    borderBottom: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,
    paddingTop: tokens.spacingVerticalS,
    paddingBottom: tokens.spacingVerticalS,
    paddingLeft: tokens.spacingHorizontalM,
    paddingRight: tokens.spacingHorizontalM,
  },
  content: {
    display: "grid",
    gridTemplateColumns: "280px 1fr",
    overflow: "hidden",
  },
  nav: {
    borderRight: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,
    overflowY: "auto",
  },
  main: {
    overflowY: "auto",
    paddingLeft: tokens.spacingHorizontalL,
    paddingRight: tokens.spacingHorizontalL,
    paddingTop: tokens.spacingVerticalL,
    paddingBottom: tokens.spacingVerticalL,
  },
});
自定义品牌主题
import { createLightTheme, createDarkTheme } from "@fluentui/react-components";

const myBrand = {
  10: "#020305", 20: "#111723", 30: "#16263D",
  40: "#193253", 50: "#1B3F6A", 60: "#1B4C82",
  70: "#18599B", 80: "#1267B4", 90: "#3174C2",
  100: "#4F82C8", 110: "#6790CF", 120: "#7F9ED5",
  130: "#96ADDC", 140: "#ADBCE3", 150: "#C4CBE9",
  160: "#DBDBF0",
};

const lightTheme = createLightTheme(myBrand);
const darkTheme = createDarkTheme(myBrand);
深色模式切换
function App() {
  const [isDark, setIsDark] = useState(false);
  return (
    <FluentProvider theme={isDark ? webDarkTheme : webLightTheme}>
      <Switch
        label="Dark mode"
        checked={isDark}
        onChange={(_, data) => setIsDark(data.checked)}
      />
    </FluentProvider>
  );
}

反模式

  • ❌ 硬编码颜色(color: "#333")— 使用 tokens.colorNeutralForeground1
  • ❌ 在 makeStyles 中使用 CSS 简写属性(border: "1px solid red")— 使用长属性或 shorthands.*
  • ❌ 拼接 classNames 字符串 — 使用 mergeClasses()
  • ❌ 为基于令牌的值使用内联 style 属性 — 使用 makeStyles 和 tokens
  • ❌ 在 v9 项目中从 @fluentui/react(v8)导入 — 使用 @fluentui/react-components
  • ❌ 使用 v8 Stack — 使用 CSS Grid 或 Flexbox
  • ❌ 直接在 CSS 中覆盖颜色系统的 CSS 自定义属性 — 自适应颜色系统由 JS 驱动
  • ❌ 移除焦点指示器 — 这是无障碍访问要求

评论

支持 Markdown