Components
Back to catalog
Component detail entry
General
@vean/ui
SButton

Button

Button belongs to the General category. Start with demos and usage, then use the API tables to finish integration and styling decisions.

Use the quick jump panel to reach overview, usage, demos, and API first, then continue through the full page.

Quick jump

Related components

If you are composing interactions in the same family, these components usually pair well together.

Button

Overview

A button component that can be used to trigger an action.

Usage

Features

  • 🎨 8 variants: solid, outline, dashed, soft, ghost, link, plain, pure
  • 🌈 8 colors: primary, destructive, success, warning, info, carbon, secondary, accent
  • 📏 6 sizes: xs, sm, md, lg, xl, 2xl
  • 🔲 4 shapes: auto, rounded, square, circle
  • ⚡ Loading state support
  • 🌐 Link function support (SButtonLink)
  • ♿ Full accessibility support
  • 🎯 TypeScript type safety

Button component family

  • SButton - Basic button component
  • SButtonLink - Link button, supports route navigation
  • SButtonIcon - Icon button, compact design
  • SButtonLoading - Loading state button
  • SButtonGroup - Button group component

Demos

Basic

Slot

Loading

Icon

Link

Group

API

Aria Layer

5

Button

11 Props1 Emits
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
color
ThemeColor
—
Theme color of the component.
size
ThemeSize
—
Visual size of the component.
variant
ButtonVariant
—
Visual variant of the component.
shape
ButtonShape
—
Shape of the component.
shadow
ButtonShadow
—
Shadow style of the component.
fitContent
boolean
—
Whether the component should fit its content width.
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
Emits
Emit NameParametersDescription
click
PointerEvent
Emitted when click occurs.

ButtonGroup

12 Props
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
color
ThemeColor
—
Theme color of the component.
size
ThemeSize
—
Visual size of the component.
variant
ButtonVariant
—
Visual variant of the component.
shape
ButtonShape
—
Shape of the component.
shadow
ButtonShadow
—
Shadow style of the component.
fitContent
boolean
—
Whether the component should fit its content width.
disabled
boolean
—
Whether all descendant buttons are disabled.
orientation
DataOrientation
'horizontal'
The orientation of the button group.
dir
Direction
—
The reading direction of the button group.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

ButtonIcon

14 Props
Props
PropTypeDefaultDescription
icon
IconValue
—
The icon value of iconify.
iconClass
ClassValue
—
The class of the icon.
iconProps
Partial<IconProps>
—
The props of the icon.
class
ClassValue
—
Additional class names applied to the root element.
color
ThemeColor
—
Theme color of the component.
size
ThemeSize
—
Visual size of the component.
variant
ButtonVariant
—
Visual variant of the component.
shape
ButtonShape
—
Shape of the component.
shadow
ButtonShadow
—
Shadow style of the component.
fitContent
boolean
—
Whether the component should fit its content width.
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

ButtonLink

