# 组件目录与契约 > 配套:[DESIGN.md](../DESIGN.md)(规则)、[ADDING-A-COMPONENT.md](ADDING-A-COMPONENT.md)(新增流程)、 > [ALRIGHT-DECOMPOSITION.md](ALRIGHT-DECOMPOSITION.md)(参考站实测依据) 状态图例:✅ 已实现 · 🚧 开发中 · 🔜 规划 · ⛔ 不进库(用组合替代) --- ## 1. 组件地图 | 组件 | 层 | 状态 | 一句话 | 关键 props | | --- | --- | --- | --- | --- | | `Icon` | L1 | ✅ | 图标字体封装(446 个字形) | `name` | | `Badge` | L1 | ✅ | 数字角标(18 高,12px) | `count` `tone` `max` | | `ItemBadge` | L1 | ✅ | 状态角标:置顶 / 付费 / HOT | `tone` | | `Tag` | L1 | ✅ | 分类与元信息标签(24 高,13px) | `tone` `variant` `shape` `icon` `dot` | | `Divider` | L1 | ✅ | 分隔线 | `orientation` `variant` `spacing` | | `Typography` | L1 | ✅ | 标题 / 文字 / 段落(Title / Text / Paragraph) | `level` `tone` `size` `lines` | | `Button` | L2 | ✅ | 操作按钮(圆角 / 胶囊) | `variant` `size` `shape` `block` `loading` `icon` | | `IconButton` | L2 | ✅ | 圆形图标按钮(28 / 36 / 44) | `label`(必填) `icon` `variant` `size` `spinning` | | `Input` | L2 | ✅ | 组合式输入框 | `icon` `clearable` `onClear` `shortcut` `inputRef` | | `Textarea` | L2 | ✅ | 多行文本(Markdown / 简介) | `rows` `resize` `invalid` | | `PasswordInput` | L2 | ✅ | 密码输入(锁图标 + 显隐切换) | `icon` `size` `toggle` | | `Switch` | L2 | ✅ | 即时生效的开关 | `checked` `onChange` `size` `label` | | `Checkbox` | L2 | ✅ | 复选框(多选 / 确认) | `checked` `onChange` `label` | | `RadioGroup` | L2 | ✅ | 互斥单选组 | `options` `value` `onChange` `direction` | | `Select` | L2 | ✅ | 受控下拉选择 | `options` `value` `onChange` `placeholder` | | `Segmented` | L2 | ✅ | 视图形态切换 | `options` `value` `onChange` `size` `block` | | `Tabs` | L2 | ✅ | 页内分区切换 | `items` `activeKey` `onChange` `variant` | | `Menu` | L2 | ✅ | 侧栏两级菜单(可折叠动画) | `items` `activeKey` `onSelect` `itemHeight` | | `Breadcrumb` | L3 | ✅ | 路径导航 | `items` `separator` | | `Layout` | L3 | ✅ | 页面骨架:页头 / 侧栏 / 内容 / 页脚 | `header` `sider` `aside` `maxWidth` `gap` `height` | | `Card` | L3 | ✅ | 白色容器(1px 极浅描边) | `as` `padding` `hoverable` | | `Cover` | L3 | ✅ | 比例封面卡(2:3 / 4:3 / 16:9 + 标题遮罩) | `ratio` `src` `caption` `lift` `onClick` | | `Image` | L3 | ✅ | 带比例 / 圆角 / 失败降级的图片 | `ratio` `fit` `radius` `fallback` | | `FormField` | L3 | ✅ | 表单字段排版(标签 + 控件 + 提示/错误) | `label` `hint` `error` `required` | | `Grid` | L3 | ✅ | 卡片列表网格 | `columns` `tabletColumns` `mobileColumns` `gap` `as` | | `Space` | L3 | ✅ | 一维间距容器 | `direction` `gap` `wrap` `align` `justify` | | `Table` | L3 | ✅ | 只读数据表格 | `columns` `rows` `rowKey` `emptyText` | | `Notice` | L4 | ✅ | 说明 / 错误提示条 | `tone` `title` `action` | | `Empty` | L4 | ✅ | 空态 | `text` `action` | | `Result` | L4 | ✅ | 整块结果反馈 | `status` `title` `description` `actions` | | `Modal` | L4 | ✅ | 居中弹窗(原生 dialog) | `open` `onClose` `title` `footer` `size` | | `Drawer` | L4 | ✅ | 侧滑抽屉(原生 dialog) | `open` `onClose` `title` `placement` `width` | | `Tooltip` | L4 | ✅ | hover / 聚焦文字提示 | `content` `placement` | | `Popover` | L4 | ✅ | 点击展开的小面板 | `content` `placement` | | `Toast` | L4 | ✅ | 命令式轻提示 | `toast()` `toast.success()` `` | | `Progress` | L4 | ✅ | 进度条 | `percent` `size` `tone` `showLabel` | | `Steps` | L4 | ✅ | 纵向步骤条 | `items` `current` | | `ScrollTop` | L4 | ✅ | 回到顶部 | `visible` `targetId` `label` | | `Pagination` | L3 | ✅ | 分页 | `page` `total` `pageSize` `onChange` | | `Skeleton` | L4 | ✅ | 骨架屏占位 | `variant` `lines` `width` `height` | | `Spinner` | L4 | ✅ | 加载指示(行内 / 区块) | `size` `label` | | `Avatar` | L1 | ✅ | 头像 / 封面占位(24 / 36 / 48 / 64) | `src` `fallback` `size` `shape` `tone` `verified` | 规划中的组件见 §5;明确不做的见 §6。 --- ## 2. 用哪个?(决策表) | 场景 | 用它 | 不要 | | --- | --- | --- | | 显示数量 | `Badge count={n}` | 用 `Tag` 包数字 | | 显示「置顶 / 付费 / HOT」 | `ItemBadge tone="sticky \| paid \| hot"` | 用 `Tag` 拼渐变 | | 分类、标签、元信息 | `Tag`(默认 neutral 浅底) | 自己写带底色的 span | | 需要强调的分类标签 | `Tag variant="solid"`(实底白字) | 给浅底标签调色值 | | 连接状态 | `Tag tone="success" dot` | 自绘圆点 | | 列表为空、搜索无结果 | `Empty`(可带 `action`) | 复用 `Notice` | | 接口失败、服务不可用 | `Notice tone="error"` | `Empty` | | 一般说明、引导 | `Notice`(`tone="info"`) | 直接写 p | | 一块内容 / 一个面板 | `Card`(`padding` 决定内边距) | 自己写白色 div | | 列表行(应用行、作者行) | 直接 `Space` + 内容 | **套 `Card`**(行不需要底色/边框/阴影) | | 多列排布 | `Grid` | 手写 `display:grid; repeat(...)` | | 一维间距 | `Space` | 每个元素写 margin | | 图标 | `` | 写 `iconfont icon-xxx` 类名 | | 主操作 | `Button`(一页一个 primary) | 多个 primary 并列 | | 登录 / 筛选这类主操作 | `Button shape="pill"` | 圆角按钮凑合 | | 只有图标的操作 | `IconButton label="…"` | `` | | 密码输入(登录 / 改密) | `PasswordInput`(锁图标 + 显隐切换) | 自己拼 `Input` + 眼睛按钮(容易漏掉切换) | | 分隔内容块 | `Divider` | `border-top` 手写 | | 长内容回到顶部 | `ScrollTop` | 自己写 fixed 按钮 | --- ## 3. 现有组件契约 每个组件按固定结构写:用途 / 不该用在哪 / 解剖 / Props / 规则 / 展示页。新增组件照抄这个结构(模板见 §8)。 ### 3.1 Icon ✅ - **用途**:把图标字体的字形封装成组件,颜色与字号继承当前文字。 - **不该用在哪**:需要多色图标、需要 SVG 描边可控的场景。 - **解剖**:单个 ``,`aria-hidden="true"`。 - **Props**:`name: IconName`(13 个字形)+ 原生 `` 属性。 - **规则**:图标一律视为装饰;字号在父级用 `font-size` 控制;新增字形走 §7 流程。 - **展示页**:`#icons` ### 3.2 Badge ✅ - **用途**:数量角标(1、18、99+)。 - **不该用在哪**:状态文字(用 `ItemBadge` 或 `Tag`)。 - **解剖**:`inline-flex` 胶囊,18px 高、12px 字,等宽数字。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `count` | `number` | 必填 | 数字 | | `tone` | `'danger' \| 'primary' \| 'neutral'` | `'danger'` | 配色 | | `max` | `number` | `99` | 超过显示 `N+`;`0` 表示不截断 | - **规则**:不负责定位;压在标题右上角由使用方用 `className` 绝对定位。 - **展示页**:`#marks` ### 3.3 ItemBadge ✅ - **用途**:标题前的状态角标——「置顶 / 付费 / HOT / 草稿」。 - **不该用在哪**:数量(`Badge`)、分类(`Tag`)。 - **解剖**:18px 高、radius 4、12px 加粗白字、红/橙渐变底(参考站 `.item-badge`)。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `tone` | `'hot' \| 'sticky' \| 'paid' \| 'neutral'` | `'hot'` | hot/sticky 红渐变,paid 橙渐变,neutral 灰底 | | `children` | `ReactNode` | 必填 | 角标文字(建议 2–4 字) | - **规则**:只做状态提示,不可点击;和标题并排时用 `Space gap="sm"`,不要加 margin。 - **展示页**:`#marks` ### 3.4 Tag ✅ - **用途**:分类、标签、元信息。 - **不该用在哪**:数量(`Badge`)、状态角标(`ItemBadge`)、可点击筛选(暂无交互态)。 - **解剖**:24px 高胶囊、13px 字,左侧可带图标或状态点;实底变体用于强调。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `tone` | `'neutral' \| 'primary' \| 'success' \| 'warning' \| 'danger'` | `'neutral'` | 语义配色 | | `variant` | `'soft' \| 'solid'` | `'soft'` | 浅底 / 实底白字 | | `shape` | `'pill' \| 'rounded'` | `'pill'` | 胶囊 / 小方块(元信息前缀用) | | `icon` | `ReactNode` | — | 前置图标(如分类图标) | | `dot` | `boolean` | `false` | 前置 6px 状态点 | - **规则**:标签是内容宽度;放进纵向 flex 时用 `align-items: flex-start`,否则会被拉满。 - **展示页**:`#marks` ### 3.5 Divider ✅ - **用途**:横向分隔内容块、纵向分隔并排元素。 - **解剖**:`role="separator"` 的普通 div,靠 border 画线。 - **Props**:`orientation: 'horizontal' | 'vertical'`、`variant: 'solid' | 'dashed'`、`spacing: 'sm' | 'md'`。 - **规则**:横向自带上下外边距(唯一带 margin 的基础组件),纵向用于 `Space` 内部。 - **展示页**:`#layouts` ### 3.6 Button ✅ - **用途**:页面操作。 - **不该用在哪**:只有图标(`IconButton`)、纯跳转链接(``)。 - **解剖**:`[icon] [spinner] [label]`,高度 32 / 36,左右内边距 20。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `variant` | `'primary' \| 'secondary' \| 'outline' \| 'ghost' \| 'danger'` | `'primary'` | 语义 | | `size` | `'sm' \| 'md'` | `'md'` | 32 / 36px | | `shape` | `'rounded' \| 'pill'` | `'rounded'` | 6px 圆角 / 胶囊 | | `block` | `boolean` | `false` | 占满一行 | | `loading` | `boolean` | `false` | 自动禁用 + `aria-busy` | | `spinning` | `boolean` | `false` | 图标原地旋转(不换转圈),用于刷新类动作 | | `icon` | `ReactNode` | — | 文字左侧图标 | | `…rest` | `ButtonHTMLAttributes` | — | `type` 默认 `"button"` | - **规则**:一屏一个 `primary`;hover 是 `opacity .8`(参考站同款),不要改背景色;禁用是浅底弱字。 - **展示页**:`#buttons` ### 3.7 IconButton ✅ - **用途**:圆形图标按钮(顶栏入口、更多、刷新、关闭)。 - **解剖**:正圆 + 居中图标;`spinning` 时图标旋转。 - **Props**:`label`(**必填**,进 `aria-label` 与 `title`)、`icon`(必填)、 `variant: 'ghost' | 'soft'`、`size: 'xs' | 'sm' | 'md'`(28 / 36 / 44,图标 16 / 20 / 24)、`spinning`、`…rest`。 - **规则**:没有 `label` 不允许合并;`spinning` 只用于「操作进行中」,不做装饰动画。 - **展示页**:`#buttons` ### 3.8 Input ✅ - **用途**:搜索框、筛选输入、表单单行输入。 - **不该用在哪**:多行文本(未来 `Textarea`)、下拉选择(未来 `Select`)。 - **解剖**:`[icon] [input] [suffix] [shortcut] [clear]`,外层容器负责边框与高度(36px、`1px solid gray-3`)。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `icon` | `IconName` | — | 左侧图标 | | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 32 / 36 / 44px | | `suffix` | `ReactNode` | — | 右侧插槽:图标按钮、单位等;排在清除按钮之前 | | `clearable` | `boolean` | `false` | 有值且传了 `onClear` 才显示清除 | | `onClear` | `() => void` | — | 清除回调 | | `shortcut` | `string` | — | 右侧提示(如 `⌘K`),仅展示 | | `inputRef` | `Ref` | — | 拿真实 input 做聚焦 | | `className` / `style` | — | — | **作用在外层容器** | | `…rest` | `InputHTMLAttributes` | — | `onChange` 是原生事件 | - **规则**:与 `Button size="md"` 同高 36;focus 只把边框换成主色(**不再叠 outline**:文本框点击时也会命中 `:focus-visible`,叠环会出现「双框」,2026-10-28 修);`type="password"` 时隐藏 Edge 原生显隐按钮(`::-ms-reveal`),否则会和 `PasswordInput` 的眼睛叠成两个。 - **展示页**:`#inputs` ### 3.9 Card ✅ - **用途**:白色容器(面板、卡片、详情块)。 - **不该用在哪**:列表行、纯排布容器。 - **解剖**:`1px solid gray-1`(几乎不可见)+ radius 12 + `shadow-card`(1%),内边距由 `padding` 决定。 - **Props**:`as: 'div' | 'section' | 'article' | 'aside'`、`padding: 'none' | 'sm' | 'md' | 'lg'`(0 / 12 / 20 / 24)、`hoverable`、`className`、`style`。 - **规则**:卡片不提供标题栏;「色条 + 标题 + 角标 + 更多」由页面组合;`hoverable` 只加深阴影,不做位移。 - **展示页**:`#cards` ### 3.10 Grid ✅ - **用途**:卡片列表的多列排布。 - **不该用在哪**:一维间距(`Space`)、页面整体骨架(CSS layout)。 - **解剖**:`display:grid`,列数走 CSS 变量,断点内建:`>1100`、`≤1100`、`≤720`。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `columns` | `number` | `4` | 宽屏列数 | | `tabletColumns` | `number` | `columns / 2`(至少 2) | ≤1100px | | `mobileColumns` | `number` | `1` | ≤720px | | `gap` | `'sm' \| 'md' \| 'lg'` | `'md'` | 8 / 12 / 16 | | `as` | `'div' \| 'ul'` | `'div'` | 列表语义 | - **规则**:不要在父级用 `flex-direction: column` 包住含比例图片的 Grid(会被压扁,见 DESIGN §9)。 - **展示页**:`#layouts` ### 3.11 Space ✅ - **用途**:一组元素之间的一维间距。 - **解剖**:`display:flex` + `gap`,方向/对齐/间距都用语义档位。 - **Props**:`direction: 'row' | 'column'`、`gap: 'xs' | 'sm' | 'md' | 'lg'`(4 / 8 / 12 / 16)、`wrap`、`align: 'start' | 'center' | 'end' | 'stretch'`、`justify: 'start' | 'center' | 'end' | 'between'`。 - **规则**:间距只用档位,不传像素;纵向排列 + 左对齐要给 `align="start"`。 - **展示页**:`#layouts` ### 3.12 Notice ✅ - **用途**:页面级说明与错误提示。 - **不该用在哪**:表单字段校验、浮层提示(未来 `Toast`)。 - **解剖**:标题 + 正文 + 可选操作按钮;错误态 `role="alert"`。 - **Props**:`tone: 'info' | 'error'`、`title`(必填)、`children`、`action: { label, onClick }`。 - **规则**:错误态只用于「确实失败」;同一区域不要堆两条以上提示。 - **展示页**:`#feedback` ### 3.13 Empty ✅ - **用途**:列表为空、搜索无结果、内容未就绪。 - **解剖**:一句说明 + 可选操作区。 - **Props**:`text`(默认「暂无内容」)、`action`。 - **规则**:空态不要用红色/错误色;能给出下一步操作时一定给。 - **展示页**:`#feedback` ### 3.14 ScrollTop ✅ - **用途**:长内容回到顶部。 - **解剖**:固定在视口右侧中部(`top:50%`、`right:24`)的 42px 圆钮,`visible` 控制淡入淡出。 - **Props**:`visible`(必填)、`targetId`(滚动容器 id;不传滚窗口)、`label`(默认「回到顶部」)、`offset`(距右侧 px,默认 24)。 - **规则**:滚动容器在页面里滚动时必须传 `targetId`;隐藏时 `tabIndex=-1`。 - **展示页**:`#scrolltop` ### 3.15 Avatar ✅ - **用途**:头像、应用图标、封面占位。 - **解剖**:裁切层(图片 / 首字) + 外置认证角标,两者分层,角标不会被圆角切掉。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `src` | `string` | — | 图片;加载失败自动降级 | | `alt` | `string` | `''` | 图片替代文本 | | `fallback` | `string` | `'•'` | 无图时的字符(通常取首字) | | `icon` | `ReactNode` | — | 无图时的图标(优先于 fallback),用于缺省头像 | | `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | 24 / 36 / 48 / 64px | | `shape` | `'circle' \| 'square'` | `'circle'` | 人/应用用圆,图标封面用方 | | `tone` | `'neutral' \| 'primary'` | `'neutral'` | 无图底色:浅灰 / 品牌浅渐变(资料卡) | | `verified` | `boolean` | `false` | 右下角认证角标(12 / 16 / 20px) | - **规则**:`fallback` 传一个字符;资料卡用 `xl` + `tone="primary"`,列表里用 `lg`,紧凑行用 `sm`;不要给头像加边框。 - **展示页**:`#avatars` ### 3.16 Modal ✅ - **用途**:需要打断流程的确认 / 表单 / 说明。 - **不该用在哪**:轻量反馈(等 `Toast`)、页面内的展开收起(用条件渲染 + 动画)。 - **解剖**:原生 ``(焦点陷阱、Esc、背景 inert 由浏览器提供)+ 遮罩 + 标题栏 + 正文 + 底部操作区。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `open` | `boolean` | 必填 | 受控开关 | | `onClose` | `() => void` | 必填 | Esc / 遮罩 / 关闭按钮都会调用 | | `title` | `ReactNode` | 必填 | 标题,同时作为 `aria-labelledby` | | `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | 300 / 460 / 640 | | `closeOnOverlay` | `boolean` | `true` | 点遮罩是否关闭 | | `footer` | `ReactNode` | — | 底部按钮区 | - **规则**:打开时锁背景滚动;危险操作必须二次确认;底部按钮顺序是「取消在左、主操作在右」。 - **展示页**:`#modal` ### 3.17 Pagination ✅ - **用途**:列表/搜索结果的翻页。 - **解剖**:上一页 + 页码(超长时省略号折叠)+ 下一页;32×32、radius 4、当前页主色实底。 - **Props**:`page`(从 1 开始)、`total`、`pageSize`(默认 10)、`onChange(page)`、`siblings`(当前页左右各几个,默认 1)。 - **规则**:首尾页固定;边界上「上一页/下一页」禁用;总数文案由页面自己写(用 `Space justify="between"`)。 - **展示页**:`#pagination` ### 3.18 Typography(Title / Text / Paragraph)✅ - **用途**:页面与内容排版——标题层级、文字层级、正文段落。 - **不该用在哪**:控件内部的文字(按钮/输入自己管),不要为了「加个字号」而套一层 `Text`。 - **解剖**:三个组件共用一个样式模块;`Title` 按 `level` 输出真实 `h1–h4`,`Text` 是 `span`/`p`/`div`,`Paragraph` 用 `-webkit-line-clamp` 做行数截断。 - **Props**: | 组件 | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | --- | | `Title` | `level` | `1 \| 2 \| 3 \| 4` | `2` | 24/32、18/26、16/24、14/22 | | `Title` | `weight` | `'normal' \| 'medium' \| 'semibold' \| 'strong'` | `'medium'` | 400 / 500 / 600 / 700;参考站的 600 用 `semibold` | | `Title` | `as` | `'h1' \| 'h2' \| 'h3' \| 'h4' \| 'div'` | 按 level | 换语义标签 | | `Text` | `tone` | `'main' \| 'secondary' \| 'sub' \| 'muted'` | `'main'` | 文字层级 | | `Text` | `size` | `'xs' \| 'sm' \| 'md' \| 'base' \| 'lg'` | `'md'` | 12 / 13 / 14 / 16 / 18 | | `Text` | `strong` / `truncate` | `boolean` | `false` | 500 字重 / 单行省略 | | `Paragraph` | `tone` | `'main' \| 'secondary' \| 'sub'` | `'sub'` | 文字层级 | | `Paragraph` | `size` | `'sm' \| 'md' \| 'base'` | `'base'` | 13 / 14 / 16,长文正文用 md | | `Paragraph` | `leading` | `'base' \| 'relaxed'` | `'base'` | relaxed = 1.9 行高(阅读型) | | `Paragraph` | `lines` | `number` | — | 最多几行,超出省略 | - **规则**:组件不带外边距,段落间距交给 `Space`;不要在页面里另写 `font-size`。 - **展示页**:`#typography` ### 3.19 Skeleton ✅ - **用途**:内容加载前的占位(列表首屏、刷新、分页加载)。 - **不该用在哪**:按钮内的 loading(`Button` 自带 spinner)、整页空态(`Empty`)。 - **解剖**:`text`(多行文本条,最后一行收短)/ `rect`(封面)/ `circle`(头像),占位块上有一层扫光。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `variant` | `'text' \| 'rect' \| 'circle'` | `'text'` | 形状 | | `lines` | `number` | `1` | 仅 text:行数 | | `width` / `height` | `number \| string` | — | rect 默认 100% / 120px,circle 默认 40 | | `className` / `style` | — | — | 外边距等布局微调 | - **规则**:形状必须和真实内容一致(否则加载完成后跳动);整块区域标 `aria-busy="true"`;骨架自身 `aria-hidden`;`prefers-reduced-motion` 下停止扫光。 - **展示页**:`#skeleton` ### 3.20 Spinner ✅ - **用途**:行内或区块的加载指示(同步状态、面板刷新)。 - **不该用在哪**:按钮内(`Button loading` 自带)、文字占位(`Skeleton`)。 - **解剖**:2px 圆环,颜色取主色,`role="status"` + `aria-label`。 - **Props**:`size: 'sm' | 'md'`(14 / 20)、`label`(默认「加载中」)、`className`。 - **规则**:颜色继承 `currentColor`(默认主色,可被外层覆盖);`prefers-reduced-motion` 下降到 2.4s。 - **展示页**:`#spinner` ### 3.21 Switch ✅ - **用途**:设置项的**即时**开关。 - **不该用在哪**:需要点「保存」才生效的表单(用 `Checkbox` + 提交按钮)。 - **解剖**:原生 `button` + `role="switch"`,轨道 + 白色圆点;空格/回车可切换。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `checked` | `boolean` | 必填 | 受控状态 | | `onChange` | `(checked: boolean) => void` | 必填 | 切换回调 | | `size` | `'sm' \| 'md'` | `'md'` | 32×18 / 40×22 | | `disabled` | `boolean` | `false` | 禁用 | | `label` | `string` | — | 无障碍名称:旁边没有文字时必填 | - **规则**:旁边配文字时用 `Text` + `Space justify="between"`,不要自己做一套行布局。 - **展示页**:`#switch` ### 3.22 Checkbox ✅ - **用途**:多选、需要确认的选项。 - **解剖**:原生 `input[type=checkbox]`(视觉隐藏)+ 自绘 16px 方块 + label 文本,点击文字也能勾选。 - **Props**:`checked`、`onChange(checked)`、`label`(必填,同时作为无障碍名称)、`disabled`。 - **规则**:多选组用 `Space direction="column"` 排列;禁用态只降对比,不隐藏。 - **展示页**:`#checkbox` ### 3.23 RadioGroup ✅ - **用途**:互斥选项组。 - **解剖**:原生 `input[type=radio]`(隐藏)+ 自绘圆点;同组共享 `name`,方向键在组内移动。 - **Props**:`options: { value, label, disabled? }[]`、`value`、`onChange(value)`、`direction: 'row' | 'column'`、`disabled`。 - **规则**:2–3 个短选项用 row;设置类用 column。单个开/关用 `Switch`,多选用 `Checkbox`。 - **展示页**:`#radio` ### 3.24 Segmented ✅ - **用途**:视图形态切换(网格/列表、全部/收藏)。 - **Props**:`options: { value, label, icon? }[]`、`value`、`onChange(value)`、`size: 'sm' | 'md'`、`block`。 - **规则**:只切展示、不切内容分区(后者用 `Tabs`);选中项白底 + 轻阴影。 - **展示页**:`#segmented` ### 3.25 Select ✅ - **用途**:受控的单值下拉选择。 - **解剖**:触发器是原生 button(`aria-haspopup="listbox"`),展开为 `role="listbox"`;点外部 / Esc 关闭,↑↓ 移动、Enter 选择。 - **Props**:`options`、`value`、`onChange(value)`、`placeholder`、`disabled`。 - **规则**:多选与搜索不在范围内(用 `Input` + 列表组合);高度与 `Input` 一致(36)。 - **展示页**:`#select` ### 3.26 Breadcrumb ✅ - **用途**:详情页路径导航。 - **Props**:`items: { label, href? }[]`、`separator`(默认 `/`)、`onNavigate(href)`(接管点击,用于 SPA 路由;传了就阻止默认跳转)。 - **规则**:最后一项忽略 `href`,并标 `aria-current="page"`;不传 `onNavigate` 时走普通链接(整页跳转)。 - **展示页**:`#breadcrumb` ### 3.27 Tabs ✅ - **用途**:页内内容分区切换。 - **Props**:`items: { key, label, disabled? }[]`、`activeKey`、`onChange(key)`、`variant: 'line' | 'pill'`。 - **规则**:只渲染标签栏,面板由页面用 `role="tabpanel"` 渲染;← → 移动、Home/End 跳首尾。 - **展示页**:`#tabs` ### 3.28 Menu ✅ - **用途**:侧栏菜单(一层折叠 + 两级)。 - **Props**:`items: { key, label, icon?, children? }[]`、`activeKey`、`onSelect(key)`、`defaultOpenKeys`、`itemHeight`(一级行高,默认 36)。 - **规则**:数据无关,业务树由页面转换;含 `activeKey` 的父级默认展开,父子均用 `aria-expanded` / `aria-current` 标注;折叠箭头是 CSS chevron(视觉回归:从字形改为边框绘制)。 - **展示页**:`#menu` ### 3.29 Toast(toast / Toaster)✅ - **用途**:操作反馈,几秒后自动消失。 - **解剖**:模块级 store + `useSyncExternalStore`;`Toaster` 挂在应用根节点,只挂一次。 - **API**:`toast(message, { tone?, duration? })`、`toast.success / .error`、`dismissToast(id)`。 - **规则**:命令式调用;页面内常驻提示用 `Notice`,整块状态用 `Result`;文案一句话,不放按钮。 - **展示页**:`#toast` ### 3.30 Table ✅ - **用途**:数据表格(只读)。 - **Props**:`columns: { key, title, width?, align? }[]`、`rows: Record[]`、`rowKey`(默认 `id`)、`emptyText`。 - **规则**:排序 / 筛选 / 分页由页面组合,组件不内置交互;空数据渲染 `emptyText`。 - **展示页**:`#table` ### 3.31 Result ✅ - **用途**:整块的完成 / 失败 / 警示 / 说明反馈。 - **Props**:`status: 'success' | 'error' | 'warning' | 'info'`、`title`、`description`、`actions`。 - **规则**:只用于整页或整块状态;行内提示用 `Notice`,轻量反馈用 `toast`。 - **展示页**:`#result` ### 3.32 Progress ✅ - **用途**:任务 / 存储进度。 - **Props**:`percent`(夹在 0–100)、`size: 'sm' | 'md'`(4 / 8px)、`tone`、`showLabel`。 - **规则**:纯展示;带 `role="progressbar"` 与 `aria-valuenow`。 - **展示页**:`#progress` ### 3.33 Steps ✅ - **用途**:有顺序的流程(发布、导入向导)。 - **Props**:`items: { title, description? }[]`、`current`(从 0 开始)。 - **规则**:`index < current` 视为已完成;当前项加粗 + 主色描边。 - **展示页**:`#steps` ### 3.34 Drawer ✅ - **用途**:侧滑面板(筛选、设置、详情),不打断主流程。 - **解剖**:与 `Modal` 同源(原生 ``),区别是贴边、全高、滑入动画。 - **Props**:`open`、`onClose`、`title`、`placement: 'right' | 'left'`、`width`(默认 360)、`footer`。 - **规则**:需要打断流程的确认用 `Modal`;打开时锁背景滚动。 - **展示页**:`#drawer` ### 3.35 Tooltip ✅ - **用途**:hover / 聚焦时的一行文字说明。 - **Props**:`content`、`placement: 'top' | 'bottom'`、`children`(建议可聚焦元素)。 - **规则**:纯 CSS 定位,不做自动翻转;交互内容用 `Popover`。 - **展示页**:`#tooltip` ### 3.36 Popover ✅ - **用途**:点击展开的小面板(说明、快捷操作)。 - **Props**:`content`、`children`、`placement: 'bottom-start' | 'bottom-end'`。 - **规则**:点外部 / Esc 关闭;内容复杂或需要滚动时改用 `Drawer` / `Modal`。 - **展示页**:`#tooltip` ### 3.37 Layout ✅ - **用途**:页面外壳——页头 / 侧栏 / 内容 / 右栏 / 页脚的区域划分与最大宽度。 - **不该用在哪**:应用内的小区块(用 `Card` + `Grid`);业务导航内容(由页面作为 slot 传入)。 - **解剖**:`flex` 纵向三行(header / body / footer),body 内是 `sider + main + aside`;main 里再套一层限宽容器(`maxWidth`)。 - **Props**: | prop | 类型 | 默认 | 说明 | | --- | --- | --- | --- | | `header` | `ReactNode` | — | 页头,默认吸顶(半透明 + 模糊) | | `sider` | `ReactNode` | — | 左侧栏,固定宽度 | | `aside` | `ReactNode` | — | 右侧栏,固定宽度(目录 / 聚合 / 广告位) | | `footer` | `ReactNode` | — | 页脚 | | `children` | `ReactNode` | 必填 | 内容区 | | `maxWidth` | `number \| 'full'` | `1280` | 内容最大宽度 | | `siderWidth` | `number` | `260` | 左侧栏宽度 | | `asideWidth` | `number` | `300` | 右侧栏宽度 | | `stickyHeader` | `boolean` | `true` | 页头是否吸顶 | | `contained` | `boolean` | `false` | 页身套一层居中容器(**页头始终通栏**,页头内容自己限宽) | | `gap` | `number` | `0` | 侧栏 / 内容 / 右栏之间的间距(px) | | `contentPadding` | `'none' \| 'sm' \| 'md' \| 'lg'` | `'md'` | 内容区留白:0 / 12 / 20 / 24 | | `contentOffset` | `number` | `0` | 内容区顶部偏移(px),给页头下的悬浮搜索/工具条留位 | | `gutter` | `number` | `0` | contained 容器的左右留白(px) | | `headerHeight` | `number` | `60` | 页头最小高度(px) | | `headerVariant` | `'blur' \| 'solid'` | `'blur'` | 半透明模糊 / 实底 + 下边框 | | `siderBordered` | `boolean` | `true` | 侧栏右侧分隔线 | | `height` | `'auto' \| 'screen'` | `'auto'` | screen:锁视口,适合应用型界面 | | `scrollable` | `boolean` | `false` | 内容区内部滚动(配 `height="screen"`) | | `hideScrollbar` | `boolean` | `false` | 内部滚动时隐藏滚动条(仍可滚轮/键盘滚动) | | `contentId` | `string` | — | 内容区 id(供 ScrollTop 等按 id 滚动) | - **规则**:Layout 不写业务内容,也不带背景装饰(需要渐变/光晕时由页面自己放绝对定位层);响应式在组件内处理——≤1200px 右栏堆到内容下方、≤1100px 侧栏堆到内容上方,**内容都不隐藏**。 - **常用配方**:顶栏+内容(首页)、左栏+内容(管理页)、内容+右栏(文章)、三栏(工作台)、窄内容(设置/阅读),展示页用 `Segmented` 切换。 - **展示页**:`#layout` ### 3.38 Cover ✅ - **用途**:比例封面卡——海报(2:3)、图文(4:3)、宽图(16:9)统一用「图片 + 底部压暗层 + 标题」。 - **不该用在哪**:需要叠加角标 / 操作按钮的封面(用 `Card padding="none"` 里放 `Cover` + 角标);纯头像用 `Avatar`。 - **解剖**:`aspect-ratio` 容器 + `object-fit: cover` 图片 + `--su-cover-scrim` 渐变遮罩;传 `onClick` 时整块变成 `