Splitter 分栏
将内容区域拆分为可调整大小的面板。
用法
调整侧栏和编辑区域的比例
组件结构
加粗的是必需部件。
data-scope="splitter":root · panel · resize-trigger
示例
垂直与折叠
垂直调整并折叠面板
禁用
禁止调整面板比例
嵌套分栏
组合水平和垂直面板
设计指引
何时使用
- 构建编辑器、文件管理器或预览界面。
- 保存用户调整后的面板比例。
何时不用
特性
- 支持水平、垂直和嵌套分栏。
- 支持最小/最大尺寸和面板折叠。
- 支持方向键、Shift、Enter 和 Escape。
- 调整中和调整结束分别提供回调。
组合
- 可在每个面板中放置独立的滚动区域。
最佳实践
- 为每个面板设置合理的最小尺寸。
- 使用
onSizesChangeEnd保存最终布局。
反模式
- 不要用于固定比例布局。
- 不要缩小分隔条的交互区域。
API 参考
产物
| 层 | 值 |
|---|---|
| 自定义元素 | <xh-splitter> |
| Vue 组件 | XhSplitterPanel XhSplitterResizeTrigger XhSplitterRoot |
| 组合式函数 | useSplitter |
| 状态机 | splitterMachine |
| 皮肤 | @xihan-ui/styles/splitter.css |
Props
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
sizes | number[] | 每块面板的百分比。提供即受控:内部不再自行修改,只发 onSizesChange。 | |
defaultSizes | number[] | 非受控初值;未提供时按面板数等分。 | |
panels | SplitterPanelProps[] | 逐块的约束;数组长度同时决定面板块数。 | |
orientation | Orientation | 面板的排布轴,默认 horizontal(并排,左右拖动);vertical 是上下堆叠,上下拖动。 | |
dir | Direction | 文字方向,默认 ltr;只对调水平排布下的左右两键与指针位移的正负。 | |
disabled | boolean | 禁用:分隔条退出 Tab 序列、不可拖动也不可推动。 | |
step | number | 方向键的步长(百分比),默认 1。 | |
largeStep | number | Shift + 方向键的步长(百分比),默认 10。 | |
translations | Partial<SplitterTranslations> | ||
onSizesChange | (details: SplitterSizesChangeDetails) => void | 每次尺寸变化都发出;拖动过程中连续发出。 | |
onSizesChangeEnd | (details: SplitterSizesChangeEndDetails) => void | 只在一次操作结束时发出一次,适合用于保存布局。 |
SplitterPanelProps
panels 的元素。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
id | string | 是 | 作者给该面板起的名字,用于派生它的 DOM id(分隔条的 aria-controls 指向它)。 |
min | number | 百分比下界,默认 0。 | |
max | number | 百分比上界,默认 100。 | |
collapsible | boolean | 是否允许折叠,默认 false。 | |
collapsedSize | number | 折叠后的百分比,默认 0;collapsible 为假时不使用。 |
事件
自定义元素将载荷放在 detail;Vue 使用同名 emit。
| 事件 | 载荷 | 说明 |
|---|---|---|
sizes-change | SplitterSizesChangeDetails | 布局变化(拖动途中连续发出);detail 为 { sizes: number[] } |
sizes-change-end | SplitterSizesChangeEndDetails | 一次拖拽收尾时发出一次;detail 为 { sizes: number[], index: number } |
插槽
仅列出带载荷的插槽。
| Vue 组件 | 插槽 | 载荷 | 说明 |
|---|---|---|---|
XhSplitterRoot | default | SplitterRootSlotProps |
React 适配器 props
只列各组件自己声明的那些:继承自 ComponentPropsWithRef 的 DOM 属性不在其中,根组件上与上面 Props 表同名的也不重复列。Vue 的对应物是上面的插槽表。
| React 组件 | 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
XhSplitterPanel | index | number | string | 第几块面板;多块时必须逐个写明。兼收字符串。 | |
XhSplitterResizeTrigger | index | number | string | 第几条分隔条;它位于第 index 与第 index+1 块面板之间,调整的是前一块。兼收字符串。 | |
XhSplitterRoot | children | SlotChildren<SplitterRootSlotProps> |
状态
以下名称仅用于内部状态机。
状态:idle · dragging
事件:SIZES.SET · BOUNDARY.STEP · BOUNDARY.TO_MIN · BOUNDARY.TO_MAX · BOUNDARY.SET · BOUNDARY.FOCUS · PANEL.COLLAPSE · PANEL.EXPAND · DRAG.START · DRAG.MOVE · DRAG.END · DRAG.CANCEL
判据:canResize
connect API
getXxxProps() 返回对应部件的宿主属性。
| 成员 | 类型 | 说明 |
|---|---|---|
sizes | number[] | |
panels | SplitterPanelState[] | |
dragging | boolean | |
disabled | boolean | |
setSizes | (next: number[]) => void | 整份赋值:逐块夹进约束、总和归位到 100 之后才落定。 |
setPanelSize | (index: number, next: number) => void | 把第 index 块调整为 next,差额从它后面的面板中获取。 最后一块没有属于自己的分隔条,它的尺寸是其余面板的余数,不可调整。 |
collapsePanel | (index: number) => void | |
expandPanel | (index: number) => void | |
togglePanel | (index: number) => void | 折叠时展开、展开时折叠;不可折叠的面板上是空操作。 |
getRootProps | () => T['element'] | |
getPanelProps | (index: number) => T['element'] | |
getResizeTriggerProps | (index: number) => T['element'] | 第 index 条分隔条位于第 index 与第 index+1 块面板之间,调整的是前一块。 |
无障碍
键盘
规格出处:W3C APG
| 按键 | 生效条件 | 行为 |
|---|---|---|
ArrowRight / ArrowDown | focus in resize-trigger, not disabled | 把这条分隔条前面那块面板按 step(默认 1%)撑大;水平排布认左右键、竖直排布认上下键,另一条轴上的方向键原样放行 |
ArrowLeft / ArrowUp | focus in resize-trigger, not disabled | 按 step 压小,同上的轴向规则;rtl 下左右两键对调,语义恒是"撑大 / 压小前一块" |
Shift+ArrowRight / Shift+ArrowDown | focus in resize-trigger, not disabled | 按 largeStep(默认 10%)撑大 |
Shift+ArrowLeft / Shift+ArrowUp | focus in resize-trigger, not disabled | 按 largeStep 压小 |
Home | focus in resize-trigger, not disabled | 把前一块面板收到它眼下能到的最小尺寸 |
End | focus in resize-trigger, not disabled | 把前一块面板撑到它眼下能到的最大尺寸 |
Escape | 拖动中 | 放弃这一场拖拽,布局退回按下那一刻;收尾回调不发 |
Enter | focus in resize-trigger 且它调整的面板 collapsible,not disabled | 折叠 / 展开该面板;展开回到折叠前的尺寸。面板不可折叠时不接这个键 |
ARIA
以下属性由 connect 生成。
| 部件 | 属性 | 值 |
|---|---|---|
root | aria-label | translations?.root |
root | role | 'group' |
resize-trigger | aria-controls | panel 部件的 id |
resize-trigger | aria-disabled | 'true' | 'false' |
resize-trigger | aria-label | translations?.resizeTrigger?.(boundary, Math.max(0, l… |
resize-trigger | aria-orientation | 'horizontal' | 'vertical' |
resize-trigger | aria-valuemax | String(panel.max) |
resize-trigger | aria-valuemin | String(panel.min) |
resize-trigger | aria-valuenow | String(panel.size) |
resize-trigger | role | 'separator' |
样式参考
皮肤
@xihan-ui/styles/splitter.css 使用 [data-scope="splitter"][data-part="root"] 部件选择器,位于 xihan.components 层。覆盖样式使用 xihan.overrides。
forced-colors: active 下另有一套规则:颜色交给系统,边框与状态标记改用系统色关键字。
数据属性
由 connect 生成;条件不成立时不输出无值属性。
| 部件 | 属性 | 值 |
|---|---|---|
root | data-disabled | ''(条件成立时才出现) |
root | data-dragging | ''(条件成立时才出现) |
root | data-orientation | props.orientation |
panel | data-collapsed | ''(条件成立时才出现) |
panel | data-disabled | ''(条件成立时才出现) |
panel | data-dragging | ''(条件成立时才出现) |
panel | data-index | String(panel.index) |
panel | data-orientation | props.orientation |
resize-trigger | data-disabled | ''(条件成立时才出现) |
resize-trigger | data-dragging | ''(条件成立时才出现) |
resize-trigger | data-index | String(boundary) |
resize-trigger | data-orientation | props.orientation |
CSS 变量
本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。
| 变量 | 部件 | CSS 属性 | 状态 | 默认来源 | 说明 |
|---|---|---|---|---|---|
--xh-splitter-disabled-opacity | root | opacity | disabled | 0.6 | splitter 的 root 部件 opacity 覆盖槽。 |
--xh-splitter-radius | root | border-radius | default | --xh-shape-surface | splitter 的 root 部件 border-radius 覆盖槽。 |
--xh-splitter-trigger-bg | resize-trigger | background | default | --xh-border-default | splitter 的 resize-trigger 部件 background 覆盖槽。 |
--xh-splitter-trigger-bg-disabled | resize-trigger | background | disabled | --xh-border-subtle | splitter 的 resize-trigger 部件 background 覆盖槽。 |
--xh-splitter-trigger-bg-dragging | resize-trigger | background | dragging | --xh-bg-brand | splitter 的 resize-trigger 部件 background 覆盖槽。 |
--xh-splitter-trigger-bg-hover | resize-trigger | background | hover | --xh-border-control | splitter 的 resize-trigger 部件 background 覆盖槽。 |
--xh-splitter-trigger-thickness | resize-trigger | block-sizeinline-size | orientation=horizontalorientation=vertical | --xh-space-1 | splitter 的 resize-trigger 部件 block-size、inline-size 覆盖槽。 |
动效
动效角色:状态(见动效规范)。
background-color 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。
系统开启减弱动效时由令牌层统一收敛,皮肤不另作判断。
