This commit is contained in:
oneao committed 2026-10-09 17:32:14 +08:00
1 parent e99a9fb274
commit 0be0b0767a
788 files changed
+112023 -14941

No files matched your search

@@ -1,2 +0,0 @@
title: UI 组件库
icon: i-lucide-component
@@ -1,2 +0,0 @@
title: 使用
icon: i-lucide-book-open
@@ -1,2 +0,0 @@
title: 通用组件
icon: i-lucide-boxes
@@ -1,2 +0,0 @@
title: 数据录入
icon: i-lucide-text-cursor-input
@@ -1,2 +0,0 @@
title: 浮层与导航
icon: i-lucide-layers
@@ -1,2 +0,0 @@
title: 反馈
icon: i-lucide-bell
@@ -1,2 +0,0 @@
title: 数据展示
icon: i-lucide-table
@@ -11,15 +11,13 @@ description: 日期 / 日期时间 / 范围选择与时间滚轮(DatePicker /
## 基础用法
:::demo{name="date/date-basic"}
:::
<demo vue="date/date-basic.vue" />
## 精度与格式
`format` 同时决定三件事:**面板粒度、展示格式、绑定值格式的默认值**;`valueFormat` 只影响绑定值。
:::demo{name="date/date-format"}
:::
<demo vue="date/date-format.vue" />
| 写法 | 面板 | 绑定值 |
| --- | --- | --- |
@@ -33,8 +31,7 @@ description: 日期 / 日期时间 / 范围选择与时间滚轮(DatePicker /
## 禁用日期与清除
:::demo{name="date/date-disabled"}
:::
<demo vue="date/date-disabled.vue" />
`disabledDate` 接收 `Date`,返回 `true` 表示该日不可选(禁用的格子不可聚焦、不可点击、不参与 hover 预览)。`timeDefault` 只在「没有值时点开面板」时决定时间初值:`'start'` 当天 00:00、`'end'` 当天 23:59:59、不传用当前时刻。
@@ -42,8 +39,7 @@ description: 日期 / 日期时间 / 范围选择与时间滚轮(DatePicker /
输入框可以直接键入,容错规则如下:
:::demo{name="date/manual-input"}
:::
<demo vue="date/manual-input.vue" />
| 输入 | 结果 |
| --- | --- |
@@ -58,15 +54,13 @@ description: 日期 / 日期时间 / 范围选择与时间滚轮(DatePicker /
两次点击确定起止;第二次点击的位置比起点更早时会**自动交换**。只点了一次就关闭面板不会写入值。
:::demo{name="date/range-basic"}
:::
<demo vue="date/range-basic.vue" />
## 时间滚轮
`TimeSelect` 绑定 `Date`,`fields` 决定显示哪几列,`hour12` 追加 am/pm 列。
:::demo{name="date/time-select"}
:::
<demo vue="date/time-select.vue" />
## API
@@ -162,11 +156,25 @@ export interface TimeSelectProps {
| `compareDay` / `compareDate` / `isInRange` / `addMonth` / `combineDateTime` | — | 比较与合成 |
| `listDateSegments` / `resolveDateSegment` / `stepDateSegment` | — | 手输光标分段与微调 |
### 样式变量
面板形态(尺寸与颜色)都可通过同名 CSS 变量覆盖:
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `--g3-calendar-main-width` | `252px` | 日历主体定宽(7 列 × 36px)。定宽而非被输入框拉伸 |
| `--g3-calendar-height` | `292px` | 日历区与时间列共用的高度(表头 40 + 星期行 36 + 6 行 × 36) |
| `--g3-calendar-cell-size` | `24px` | 单元格内块尺寸:选中 / 今日方块的边长、范围背景带的厚度 |
| `--g3-time-col-width` | `56px` | 时间列每列宽度(时 / 分 / 秒各一列) |
| `--g3-time-item-height` | `28px` | 时间列单项高度 |
| `--g3-time-select-height` | `196px` | `G3TimeSelect` 独立使用时的整块高度(在面板内改由日历区高度决定) |
## 实现说明
- **零第三方依赖**:fms 版依赖 dayjs + 两个插件,这里用 `date/date-utils.ts` 自研实现(格式化 token、严格解析、段定位、微调步进),保持组件库只依赖 `vue`;
- **值的内部表示**:内部一律用 `Date` 运算,**对外一律字符串**。展示用 `format`、绑定值用 `valueFormat`,两者可以不同(展示到分钟、绑定到秒);
- **不污染绑定值**:手输过程只改本地文本,失焦 / 回车才提交;非法输入进错误态并回填旧值——表单里绝不允许出现「半天没法提交但看不出哪里错」的状态;
- **面板是草稿值**:有时间精度时,点选只改草稿、点「确定」才提交;没有时间精度时点选即提交并关闭。关闭面板会丢弃草稿;
- **定位复用 Popover**(`trigger="manual"`、`followTriggerWidth`),因此弹窗内打开日期面板、滚动跟随、Esc 关闭这些行为与 Select 完全一致;
- **定位复用 Popover**(`trigger="manual"`、`placement="bottom-start"`、`unwrapped`):弹窗内打开日期面板、滚动跟随、Esc 关闭这些行为与 Select 一致;但面板**不**跟随触发框宽度(Select 才用 `followTriggerWidth`),日历定宽 252px,输入框再宽也不会把日期格子撑散;
- **单元格形态对齐 antd**:内块是 24px 的**圆角方块**(不是圆形);「今日」用 1px 主色**描边**(不改文字色,选中时描边与填充叠加);范围高亮是厚度 24px 的**整条背景带**(起止两端各染半段、端点内块只在朝外一侧倒角),所以跨格的范围能连成一条连续色带;
- 键盘可达性:日历是 `role="grid"`,格子为 `role="gridcell"`,只有当前格子 `tabindex=0`(roving tabindex),`← → ↑ ↓ Home End PageUp PageDown` 都能操作,且会跳过禁用日期;底部时间列是 `role="listbox"`,`↑ ↓` 步进 1、`PageUp/PageDown` 步进 5。
@@ -15,30 +15,25 @@ description: 页码、每页条数、快速跳转与总条数
## 基础用法
:::demo{name="pagination/basic"}
:::
<demo vue="pagination/basic.vue" />
## 每页条数
`showSizeChanger` 显示每页条数下拉;`showSizeChange` 只在该值变化时触发,**先于** `change`。
:::demo{name="pagination/size-changer"}
:::
<demo vue="pagination/size-changer.vue" />
## 快速跳转与总条数
:::demo{name="pagination/quick-jumper"}
:::
<demo vue="pagination/quick-jumper.vue" />
`#showTotal` 插槽作用域是 `{ total, from, to }`:
:::demo{name="pagination/total"}
:::
<demo vue="pagination/total.vue" />
## 只有一页时隐藏
:::demo{name="pagination/hide-on-single"}
:::
<demo vue="pagination/hide-on-single.vue" />
## 与列表联动
@@ -17,29 +17,25 @@ description: 可拖拽调整大小的多面板布局,支持左右 / 上下与
`G3SplitterPanel` 放 `G3Splitter` 内。给了 `defaultSize` / `size` 的面板尺寸固定,其余面板平分剩余空间。
:::demo{name="splitter/basic"}
:::
<demo vue="splitter/basic.vue" />
## 上下分栏
`direction="vertical"` 时用 `defaultSize` 控制高度;`barOnHover` 默认 `true`(分割线只在 hover / 聚焦 / 拖拽时显示)。
:::demo{name="splitter/vertical"}
:::
<demo vue="splitter/vertical.vue" />
## 尺寸约束
`min` / `max` 支持数字(px)或百分比字符串;`resizable="false"` 的面板不参与拖动(两侧都必须可调,分隔条才能拖)。
:::demo{name="splitter/constraints"}
:::
<demo vue="splitter/constraints.vue" />
## 嵌套
外层左右、内层上下,可以组合出常见的工作台布局。
:::demo{name="splitter/nested"}
:::
<demo vue="splitter/nested.vue" />
## 键盘操作
@@ -17,36 +17,31 @@ description: 在同一区域切换多个内容面板,首次激活才挂载、
`G3TabPane` 只作声明,不渲染 DOM:`tab-key` 是唯一标识(不传按声明顺序取索引),`label` 是标签文字。
:::demo{name="tabs/basic"}
:::
<demo vue="tabs/basic.vue" />
## 数据源写法
`items` 提供时优先于插槽;`content` 可以是字符串、VNode 或返回 VNode 的函数。标签动态来自接口时用这种写法。
:::demo{name="tabs/items"}
:::
<demo vue="tabs/items.vue" />
## 位置
`placement="left" | "right"` 时标签栏纵向排列,指示条自动贴到对应边。
:::demo{name="tabs/placement"}
:::
<demo vue="tabs/placement.vue" />
## 视觉风格
`type="line"` 是下划线指示条(默认),`type="pill"` 是胶囊式;`centered` 让标签栏居中。
:::demo{name="tabs/type"}
:::
<demo vue="tabs/type.vue" />
## 只要标签栏
`navOnly` 时不渲染内容区,内容由外部(路由、分栏)控制;配合 `#label`、`#leftExtra`、`#rightExtra` 可以定制标签与两端内容。
:::demo{name="tabs/nav-only"}
:::
<demo vue="tabs/nav-only.vue" />
## 键盘操作
@@ -18,15 +18,13 @@ description: 层级数据展示与操作:选中、勾选联动、过滤、拖
`treeData` 是嵌套结构,默认按 `{ key, title, children }` 取值;选中值用 `v-model:selected-keys`。
:::demo{name="tree/basic"}
:::
<demo vue="tree/basic.vue" />
## 勾选与半选
`checkable` 开启复选框;**默认是父子联动**(选中父节点自动勾选全部子孙,部分选中时父节点显示半选)。`checkStrictly` 关闭联动,父子互不影响。
:::demo{name="tree/checkable"}
:::
<demo vue="tree/checkable.vue" />
`check` 事件的载荷是 `{ checked, halfChecked }`,`checked` 已包含联动推导出的子孙节点,可以直接提交给后端。
@@ -39,15 +37,13 @@ description: 层级数据展示与操作:选中、勾选联动、过滤、拖
| 完全受控 | 传 `expanded-keys` + `v-model:expanded-keys` |
| 选中/勾选后自动展开祖先 | `auto-expand-parent` |
:::demo{name="tree/expand"}
:::
<demo vue="tree/expand.vue" />
## 过滤
`filter` 传关键词:命中的节点与它的**祖先链**会显示,命中文字高亮,命中路径自动展开(这个自动展开不会写进你的 `expandedKeys`)。
:::demo{name="tree/filter"}
:::
<demo vue="tree/filter.vue" />
`#title` 插槽存在时,内置高亮不生效——因为标题完全由你渲染。需要自带高亮时请在自己的插槽里处理。
@@ -55,15 +51,13 @@ description: 层级数据展示与操作:选中、勾选联动、过滤、拖
`lazy` 模式下,展开一个「没有 children 且未加载过」的节点会触发 `load`;你请求完把 children 写回数据,并把 key 记入 `loaded-keys`(组件据此停止显示加载图标、并判断是否还有子节点)。
:::demo{name="tree/lazy"}
:::
<demo vue="tree/lazy.vue" />
## 拖拽排序
`draggable` 开启拖拽。落点按行的上 25% / 中 50% / 下 25% 分成 `before` / `inside` / `after`,你需要在 `drop` 事件里自己重排数据——组件**不会**直接修改 `tree-data`。
:::demo{name="tree/draggable"}
:::
<demo vue="tree/draggable.vue" />
`externalDragKey` 可以把「树外拖入」的来源(如字段库)映射成拖拽键,从而让树内节点成为落点(用于「把字段拖进目录」这类场景)。
@@ -71,15 +65,13 @@ description: 层级数据展示与操作:选中、勾选联动、过滤、拖
`contextMenu` 传数组或 `(node, key) => items`:节点上右键收到该节点,空白处右键收到 `null`。
:::demo{name="tree/context-menu"}
:::
<demo vue="tree/context-menu.vue" />
## 自定义字段与渲染
`fieldNames` 映射后端字段;节点自身的 `icon` / `disabled` / `disableCheckbox` / `draggable: false` / `isLeaf` 可以逐节点覆盖行为。
:::demo{name="tree/custom"}
:::
<demo vue="tree/custom.vue" />
## 键盘操作
@@ -186,7 +178,8 @@ export interface TreeContextMenuItem {
| 变量 | 默认值 | 说明 |
| --- | --- | --- |
| `--g3-tree-node-height` | `32px` | 节点行高 |
| `--g3-tree-node-height` | `28px` | 节点行高 |
| `--g3-tree-node-gap` | `6px` | 相邻节点行之间的竖向间距 |
| `--g3-tree-indent` | `18px` | 每层缩进量 |
| `--g3-tree-icon-size` | `16px` | 图标尺寸 |
| `--g3-tree-switcher-size` | `22px` | 展开箭头点击区 |
@@ -17,8 +17,7 @@ description: 命令式轻提示:info / success / warning / error
`G3Message` 是一个对象,直接调用即可——它会自己挂载容器到 `body`,无需在模板里写组件。
:::demo{name="message/basic"}
:::
<demo vue="message/basic.vue" />
```ts
import { G3Message } from '@g3soft/ui'
@@ -33,8 +32,7 @@ G3Message.error('保存失败,请重试')
第二个参数是选项对象;调用返回 `{ close }` 句柄,可以提前关闭。
:::demo{name="message/options"}
:::
<demo vue="message/options.vue" />
| 选项 | 类型 | 默认值 | 说明 |
| --- | --- | --- | --- |
@@ -46,8 +44,7 @@ G3Message.error('保存失败,请重试')
`placement` 可逐条指定;`G3Message.config()` 设置全局默认,只影响之后的调用。
:::demo{name="message/placement"}
:::
<demo vue="message/placement.vue" />
```ts
G3Message.config({ placement: 'top-right', duration: 2000 })
@@ -15,8 +15,7 @@ description: 命令式通知:带标题与描述,适合承载需要阅读的
## 基础用法
:::demo{name="notification/basic"}
:::
<demo vue="notification/basic.vue" />
```ts
import { G3Notification } from '@g3soft/ui'
@@ -29,8 +28,7 @@ G3Notification.error({ title: '构建失败', description: '单元测试未通
通知只出现在四角(避免遮挡页面中央内容);逐条可指定 `placement`,也可以用 `config()` 设全局默认。
:::demo{name="notification/placement"}
:::
<demo vue="notification/placement.vue" />
```ts
G3Notification.config({ placement: 'bottom-right', duration: 6000 })
@@ -38,8 +36,7 @@ G3Notification.config({ placement: 'bottom-right', duration: 6000 })
## 关闭与清理
:::demo{name="notification/close"}
:::
<demo vue="notification/close.vue" />
## 使用注意
@@ -17,8 +17,7 @@ description: 隐藏原生滚动条,用自绘滑块承载可滚动内容
容器必须有确定高度(`height` / `max-height`),滚动才会生效。
:::demo{name="scrollbar/basic"}
:::
<demo vue="scrollbar/basic.vue" />
## 自动隐藏策略
@@ -31,8 +30,7 @@ description: 隐藏原生滚动条,用自绘滑块承载可滚动内容
| `move` | 鼠标移入或滚动时显示 | 面板、卡片 |
| `leave` | 鼠标移出后隐藏 | 需要极简视觉的展示区 |
:::demo{name="scrollbar/autohide"}
:::
<demo vue="scrollbar/autohide.vue" />
## 无障碍
@@ -17,22 +17,19 @@ description: 包裹内容显示加载遮罩,或作为独立的加载指示器
传默认插槽即「包裹模式」:`spinning` 为 true 时给内容加遮罩并显示指示器。
:::demo{name="spin/basic"}
:::
<demo vue="spin/basic.vue" />
## 独立使用
不传默认插槽时就是独立指示器,配 `description` 显示加载文案。
:::demo{name="spin/standalone"}
:::
<demo vue="spin/standalone.vue" />
## 延迟显示
`delay` 用来防「闪一下」:请求很快时根本不显示加载态,只有超过 `delay` 才出现。
:::demo{name="spin/delay"}
:::
<demo vue="spin/delay.vue" />
## 使用建议
@@ -18,15 +18,13 @@ description: 支持选中、未选中与半选三种状态的独立勾选控件
`v-model` 绑定 `boolean`。
:::demo{name="checkbox/basic"}
:::
<demo vue="checkbox/basic.vue" />
## 半选联动
`indeterminate` 是纯展示状态:组件**不会**自动推导它,需要业务根据子项结果计算。
:::demo{name="checkbox/indeterminate"}
:::
<demo vue="checkbox/indeterminate.vue" />
| 状态 | 表现 |
| --- | --- |
@@ -36,15 +34,13 @@ description: 支持选中、未选中与半选三种状态的独立勾选控件
## 禁用态
:::demo{name="checkbox/disabled"}
:::
<demo vue="checkbox/disabled.vue" />
## 富内容
默认插槽可以放任意内容(多行说明、链接、标签),此时仍然整块可点击。
:::demo{name="checkbox/rich-label"}
:::
<demo vue="checkbox/rich-label.vue" />
## API
@@ -17,15 +17,13 @@ description: 收集、校验与提交一组字段,支持横向 / 纵向布局
`model` 必须是响应式对象;`rules` 的键是字段名。
:::demo{name="form/basic"}
:::
<demo vue="form/basic.vue" />
## 校验规则
一条规则可以同时带多个约束,错误消息会全部收集;`message` 也支持传函数做动态文案。
:::demo{name="form/rules"}
:::
<demo vue="form/rules.vue" />
| 规则字段 | 类型 | 说明 |
| --- | --- | --- |
@@ -40,15 +38,13 @@ description: 收集、校验与提交一组字段,支持横向 / 纵向布局
`layout` 支持横向(label 在左)与纵向(label 在上);横向时可配 `labelAlign` 与 `labelWidth`。
:::demo{name="form/layout"}
:::
<demo vue="form/layout.vue" />
## 校验时机
`validateTrigger` 决定何时校验:`change` 输入即校验(默认),`blur` 失焦才校验。两种情况都做了「首次为空不报错」的处理,避免打开表单就整片飘红。
:::demo{name="form/validate-trigger"}
:::
<demo vue="form/validate-trigger.vue" />
## 提交、失败与重置
@@ -57,22 +53,19 @@ description: 收集、校验与提交一组字段,支持横向 / 纵向布局
- `reset`:点击 `html-type="reset"` 的按钮触发,同时清空所有字段的错误与触碰标记;
- 也可以在保存前手动 `formRef.validateAll()`。
:::demo{name="form/submit"}
:::
<demo vue="form/submit.vue" />
## 多列网格
`columns > 1` 时字段按网格排布,`FormItem` 用 `span` 跨列、`lineStart` 强制从下一行第一列开始。
:::demo{name="form/grid"}
:::
<demo vue="form/grid.vue" />
## 分组
`G3FormGroup` 在长表单里做分组,组内可以覆盖列数、布局与 label 宽度。
:::demo{name="form/group"}
:::
<demo vue="form/group.vue" />
## API
@@ -17,8 +17,7 @@ description: 单行 / 密码 / 数字 / 多行四种模式,支持清除、前
## 基础用法
:::demo{name="input/basic"}
:::
<demo vue="input/basic.vue" />
`v-model` 的值类型是 `string`;`type="number"` 时提交值为 `number`(空值保留为 `''`)。
@@ -26,8 +25,7 @@ description: 单行 / 密码 / 数字 / 多行四种模式,支持清除、前
`type="password"` 会在右侧渲染一个显示/隐藏按钮,按钮带 `aria-pressed` 与无障碍标签。
:::demo{name="input/password"}
:::
<demo vue="input/password.vue" />
密码框建议同时设置 `autocomplete="current-password"`,让浏览器密码管理器正确识别。
@@ -35,36 +33,31 @@ description: 单行 / 密码 / 数字 / 多行四种模式,支持清除、前
`type="number"` 做了三件事:过滤非数字字符、保留输入中间态(`12.` 不会被打断)、**失焦或回车时把字符串提交为 `Number`**。
:::demo{name="input/number"}
:::
<demo vue="input/number.vue" />
## 多行文本
`rows` 是初始行数;`show-count` 显示字数统计;右下角有拖拽手柄,可以拖拽或聚焦后用 `↑ / ↓ / Home` 调整高度(聚焦后是 `role="slider"`)。
:::demo{name="input/textarea"}
:::
<demo vue="input/textarea.vue" />
## 可清除
`allowClear` 时,有值且 hover / 聚焦会出现清除按钮;点击清空值并触发 `clear` 事件。
:::demo{name="input/clearable"}
:::
<demo vue="input/clearable.vue" />
## 前后缀插槽
`#prefix` / `#suffix` 放图标或单位,图标尺寸跟随字号(`1em`)。
:::demo{name="input/slots"}
:::
<demo vue="input/slots.vue" />
## 校验状态
`status` 让输入框表达校验结果:`error` 红边、`warning` 黄边。配合 `G3FormItem` 时通常由表单自动管理,无需手写。
:::demo{name="input/status"}
:::
<demo vue="input/status.vue" />
## 实例方法
@@ -77,8 +70,7 @@ inputRef.value?.focus({ cursor: 'all' }) // 聚焦并全选
inputRef.value?.focus({ preventScroll: true }) // 聚焦但不滚动页面
```
:::demo{name="input/methods"}
:::
<demo vue="input/methods.vue" />
## API
@@ -16,8 +16,7 @@ description: 与 RadioGroup 组合使用,在一组选项里选中一个
## 基础用法
:::demo{name="radio/basic"}
:::
<demo vue="radio/basic.vue" />
组会自动生成唯一的原生 `name`(`useId`),因此同页多组之间不会互相干扰,键盘方向键也能在组内来回切换。
@@ -25,15 +24,13 @@ description: 与 RadioGroup 组合使用,在一组选项里选中一个
组默认是水平换行的 `inline-flex`;纵向排列用外部 `style` 改 `flex-direction`,或给组包一层纵向容器。
:::demo{name="radio/vertical"}
:::
<demo vue="radio/vertical.vue" />
## 卡片式选择
默认插槽可以放任意内容,配合 `style` 就能做成卡片选择器(常见于套餐、模板选择)。
:::demo{name="radio/cards"}
:::
<demo vue="radio/cards.vue" />
## API
@@ -18,50 +18,43 @@ description: 下拉选择,支持筛选、多选、远程搜索、触底加载
`options` 默认按 `{ label, value, disabled }` 取值。
:::demo{name="select/basic"}
:::
<demo vue="select/basic.vue" />
## 字段名映射
后端返回的字段名不是 `label` / `value` 时,用 `labelKey` / `valueKey` 映射,不必在业务侧做数据转换。
:::demo{name="select/field-names"}
:::
<demo vue="select/field-names.vue" />
## 多选
`multiple` 时 `modelValue` 为数组,选中后下拉保持打开,选中项以顿号拼接显示。
:::demo{name="select/multiple"}
:::
<demo vue="select/multiple.vue" />
## 筛选
`filterable` 默认就是开启的;不传时按 `label` / `value` 做大小写不敏感的包含匹配,也可以传 `filterOption` 自定义。
:::demo{name="select/filterable"}
:::
<demo vue="select/filterable.vue" />
## 远程搜索
`remote` 模式不会做本地筛选,全部交给父层:输入触发 `search`,父层把结果写回 `options`;`loading` 时右侧显示加载图标而不是箭头/清除按钮。
:::demo{name="select/remote"}
:::
<demo vue="select/remote.vue" />
## 触底加载更多
列表滚到底部会持续触发 `loadMore`,配合 `loading` 去重;`#footer` 插槽可以放加载提示。
:::demo{name="select/load-more"}
:::
<demo vue="select/load-more.vue" />
## 自定义选项
不传 `options` 时使用默认插槽,插槽透出 `{ select, close }`,适合做带描述、头像的富选项。
:::demo{name="select/custom-option"}
:::
<demo vue="select/custom-option.vue" />
## 键盘操作
@@ -17,20 +17,17 @@ description: 用于切换单个状态的即时开关
`v-model` 绑定 `boolean`;`change` 回传新值与原生事件。
:::demo{name="switch/basic"}
:::
<demo vue="switch/basic.vue" />
## 禁用态
:::demo{name="switch/disabled"}
:::
<demo vue="switch/disabled.vue" />
## 与表单一起使用
放入 `G3FormItem` 时,label 与校验由表单负责,`Switch` 只提供值。
:::demo{name="switch/in-form"}
:::
<demo vue="switch/in-form.vue" />
## 关于「异步切换」
@@ -17,22 +17,19 @@ description: 把多个按钮贴合排列成一组,适用于工具条与互斥
默认水平排列,组内按钮共用一套圆角与边框。
:::demo{name="button-group/basic"}
:::
<demo vue="button-group/basic.vue" />
## 纵向排列
`orientation="vertical"` 时纵向贴合,组内按钮宽度一致,常作为侧边操作组。
:::demo{name="button-group/vertical"}
:::
<demo vue="button-group/vertical.vue" />
## 组合不同变体与尺寸
组内按钮各自保留 `type` / `size`;混排时建议统一变体,否则视觉层次会混乱。
:::demo{name="button-group/variant"}
:::
<demo vue="button-group/variant.vue" />
## API
@@ -18,8 +18,7 @@ description: 触发一个操作,支持 8 种视觉变体、3 档尺寸与加
不传 `type` 时使用 `primary`;按钮内容写在默认插槽里。
:::demo{name="button/basic"}
:::
<demo vue="button/basic.vue" />
按钮是原生 `<button>`,因此天然支持 `disabled`、键盘 `Enter / Space` 触发与表单语义。
@@ -27,8 +26,7 @@ description: 触发一个操作,支持 8 种视觉变体、3 档尺寸与加
`type` 决定按钮的视觉重量,请按「操作重要性」选择,而不是按颜色喜好选择。
:::demo{name="button/variant"}
:::
<demo vue="button/variant.vue" />
| 变体 | 使用场景 |
| --- | --- |
@@ -45,8 +43,7 @@ description: 触发一个操作,支持 8 种视觉变体、3 档尺寸与加
`size` 提供 3 档,默认 `medium`(`--g3-control-height`,32px)。
:::demo{name="button/size"}
:::
<demo vue="button/size.vue" />
尺寸只影响按钮自身的高度与字号;图标按钮(`type="icon"`)会同步变成正方形。
@@ -54,8 +51,7 @@ description: 触发一个操作,支持 8 种视觉变体、3 档尺寸与加
使用 `#icon` 插槽放图标,图标大小跟随按钮字号(`1em`);纯图标按钮用 `type="icon"`,**必须**提供 `aria-label`,否则屏幕阅读器读不出来。
:::demo{name="button/icon"}
:::
<demo vue="button/icon.vue" />
`type="icon"` 的按钮没有文字,因此无障碍标签需要手动补:
@@ -69,8 +65,7 @@ description: 触发一个操作,支持 8 种视觉变体、3 档尺寸与加
`loading` 会同时做三件事:显示加载图标、进入原生 `disabled`、**拦截 `click` 事件**(不会触发 `click`),因此可以直接用它防止重复提交。
:::demo{name="button/loading"}
:::
<demo vue="button/loading.vue" />
需要注意的是:`loading` 时按钮是原生禁用状态,浏览器不会派发 `click`;组件内部也额外做了拦截,避免在「按下瞬间进入 loading」时重复触发。
@@ -78,8 +73,7 @@ description: 触发一个操作,支持 8 种视觉变体、3 档尺寸与加
`disabled` 使用原生 `disabled` 属性,同时降低整体透明度并显示禁用光标。
:::demo{name="button/disabled"}
:::
<demo vue="button/disabled.vue" />
禁用按钮的 `click` 不会触发,也不会被聚焦(原生行为),所以不要把「必填校验失败」的提交按钮设为禁用——用户会不知道原因。
@@ -87,15 +81,13 @@ description: 触发一个操作,支持 8 种视觉变体、3 档尺寸与加
`block` 让按钮占满父容器宽度,常用于移动端、抽屉底部与卡片内。
:::demo{name="button/block"}
:::
<demo vue="button/block.vue" />
## 表单中的提交与重置
`htmlType` 对应原生 `<button type>`,配合 G3Form 使用时写 `html-type="submit"` / `"reset"` 即可触发表单的提交与重置。
:::demo{name="button/html-type"}
:::
<demo vue="button/html-type.vue" />
`htmlType` 默认值是 `button`,这样按钮放在表单里不会意外提交(原生 `<button>` 在表单内的默认行为是 `submit`)。
@@ -103,15 +95,13 @@ description: 触发一个操作,支持 8 种视觉变体、3 档尺寸与加
通过 `G3ConfigProvider` 的 `componentDefaults` 可以一次性修改某类组件的默认 props,组件内部的回落顺序是 **显式 prop > 全局默认值 > 组件内置默认**。
:::demo{name="button/global-defaults"}
:::
<demo vue="button/global-defaults.vue" />
## click 事件
`@click` 回传原生 `MouseEvent`,可以直接读取修饰键或做 `preventDefault`。
:::demo{name="button/event"}
:::
<demo vue="button/event.vue" />
## API
@@ -17,15 +17,13 @@ description: 24 栅格布局,支持间距、偏移、位移与 flex 自适应
`span` 表示占多少格(0-24);一行内累计超过 24 会自动换行。
:::demo{name="grid/basic"}
:::
<demo vue="grid/basic.vue" />
## 间距
`gutter` 传数字表示水平与垂直同值,传 `[水平, 垂直]` 可分别控制。栅格间距用 `gap` 实现,子列不再需要自己写 margin。
:::demo{name="grid/gutter"}
:::
<demo vue="grid/gutter.vue" />
## 偏移与位移
@@ -33,29 +31,25 @@ description: 24 栅格布局,支持间距、偏移、位移与 flex 自适应
- `push` / `pull`:左右位移,常用于调整视觉顺序;
- `order`:flex 的排序值,最小排在最前。
:::demo{name="grid/offset"}
:::
<demo vue="grid/offset.vue" />
## 对齐与分布
`align` 控制交叉轴(`align-items`),`justify` 控制主轴分布(`justify-content`)。需要行内有高度差时给 `Row` 一个固定高度。
:::demo{name="grid/align"}
:::
<demo vue="grid/align.vue" />
## flex 自适应
`flex` 传数字表示 `flex-grow` 的份数,传字符串则作为完整的 `flex` 简写使用。
:::demo{name="grid/flex"}
:::
<demo vue="grid/flex.vue" />
## 不换行
`wrap=false` 时列不会换行,超出 24 格的部分会被压缩,适合「横向铺满、不允许折行」的工具条。
:::demo{name="grid/no-wrap"}
:::
<demo vue="grid/no-wrap.vue" />
## API
@@ -18,48 +18,41 @@ description: 在一组互斥选项中切换,滑块跟随选中项移动
`options` 可以直接传原始值数组,选中值通过 `v-model` 双向绑定(支持字符串、数字、布尔)。
:::demo{name="segmented/basic"}
:::
<demo vue="segmented/basic.vue" />
## 对象选项
选项写成对象可以自定义显示文字、加图标、单独禁用某一项。
:::demo{name="segmented/options"}
:::
<demo vue="segmented/options.vue" />
## 圆角形状
:::demo{name="segmented/shape"}
:::
<demo vue="segmented/shape.vue" />
## 纵向排列
`vertical` 时滑块上下移动,适合做侧边栏的视图切换。
:::demo{name="segmented/vertical"}
:::
<demo vue="segmented/vertical.vue" />
## 撑满宽度
`block` 让各项等分父容器宽度(纵向时为高度),常用于移动端或表单顶部。
:::demo{name="segmented/block"}
:::
<demo vue="segmented/block.vue" />
## 自定义每项内容
`#label` 插槽作用域为 `{ option, index, checked }`:`option` 是原始选项对象,`checked` 表示该项是否选中。
:::demo{name="segmented/custom-label"}
:::
<demo vue="segmented/custom-label.vue" />
## 非受控用法
不传 `modelValue` 时组件内部维护选中值(默认不选中),通过 `change` 把结果抛给业务。
:::demo{name="segmented/uncontrolled"}
:::
<demo vue="segmented/uncontrolled.vue" />
## API
@@ -19,15 +19,13 @@ description: 为一组内联元素设置统一间距,并支持插入分隔符
默认水平排列、间距 `small`(8px)、交叉轴居中对齐。
:::demo{name="space/basic"}
:::
<demo vue="space/basic.vue" />
## 间距大小
`size` 支持三种写法:预设名 `small` / `middle` / `large`、数字(按 px 处理)、以及 `[水平, 垂直]` 数组。
:::demo{name="space/size"}
:::
<demo vue="space/size.vue" />
| 写法 | 效果 |
| --- | --- |
@@ -41,29 +39,25 @@ description: 为一组内联元素设置统一间距,并支持插入分隔符
`vertical` 是简写;`orientation` 与它同时配置时,以 `orientation` 优先(这样上层组件透传 `orientation` 时不会被 `vertical` 覆盖)。
:::demo{name="space/vertical"}
:::
<demo vue="space/vertical.vue" />
## 分隔符
`#separator` 插槽会在相邻子元素之间插入内容,**不会**在首尾添加。
:::demo{name="space/separator"}
:::
<demo vue="space/separator.vue" />
## 自动换行
`wrap` 只在水平方向生效;配合 `[水平, 垂直]` 形式的 `size` 可以分别控制列间距与行间距。
:::demo{name="space/wrap"}
:::
<demo vue="space/wrap.vue" />
## 空节点不占位
`v-if` 关闭的节点、注释节点不会被计入间距,因此条件渲染不会留下空隙。
:::demo{name="space/empty-children"}
:::
<demo vue="space/empty-children.vue" />
## API
@@ -16,8 +16,7 @@ description: 用于标记与分类的小型容器,支持多种变体、可关
## 视觉变体
:::demo{name="tag/variant"}
:::
<demo vue="tag/variant.vue" />
| 变体 | 语义 | 典型场景 |
| --- | --- | --- |
@@ -32,29 +31,25 @@ description: 用于标记与分类的小型容器,支持多种变体、可关
`closable` 会渲染关闭按钮(`role="button"`,支持 Enter / Space)。**点击关闭后标签会自己隐藏**,同时触发 `close` 事件——业务通常只需要在事件里同步数据源。
:::demo{name="tag/closable"}
:::
<demo vue="tag/closable.vue" />
## 阻止自动关闭(受控)
如果标签的显示与否由业务数据决定,在 `close` 里调用 `event.preventDefault()` 即可阻止自动隐藏。
:::demo{name="tag/prevent-close"}
:::
<demo vue="tag/prevent-close.vue" />
## 图标
`#icon` 放前置图标,`#close-icon` 可以替换默认的关闭图标(例如换成文字 `×`)。
:::demo{name="tag/icon"}
:::
<demo vue="tag/icon.vue" />
## 链接标签
传 `href` 后渲染成 `<a>`;`disabled` 时会去掉 `href` 并标记 `aria-disabled`,避免出现「看起来能点但点了没反应」。
:::demo{name="tag/link"}
:::
<demo vue="tag/link.vue" />
## API
@@ -17,29 +17,25 @@ description: 从屏幕边缘滑出的面板,支持四个方向与边缘拖拽
`v-model:open` 控制显隐;`cancel` 表示「被关闭」(遮罩 / Esc / 关闭按钮)。
:::demo{name="drawer/basic"}
:::
<demo vue="drawer/basic.vue" />
## 四个方向
`placement` 支持 `right`(默认)/ `left` / `top` / `bottom`;左右方向用 `width`,上下方向用 `height` 控制尺寸,缩放手柄也会跟着换方向。
:::demo{name="drawer/placement"}
:::
<demo vue="drawer/placement.vue" />
## 自定义尺寸
尺寸接受数字(px)或任意 CSS 长度(`'60%'`、`'48rem'`);`resizable=false` 可以关掉边缘拖拽。
:::demo{name="drawer/size"}
:::
<demo vue="drawer/size.vue" />
## 底部动作与补充信息
`#footer` 放底部动作区;`#extra` 在标题下方补充信息(如「已选 2 个条件」)。
:::demo{name="drawer/footer"}
:::
<demo vue="drawer/footer.vue" />
## Modal 还是 Drawer?
@@ -18,25 +18,21 @@ description: 点击 / 悬停 / 右键触发的操作列表,支持子菜单与
`items` 是最常用的写法,点击后通过 `click` 事件回传 `{ key, item }`。
:::demo{name="dropdown/basic"}
:::
<demo vue="dropdown/basic.vue" />
## 声明式写法
也可以把 `G3DropdownItem` 写在插槽里:它不渲染任何 DOM,只作为数据载体被 `Dropdown` 收集,因此键盘导航、高亮、子菜单这些能力与 `items` 写法完全一致。使用声明式写法时**建议用 `#trigger` 显式指定触发器**,避免触发器跟菜单项混在默认插槽里。
:::demo{name="dropdown/declarative"}
:::
<demo vue="dropdown/declarative.vue" />
## 触发方式
:::demo{name="dropdown/trigger"}
:::
<demo vue="dropdown/trigger.vue" />
## 菜单项类型
:::demo{name="dropdown/item-types"}
:::
<demo vue="dropdown/item-types.vue" />
| 项配置 | 说明 |
| --- | --- |
@@ -54,8 +50,7 @@ description: 点击 / 悬停 / 右键触发的操作列表,支持子菜单与
`#header` 用于账号卡片之类的头部(不参与键盘导航);`#menu` 是完全自定义菜单结构的逃生舱。
:::demo{name="dropdown/header-slot"}
:::
<demo vue="dropdown/header-slot.vue" />
## 键盘操作
@@ -68,8 +63,7 @@ description: 点击 / 悬停 / 右键触发的操作列表,支持子菜单与
| `Enter` | 选中高亮项并关闭菜单(有子菜单的父项只高亮,不选中) |
| `Esc` | 关闭菜单(由 Popover 处理) |
:::demo{name="dropdown/keyboard"}
:::
<demo vue="dropdown/keyboard.vue" />
## API
@@ -18,36 +18,31 @@ description: 模态窗口,支持拖动、缩放、全屏与命令式确认框
`v-model:open` 控制显隐。三个事件区分关闭来源:`confirm`(底部确认按钮)、`cancel`(取消按钮 / 遮罩 / Esc / 右上角关闭)、`closed`(退场动画结束)。
:::demo{name="modal/basic"}
:::
<demo vue="modal/basic.vue" />
## 拖动、缩放与全屏
默认允许拖动标题栏移动面板、拖拽四边缩放、右上角切换全屏。三者互相协调:进入全屏会复位拖拽位置并禁用缩放手柄。
:::demo{name="modal/resize"}
:::
<demo vue="modal/resize.vue" />
## 居中显示
面板默认贴顶(`align-items: flex-start`)——这样长内容不会把标题栏顶出视口。确认类、短表单可以开 `centered` 垂直居中。
:::demo{name="modal/resize"}
:::
<demo vue="modal/resize.vue" />
## 控制关闭入口
`maskClosable` / `keyboard` / `closable` / `footer` 分别控制遮罩点击、Esc、右上角关闭按钮与底部按钮区。
:::demo{name="modal/mask"}
:::
<demo vue="modal/mask.vue" />
## 表单弹窗与异步确认
`confirmLoading` 期间**阻止一切关闭**(含遮罩、Esc、取消按钮),避免异步提交被打断;底部按钮自动进入加载态。
:::demo{name="modal/form"}
:::
<demo vue="modal/form.vue" />
## 命令式确认框
@@ -66,22 +61,19 @@ const handle = G3Modal.confirm({
handle.destroy() // 立即关闭并卸载(不等退场动画)
```
:::demo{name="modal/confirm"}
:::
<demo vue="modal/confirm.vue" />
**`onConfirm` 的 Promise 语义**:resolve → 关闭;reject → 保持打开、解除 loading,错误由调用方提示。
**`onCancel` 的触发范围**:只有点击「取消」按钮才会调用 `onCancel`;点遮罩空白、Esc、右上角关闭按钮都是**静默关闭**(只关窗,不跑取消逻辑),避免用户随手点空白就触发取消副作用。
:::demo{name="modal/confirm-async"}
:::
<demo vue="modal/confirm-async.vue" />
## 自定义底部与头部
`#footer` 完全接管底部;`#header-extra` 放标题右侧的额外动作。
:::demo{name="modal/footer-slot"}
:::
<demo vue="modal/footer-slot.vue" />
## API
@@ -16,15 +16,13 @@ description: 浮层基座:12 方位定位、自动翻转、外部点击与 Esc
`#trigger` 是触发器,`#content` 是浮层内容;默认 click 触发、显示箭头。
:::demo{name="popover/basic"}
:::
<demo vue="popover/basic.vue" />
## 方位
`placement` 支持 12 个方位:`top` / `bottom` / `left` / `right` 各自带 `-start` / `-end` 对齐。空间不足时**自动翻转到对面**,再不够会沿视口边缘收缩(shift),始终保持 8px 安全边距。
:::demo{name="popover/placement"}
:::
<demo vue="popover/placement.vue" />
## 触发方式
@@ -36,22 +34,19 @@ description: 浮层基座:12 方位定位、自动翻转、外部点击与 Esc
| `contextmenu` | 右键时在**鼠标位置**打开,越界自动回退 |
| `manual` | 组件不接管开关,完全由 `open` 控制 |
:::demo{name="popover/trigger"}
:::
<demo vue="popover/trigger.vue" />
## 受控用法
传 `open` 即为受控:所有开关意图都会通过 `update:open` / `openChange` 抛出,你可以在里面做权限校验、埋点,或选择不关闭。
:::demo{name="popover/controlled"}
:::
<demo vue="popover/controlled.vue" />
## 箭头与宽度
`arrow=false` 去掉尖角(菜单类浮层常用);`followTriggerWidth` 让浮层宽度以触发器宽度为下限(表单控件常用)。
:::demo{name="popover/arrow-width"}
:::
<demo vue="popover/arrow-width.vue" />
## API
@@ -17,29 +17,25 @@ description: hover 或聚焦时显示的简短说明
`content` 传纯文本;默认在触发器上方显示。
:::demo{name="tooltip/basic"}
:::
<demo vue="tooltip/basic.vue" />
## 方位
`placement` 支持 12 个方位,空间不足会自动翻转。
:::demo{name="tooltip/placement"}
:::
<demo vue="tooltip/placement.vue" />
## 富内容
`#content` 插槽可以放多行说明、快捷键等富内容。
:::demo{name="tooltip/rich"}
:::
<demo vue="tooltip/rich.vue" />
## 受控与禁用
`disabled` 时不响应 hover;传 `open` 则完全受控(适合「首次进入引导」这类场景)。
:::demo{name="tooltip/disabled"}
:::
<demo vue="tooltip/disabled.vue" />
## 注意事项