按钮
概述
一个可用于触发动作的按钮组件。
用法
特性
- 🎨 8 种变体:solid、outline、dashed、soft、ghost、link、plain、pure
- 🌈 8 种颜色:primary、destructive、success、warning、info、carbon、secondary、accent
- 📏 6 种尺寸:xs、sm、md、lg、xl、2xl
- 🔲 4 种形状:auto、rounded、square、circle
- ⚡ 支持加载状态
- 🌐 支持链接功能 (SButtonLink)
- ♿ 完全支持无障碍访问
- 🎯 TypeScript 类型安全
按钮组件系列
- SButton - 基础按钮组件
- SButtonLink - 链接按钮,支持路由导航
- SButtonIcon - 图标按钮,紧凑设计
- SButtonLoading - 加载状态按钮
- SButtonGroup - 按钮组组件
演示
Basic
Slot
Loading
Icon
Group
API
Aria 层
5Button
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
class | ClassValue | — | 应用于根元素的额外类名。 |
color | ThemeColor | — | 组件的主题颜色。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
variant | ButtonVariant | — | 该组件的视觉变体。 |
shape | ButtonShape | — | 组件的结构。 |
shadow | ButtonShadow | — | 遵循该组件的样式规范。 |
fitContent | boolean | — | 组件是否应适应其内容宽度。 |
type | ButtonType | 'button' | 按钮元素的类型。可以是 'button'、'submit' 或 'reset' 之一。 |
disabled | boolean | — | 该组件是否已禁用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
事件
| 事件名 | 参数 | 描述 |
|---|---|---|
click | PointerEvent | 在发生点击时触发。 |
ButtonGroup
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
class | ClassValue | — | 应用于根元素的额外类名。 |
color | ThemeColor | — | 组件的主题颜色。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
variant | ButtonVariant | — | 该组件的视觉变体。 |
shape | ButtonShape | — | 组件的结构。 |
shadow | ButtonShadow | — | 遵循该组件的样式规范。 |
fitContent | boolean | — | 组件是否应适应其内容宽度。 |
disabled | boolean | — | 所有子级按钮是否均处于禁用状态。 |
orientation | DataOrientation | 'horizontal' | 按钮组的排列方向。 |
dir | Direction | — | 按钮组的阅读方向。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
ButtonIcon
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
icon | IconValue | — | iconify 的图标值。 |
iconClass | ClassValue | — | 图标的类。 |
iconProps | Partial<IconProps> | — | 图标的 props。 |
class | ClassValue | — | 应用于根元素的额外类名。 |
color | ThemeColor | — | 组件的主题颜色。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
variant | ButtonVariant | — | 该组件的视觉变体。 |
shape | ButtonShape | — | 组件的结构。 |
shadow | ButtonShadow | — | 遵循该组件的样式规范。 |
fitContent | boolean | — | 组件是否应适应其内容宽度。 |
type | ButtonType | 'button' | 按钮元素的类型。可以是 'button'、'submit' 或 'reset' 之一。 |
disabled | boolean | — | 该组件是否已禁用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
ButtonLink
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
class | ClassValue | — | 应用于根元素的额外类名。 |
color | ThemeColor | — | 组件的主题颜色。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
variant | ButtonVariant | — | 该组件的视觉变体。 |
shape | ButtonShape | — | 组件的结构。 |
shadow | ButtonShadow | — | 遵循该组件的样式规范。 |
fitContent | boolean | — | 组件是否应适应其内容宽度。 |
type | ButtonType | 'button' | 按钮元素的类型。可以是 'button'、'submit' 或 'reset' 之一。 |
disabled | boolean | — | 该组件是否被禁用。
当值为 `true` 时,该链接将被禁用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
to | string | import("vue-router").RouteLocationAsRelativeGeneric | import("vue-router").RouteLocationAsPathGeneric | — | Route Location:点击该链接后应跳转到的位置。 |
replace | boolean | — | 调用 `router.replace` 而不是 `router.push`。 |
href | string | — | 点击链接时应跳转到的 URL。 |
activeClass | string | — | 当链接处于活动状态时应用的类 |
exactActiveClass | string | — | 当链接完全有效时应用的类 |
inactiveClass | string | — | 链接处于非活动状态时应应用的类。 |
prefetchedClass | string | — | 一个用于标记已预取链接的类。 |
external | boolean | — | 强制将链接视为外部链接(true)或内部链接(false)。这有助于处理边界情况 |
ariaCurrentValue | 'true' | 'false' | 'page' | 'date' | 'time' | 'step' | 'location' | `'page'` | 当链接处于活动状态时,传递给 `aria-current` 属性的值。 |
viewTransition | boolean | — | 如果支持,请将 `router.push()` 返回的 Promise 传递给 `document.startViewTransition()`。 |
target | (string & {}) | '_blank' | '_parent' | '_self' | '_top' | null | — | 将链接的 URL 作为浏览上下文的名称显示在何处。 |
rel | (string & {}) | 'noopener' | 'noreferrer' | 'nofollow' | 'sponsored' | 'ugc' | null | 'noopener noreferrer' | 应用于链接的 rel 属性值。对于外部链接,默认值为“noopener noreferrer”。 |
noRel | boolean | — | 如果设置为 true,则不会在链接中添加 rel 属性 |
prefetch | boolean | — | 启用后,将预取视口内链接的中间件、布局和有效载荷。 |
prefetchOn | 'visibility' | 'interaction' | Partial<{ visibility: boolean; interaction: boolean; }> | — | 允许控制何时预取链接。默认情况下,仅在可见性发生变化时才会触发预取。 |
noPrefetch | boolean | — | 用于禁用 `prefetch` 属性的逃逸机制。 |
trailingSlash | 'append' | 'remove' | — | 一个用于在此特定链接的 `href` 中添加或移除尾部斜杠的选项。
如果提供了此选项,将覆盖全局 `trailingSlash` 选项。 |
ButtonLoading
属性
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
loading | boolean | false | 按钮是否正在加载。 |
loadingText | string | — | 按钮加载时显示的文本。
当加载位置位于中心时,将显示此文本。 |
loadingDuration | number | 150 ms | 加载状态的持续时间(单位:毫秒)。 |
autoLoading | boolean | false | 是否在点击事件期间自动处理加载状态。当值为 true 时,按钮将在点击事件执行期间显示加载状态
;当值为 false 时,您需要手动控制加载状态。 |
loadingIcon | IconValue | 'svg-spinners:270-ring' | 按钮加载时显示的 iconify 图标名称。 |
loadingIconProps | Partial<IconProps> | — | 加载图标的 props。 |
loadingPosition | Align | 'start' | 加载图标的位置。 |
class | ClassValue | — | 应用于根元素的额外类名。 |
color | ThemeColor | — | 组件的主题颜色。 |
size | ThemeSize | — | 组件的视觉尺寸。 |
variant | ButtonVariant | — | 该组件的视觉变体。 |
shape | ButtonShape | — | 组件的结构。 |
shadow | ButtonShadow | — | 遵循该组件的样式规范。 |
fitContent | boolean | — | 组件是否应适应其内容宽度。 |
type | ButtonType | 'button' | 按钮元素的类型。可以是 'button'、'submit' 或 'reset' 之一。 |
disabled | boolean | — | 该组件是否已禁用。 |
asChild | boolean | — | 将默认渲染元素替换为作为子元素传递的元素,并合并两者的属性及行为。 |
as | AsTag | Component | 'div' | 该组件应渲染为的元素或组件。可通过 `asChild` 进行覆盖。 |
注意事项
架构与对标差异
VeanUI 将按钮拆分为负责状态、ARIA 与键盘行为的 Aria 层(@vean/aria/button),以及负责变体与 UnoCSS 样式的 styled 层(@vean/ui)。这与 shadcn/ui 的 headless/styled 分离一致,区别于 Ant Design、Element Plus、MUI、Mantine、Naive UI 等单包方案。
| 维度 | VeanUI | Ant Design / Element Plus / MUI / Mantine / Naive UI |
|---|---|---|
| 架构 | Aria + styled 分离 | 单包 |
| 样式 | 通过 cv() recipe 生成 UnoCSS 工具类 | CSS-in-JS / SCSS / CSS 变量 |
| 定制 | class 属性、as / asChild 多态、插槽覆盖 | className、style、组件覆盖 |
| 加载态 | 独立的 SButtonLoading 组件 | 基础按钮上的 loading 属性 |
| 图标按钮 | 独立的 SButtonIcon 组件 | 基础按钮上的 icon 属性 |
常见问题
为什么禁用按钮同时保留 aria-disabled 和原生 disabled? 原生 disabled 属性会将按钮移出 Tab 序列并阻止平台层面的点击。同时设置 aria-disabled="true" 是为了在通过 as 属性将按钮渲染为非 <button> 元素(例如 as="a" 或 as="div",此时原生 disabled 不生效)时,辅助技术仍能播报禁用状态。
如何让按钮占满宽度? 传入 class="w-full"(反之可用 fitContent)。VeanUI 不提供 block 属性,因为 UnoCSS 工具类已能覆盖该需求,无需扩展 API。
如何显示加载指示器? 使用 SButtonLoading。它支持 autoLoading(在点击处理期间自动切换加载态)、受控的 loading 属性、loadingPosition(start / center / end)、loadingText 以及自定义 loadingIcon。基础 SButton 刻意不内置加载态以保持 API 精简。加载期间按钮会设置 aria-busy="true",加载图标设置 aria-hidden,确保状态被播报而不引入冗余装饰。
SButtonGroup 如何向子组件传递属性?SButtonGroup 通过 context 将 color、size、variant、shape、shadow、disabled、fitContent 转发给后代 SButton。子组件自身设置的属性优先于分组传入的值。
能把按钮渲染为链接或其他元素吗? 可以。使用 as 属性切换根标签(as="a"、as="div"……),或用 asChild 将属性合并到自定义子节点上。如需路由感知的链接按钮,推荐使用 SButtonLink——它将 SButton 与 Link 组件组合在一起。