28 Props
Props
PropTypeDefaultDescription
class
ClassValue
—
Additional class names applied to the root element.
color
ThemeColor
—
Theme color of the component.
size
ThemeSize
—
Visual size of the component.
variant
ButtonVariant
—
Visual variant of the component.
shape
ButtonShape
—
Shape of the component.
shadow
ButtonShadow
—
Shadow style of the component.
fitContent
boolean
—
Whether the component should fit its content width.
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled. When `true`, the link is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`
to
string | import("vue-router").RouteLocationAsRelativeGeneric | import("vue-router").RouteLocationAsPathGeneric
—
Route Location the link should navigate to when clicked on.
replace
boolean
—
Calls `router.replace` instead of `router.push`.
href
string
—
The URL the link should navigate to when clicked on.
activeClass
string
—
Class to apply when the link is active
exactActiveClass
string
—
Class to apply when the link is exact active
inactiveClass
string
—
The class to apply to the link when it is inactive.
prefetchedClass
string
—
A class to apply to links that have been prefetched.
external
boolean
—
Forces the link to be considered as external (true) or internal (false). This is helpful to handle edge-cases
ariaCurrentValue
'true' | 'false' | 'page' | 'date' | 'time' | 'step' | 'location'
`'page'`
Value passed to the attribute `aria-current` when the link is exact active.
viewTransition
boolean
—
Pass the returned promise of `router.push()` to `document.startViewTransition()` if supported.
target
(string & {}) | '_blank' | '_parent' | '_self' | '_top' | null
—
Where to display the linked URL, as the name for a browsing context.
rel
(string & {}) | 'noopener' | 'noreferrer' | 'nofollow' | 'sponsored' | 'ugc' | null
'noopener noreferrer'
A rel attribute value to apply on the link. Defaults to "noopener noreferrer" for external links.
noRel
boolean
—
If set to true, no rel attribute will be added to the link
prefetch
boolean
—
When enabled will prefetch middleware, layouts and payloads of links in the viewport.
prefetchOn
'visibility' | 'interaction' | Partial<{ visibility: boolean; interaction: boolean; }>
—
Allows controlling when to prefetch links. By default, prefetch is triggered only on visibility.
noPrefetch
boolean
—
Escape hatch to disable `prefetch` attribute.
trailingSlash
'append' | 'remove'
—
An option to either add or remove trailing slashes in the `href` for this specific link. Overrides the global `trailingSlash` option if provided.

ButtonLoading

18 Props
Props
PropTypeDefaultDescription
loading
boolean
false
Whether the button is loading.
loadingText
string
—
The text to display when the button is loading. It will be displayed when the loading position is center.
loadingDuration
number
150 ms
The duration of the loading state in milliseconds.
autoLoading
boolean
false
Whether to automatically handle loading state during click event. When true, the button will show loading state during click event execution. When false, you need to manually control the loading state.
loadingIcon
IconValue
'svg-spinners:270-ring'
The icon name of iconify to display when the button is loading.
loadingIconProps
Partial<IconProps>
—
The props of the loading icon.
loadingPosition
Align
'start'
The position of the loading icon.
class
ClassValue
—
Additional class names applied to the root element.
color
ThemeColor
—
Theme color of the component.
size
ThemeSize
—
Visual size of the component.
variant
ButtonVariant
—
Visual variant of the component.
shape
ButtonShape
—
Shape of the component.
shadow
ButtonShadow
—
Shadow style of the component.
fitContent
boolean
—
Whether the component should fit its content width.
type
ButtonType
'button'
The type of the button element. Can be one of 'button', 'submit', or 'reset'.
disabled
boolean
—
Whether the component is disabled.
asChild
boolean
—
Change the default rendered element for the one passed as a child, merging their props and behavior.
as
AsTag | Component
'div'
The element or component this component should render as. Can be overwrite by `asChild`

Notes

Architecture and benchmark differences

VeanUI splits the button into an Aria layer (@vean/aria/button) that owns state, ARIA, and keyboard behavior, and a styled layer (@vean/ui) that owns variants and UnoCSS classes. This mirrors shadcn/ui’s headless/styled separation and differs from single-package libraries such as Ant Design, Element Plus, MUI, Mantine, and Naive UI.

AspectVeanUIAnt Design / Element Plus / MUI / Mantine / Naive UI
ArchitectureAria + styled splitsingle package
StylingUnoCSS utility classes via cv() recipeCSS-in-JS / SCSS / CSS vars
Customizationclass prop, as / asChild polymorphism, slot overridesclassName, style, component overrides
Loadingdedicated SButtonLoading componentloading prop on the base button
Icon buttondedicated SButtonIcon componenticon prop on the base button

FAQ

Why does the disabled button keep aria-disabled in addition to the native disabled? The native disabled attribute removes the button from the tab order and blocks platform-level clicks. aria-disabled="true" is also set so assistive technology can announce the disabled state when the button is rendered as a non-<button> element through the as prop (e.g. as="a" or as="div"), where the native disabled attribute does not apply.

How do I make a full-width button? Pass class="w-full" (or fitContent for the opposite effect). VeanUI does not add a block prop because UnoCSS utilities cover this without expanding the API surface.

How do I show a loading indicator? Use SButtonLoading. It supports autoLoading (toggles loading during the click handler), a controlled loading prop, loadingPosition (start / center / end), loadingText, and a custom loadingIcon. The base SButton intentionally stays loading-free to keep its API minimal. While loading, the button sets aria-busy="true" and the loading icon is aria-hidden so the state is announced without redundant decoration.

How does SButtonGroup propagate props to children?SButtonGroup provides a context that forwards color, size, variant, shape, shadow, disabled, and fitContent to descendant SButton instances. A child’s own prop takes precedence over the group’s value.

Can I render the button as a link or another element? Yes. Use the as prop to change the root tag (as="a", as="div", …), or asChild to merge props onto a custom child. For routing-aware link buttons, prefer SButtonLink, which composes SButton with the Link component.

Changelog

Version history is grouped by release so you can quickly see what changed for this component across published versions.

v0.50.1

2026-10-09

Compare release

Optimization

restore soft variant styles for button component

Scope: buttonAuthors: soybeanjsView commit98b80

v0.50.0

2026-10-02

Compare release

Refactor

fold the customizer example into the basic example

Scope: buttonAuthors: soybeanjsView commit0c88d

Style

refine button styles and update variant classes for better consistency

Scope: buttonAuthors: soybeanjsView commit95d42

Style

refine button styles and update variant classes for better consistency

Scope: buttonAuthors: soybeanjsView commit95d42

Refactor

fold the customizer example into the basic example

Scope: buttonAuthors: soybeanjsView commit0c88d

v0.23.0

2026-05-18

Compare release

Optimization

add data-normal attribute and update styles

Scope: buttonAuthors: soybeanfeView commit28d0a

v0.19.0

2026-05-11

Compare release

Optimization

introduce buttonIconVariants for consistent button styling

Scope: buttonAuthors: soybeanfeView commit21b77

v0.18.0

2026-05-05

Compare release

Optimization

update button props and event types for consistency

Scope: buttonAuthors: soybeanfeView commit43c2b

v0.13.3

2026-03-21

Compare release

Feature

add type prop to ButtonProps interface and update default props

Scope: buttonAuthors: soybeanjsView commit1a0b9

v0.0.20

2026-01-21

Compare release

Docs

update documentation for Button component, including overview, main features, and API details

Scope: buttonAuthors: soybeanjsView commit4d06f

v0.0.2

2025-11-18

Compare release

Feature

add Button component with various states and configurations, including loading, icon, and group functionalities

Scope: buttonAuthors: soybeanjsView commit62bf7

Feature

add ButtonLink component and integrate it into the button example, enhancing link functionalities

Scope: buttonAuthors: soybeanjsView commit81d56

Feature

add fitContent prop to button components for improved layout flexibility

Scope: buttonAuthors: soybeanjsView commit5479b

Fix

include 'fitContent' in omitted props for button component

Scope: buttonAuthors: soybeanjsView commita1cf7

Refactor

rename button components to use 'S' prefix, enhance ButtonGroup with default props for orientation and direction

Scope: buttonAuthors: soybeanjsView commit5be48

Refactor

consolidate button group and button icon variants into a single file, update imports, and enhance button icon class binding

Scope: buttonAuthors: soybeanjsView commitb2fee

Fix

include 'fitContent' in omitted props for button component

Scope: buttonAuthors: soybeanjsView commita1cf7

Feature

add Button component with various states and configurations, including loading, icon, and group functionalities

Scope: buttonAuthors: soybeanjsView commit62bf7

Feature

add ButtonLink component and integrate it into the button example, enhancing link functionalities

Scope: buttonAuthors: soybeanjsView commit81d56

Feature

add fitContent prop to button components for improved layout flexibility

Scope: buttonAuthors: soybeanjsView commit5479b

Refactor

rename button components to use 'S' prefix, enhance ButtonGroup with default props for orientation and direction

Scope: buttonAuthors: soybeanjsView commit5be48

Refactor

consolidate button group and button icon variants into a single file, update imports, and enhance button icon class binding

Scope: buttonAuthors: soybeanjsView commitb2fee