- 前端
- UI组件
【免费下载链接】rsuite
🧱 A suite of React components .
在 rsuite 中,<ButtonGroup>的divided属性用于在按钮组内的相邻按钮之间绘制分隔线,从而把一组功能相关的按钮在视觉上区分为独立的个体。本文以官方文档中“分隔按钮”示例为主线,完整还原该示例的运行方式,并深入源码剖析divided是如何从组件属性一路传导到data-dividedDOM 属性、再到 SCSS 边框规则生效的,帮助你在实际业务中正确、可控地使用分隔按钮组。
示例效果与完整代码
分隔按钮的典型场景是:一组操作按钮在逻辑上同属一个按钮组(共享圆角、尺寸、禁用状态),但在视觉上需要彼此独立,例如文本编辑工具栏中的“加粗 / 斜体 / 下划线”三个按钮。官方示例(对应仓库中 divided 示例片段)展示了水平与垂直两种布局、default与primary两种外观组合:
import { Button, ButtonGroup, VStack, HStack } from 'rsuite'; const ButtonGroupWithAppearance = ({ appearance, vertical }) => ( <ButtonGroup divided vertical={vertical}> <Button appearance={appearance}>Bold</Button> <Button appearance={appearance}>Italic</Button> <Button appearance={appearance}>Underline</Button> </ButtonGroup> ); const App = () => ( <VStack spacing={12}> <HStack> <ButtonGroupWithAppearance appearance="default" /> <ButtonGroupWithAppearance appearance="primary" /> </HStack> <HStack> <ButtonGroupWithAppearance appearance="default" vertical /> <ButtonGroupWithAppearance appearance="primary" vertical /> </HStack> </VStack> ); ReactDOM.render(<App />, document.getElementById('root'));这个示例包含四个按钮组实例:
- 第一行:
default与primary两种外观的水平分隔按钮组; - 第二行:同样两种外观的垂直分隔按钮组(通过
vertical属性开启)。
divided与vertical相互正交:开启vertical后,分隔线的方向会从“按钮之间的竖线”自动切换为“按钮之间的横线”,这一行为完全由样式层保证,无需你额外处理。
组件属性:divided 如何落到 DOM 上
divided是<ButtonGroup>的一个可选布尔属性,在 ButtonGroup 组件定义 中声明为/** Add dividing lines between buttons */ divided?: boolean;。组件渲染时并不直接绘制任何线条,而是把它作为数据属性透传到根元素上:
// src/ButtonGroup/ButtonGroup.tsx return ( <ButtonGroupContext.Provider value={contextValue}> <Box as={as} {...rest} role={role} ref={ref} className={classes} >// src/ButtonGroup/test/ButtonGroup.spec.tsx it('Should add divided variation', () => { render(<ButtonGroup divided />); expect(screen.getByRole('group')).to.have.attr('data-divided', 'true'); });参见 ButtonGroup 单元测试。此外该测试文件还验证了size、vertical、block、justified、组级disabled等属性的透传行为,说明divided与其他布局属性一样,都是“数据属性 + 样式消费”的模式。
样式实现:分隔线的真正来源
分隔线样式全部定义在 ButtonGroup 样式文件 中,按水平/垂直两种布局分别实现。
水平布局(默认):给除最后一个按钮外的每个按钮加 1px 的右边框,作为其与下一个按钮之间的分隔线:
// src/ButtonGroup/styles/index.scss .rs-btn-group:not([data-vertical='true']) { &[data-divided='true'] > .rs-btn { &:not(:last-child) { border-right-width: 1px; } } }垂直布局:同样的逻辑旋转 90 度,改用下边框:
// src/ButtonGroup/styles/index.scss .rs-btn-group[data-vertical='true'] { &[data-divided='true'] > .rs-btn { &:not(:last-child) { border-bottom-width: 1px; } } }这与示例中“水平组出现竖分隔线、垂直组出现横分隔线”的现象完全吻合。需要注意几点实现细节:
- 边框宽度而非边框颜色:规则只调整
border-*-width。普通按钮(default/primary外观)本来就有边框,因此divided实际上是把相邻按钮之间被“挤掉”的边框重新恢复出来。普通(非 divided)水平按钮组则是通过float: inline-start与首尾之外的按钮去掉左右圆角来“贴合”在一起的,见 样式文件中的水平布局规则。 - ghost 外观的边框折叠:对于
appearance="ghost"的相邻按钮,样式表通过-1px的外边距让两条 1px 边框重叠成一条(水平用margin-inline-start: -1px,垂直用margin-top: -1px)。因此如果你用 ghost 按钮组合divided组,分隔线同样保持 1px 粗。 - 垂直布局下的圆角处理:垂直组中除最后一个按钮外清除下圆角、除第一个按钮外清除上圆角(见 样式文件),保证整组呈现为一个连续的柱状块,分隔线嵌在其内部。
与 size、disabled 等组级状态的协同
divided示例中每个按钮都显式写了appearance,但size和disabled并不需要在每个按钮上重复声明。ButtonGroup通过 Context 向子按钮下发组级状态:
// src/ButtonGroup/ButtonGroup.tsx const contextValue = useMemo(() => ({ size, disabled }), [disabled, size]);子按钮在 Button 组件 中消费该 Context,并在自身未显式指定时回退到组级值:
const buttonGroup = useContext(ButtonGroupContext); // ... disabled = buttonGroup?.disabled, size = buttonGroup?.size || 'md',因此<ButtonGroup divided size="lg">会让组内所有按钮统一为lg尺寸——这一点由 样式测试 验证(size="lg"时按钮内边距为10px 14px),单元测试 也逐一切换lg/md/sm/xs断言子按钮的data-size。组级disabled则会让所有子按钮同时带上data-disabled="true"与原生disabled属性,见 测试用例。
<ButtonGroup>完整 Props 参考
divided只是按钮组的一组布局属性之一,下表汇总官方文档给出的完整属性说明(源自 ButtonGroup 文档中文页面,与 组件接口定义 一致):
| 属性名称 | 类型(默认值) | 描述 |
|---|---|---|
block | boolean | 将按钮组显示为块级元素,占据整个容器的宽度(需配合vertical生效,对应data-block) |
classPrefix | string('btn-group') | 自定义 CSS 类前缀,用于样式定制和主题适配 |
disabled | boolean | 禁用组内所有按钮 |
divided | boolean | 在按钮组中显示分隔线(本文主题) |
justified | boolean | 在水平布局中均匀分配按钮宽度(等宽) |
size | 'lg' | 'md' | 'sm' | 'xs'('md') | 为组内所有按钮设置统一尺寸 |
vertical | boolean | 采用垂直堆叠布局显示按钮 |
组件根类名为rs-btn-group(默认classPrefix为btn-group),可通过 Storybook 故事 中的Size、Vertical、Block、Justified等场景对照观察各种布局形态。
可访问性与使用建议
- 从源码结构看,
ButtonGroup根节点默认渲染role="group"(见 组件源码),源码注释中建议同时提供aria-label或aria-labelledby以便屏幕阅读器理解这组按钮的语义。 divided是纯视觉属性:它不改变键盘焦点顺序,也不影响各按钮独立触发的行为;分隔的每个按钮仍是独立可聚焦、可点击的<button>元素。- 若需要“外观整体、点击拆分”的分体式下拉按钮,官方文档在“分体式按钮”一节提供了
Button+Menu的组合方案(见 示例片段),与divided的定位不同,可按需选择。
小结
divided的使用成本极低——在<ButtonGroup>上加一个布尔属性即可——但其背后是 rsuite 组件库典型的“数据属性 + 属性选择器”样式机制:组件把divided/vertical等状态写成data-*属性,样式表按水平、垂直两套规则恢复相邻按钮间的 1px 边框(ghost 外观则靠负边距折叠边框)。理解这条链路后,你可以放心地把divided与vertical、size、appearance、disabled任意组合,并且清楚地知道视觉结果来自哪里、如何用classPrefix和自定义 CSS 覆盖它。
- 前端
- UI组件
【免费下载链接】rsuite
🧱 A suite of React components .
相关推荐
Rsuite ButtonGroup 实战指南:用 ButtonGroup 与 ButtonToolbar 构建一致、可控的按钮组布局
Rsuite ButtonGroup 实战指南:用 ButtonGroup 与 ButtonToolbar 构建一致、可控的按钮组布局 ButtonGroup
前端UI组件Tachyons按钮设计:基于原子类的多样化按钮样式实现
Tachyons按钮设计:基于原子类的多样化按钮样式实现 你是否还在为网页按钮设计耗费大量CSS代码?是否因按钮状态变化导致样式冲突而头疼?本文将展示如何使用T
前端Rsuite ButtonGroup 外观定制详解:appearance 的五种取值与>Rsuite ButtonGroup 外观定制详解:appearance 的五种取值与 data appearance 实现原理 本文以 Rsuite 官方文档
前端UI组件
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考