Skip to content

Button ​

Neo-brutalist button component supporting 9 variants, 4 sizes + icon mode, loading state, and asChild composition support.

Demo ​

Preview

变体

尺寸

状态

提交按钮

装饰形态(flair)

Installation ​

pnpm dlx brutx-vue@latest add button

Usage ​

vue
<script setup>
import { Button } from 'brutx-ui-vue'
</script>

<template>
    <Button variant="primary" size="default">
        Click me
    </Button>
</template>

Loading State ​

vue
<script setup>
import { ref } from 'vue'
import { Button } from 'brutx-ui-vue'

const isLoading = ref(false)

async function handleSubmit() {
    isLoading.value = true
    await new Promise(resolve => setTimeout(resolve, 2000))
    isLoading.value = false
}
</script>

<template>
    <Button variant="primary" :loading="isLoading" @click="handleSubmit">
        Save Changes
    </Button>
</template>

Disabled State ​

vue
<script setup>
import { Button } from 'brutx-ui-vue'
</script>

<template>
    <Button variant="primary" disabled>
        Disabled
    </Button>
</template>

Submit Button and Pending Text ​

Set type="submit" to render the button as a form submit button. Combined with loading and pendingText, the button displays a pending text (replacing the slot content) during submission. When pendingText is not provided, it falls back to the i18n default (submitButton.submitting):

vue
<script setup>
import { ref } from 'vue'
import { Button } from 'brutx-ui-vue'

const isLoading = ref(false)

async function handleSubmit() {
    isLoading.value = true
    await new Promise(resolve => setTimeout(resolve, 2000))
    isLoading.value = false
}
</script>

<template>
    <form @submit.prevent="handleSubmit">
        <Button type="submit" variant="primary" :loading="isLoading" pending-text="Saving...">
            Save
        </Button>
    </form>
</template>

The pending text is shown and the slot content is hidden only when type="submit" and loading=true. In all other cases, the slot content renders normally and the loading icon still appears.

asChild ​

Use asChild to render button styles onto a custom element (e.g., a router link):

vue
<script setup>
import { Button } from 'brutx-ui-vue'
import { RouterLink } from 'vue-router'
</script>

<template>
    <Button as-child>
        <RouterLink to="/about">About</RouterLink>
    </Button>
</template>

Glitch Effect ​

Button includes effect="glitch" for the glitch tear animation.

vue
<template>
    <Button
        effect="glitch"
        variant="primary"
        glitch-trigger="click"
        glitch-speed="fast"
        glitch-direction="both"
        data-text="GLITCH"
    >
        GLITCH
    </Button>
</template>

Note: when building a glitch button directly with the exported buttonVariants({ effect: 'glitch' }), pass glitchSpeed and glitchDirection explicitly — the medium/horizontal defaults are provided by the <Button> component, not by the raw utility function.

With the default effect="none", Button creates no effect media listeners, timers, or text synchronization. Both autoplay and the exposed play() method respect this switch. Glitch playback stops while disabled, loading, or reduced motion is enabled. KeepAlive deactivation and unmount release resources; activation reads the current motion preference before resuming.

Variants ​

VariantDescription
defaultBackground color with hard shadow
primaryPrimary (coral) background
secondarySecondary (mint) background
accentAccent (yellow) background
dangerDestructive (red) background with white text
successSuccess (green) background
outlineTransparent background with inversion on hover
ghostNo border or shadow with subtle hover effect
linkNo border or shadow with underline on hover
vue
<template>
    <Button variant="primary">Primary variant</Button>
</template>

Decorative Flair ​

The flair dimension composes orthogonally with color variants, offering three mechanical texture modes:

FlairDescription
noneDefault; outputs no extra decoration classes
stackedMulti-layer rainbow hard shadow with matched 1.5x press displacement
hazardWarning stripes surround a solid yellow label with black text, preserving text contrast on hover
ticketTicket tear — semicircle notches at the left/right midpoints
vue
<template>
    <Button variant="primary" flair="stacked">Stacked shadow</Button>
    <Button variant="accent" flair="hazard">Hazard stripes</Button>
    <Button variant="default" flair="ticket">Ticket notch</Button>
</template>

Sizes ​

SizeHeightPaddingFont Size
smh-9px-3 py-1text-sm
defaulth-11px-5 py-2text-base
lgh-14px-8 py-3text-lg
xlh-16px-10 py-4text-xl
iconh-11 w-11p-0—

API Reference ​

Button — Props
NameTypeDefaultDescription
variant
"accent" | "danger" | "default" | "ghost" | "link" | "outline" | "primary" | "secondary" | "success" | undefined
"default"
Controls the button’s visual variant, including its color and interaction-state styles.
Details

Declared type

NonNullable<"default" | "ghost" | "primary" | "secondary" | "success" | "danger" | "accent" | "outline" | "link" | null | undefined> | undefined

Literal values

  • "accent"
  • "danger"
  • "default"
  • "ghost"
  • "link"
  • "outline"
  • "primary"
  • "secondary"
  • "success"

Default value details

Resolved value
"default"

Source

Button.vue:21

packages/ui/src/components/button/Button.vue

size
"default" | "icon" | "lg" | "sm" | "xl" | undefined
"default"
Controls the button dimensions and padding. Use icon for a square icon button.
Details

Declared type

NonNullable<"default" | "lg" | "sm" | "xl" | "icon" | null | undefined> | undefined

Literal values

  • "default"
  • "icon"
  • "lg"
  • "sm"
  • "xl"

Default value details

Resolved value
"default"

Source

Button.vue:23

packages/ui/src/components/button/Button.vue

flair
"none" | "stacked" | "hazard" | "ticket" | undefined
"none"
Adds a decorative treatment such as stacked shadows, hazard stripes, or a ticket notch. It composes independently with the color variant.
Details

Declared type

"none" | "stacked" | "hazard" | "ticket" | undefined

Literal values

  • "hazard"
  • "none"
  • "stacked"
  • "ticket"

Default value details

Resolved value
"none"

Source

Button.vue:25

packages/ui/src/components/button/Button.vue

asChild
boolean | undefined
false
Merges the button props, styles, and interaction behavior into its single child element.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
false

Source

Button.vue:27

packages/ui/src/components/button/Button.vue

type
"button" | "submit" | "reset" | undefined
undefined
Sets the native button type. When omitted, the rendered native button uses the browser’s default button behavior.
Details

Declared type

"button" | "submit" | "reset" | undefined

Literal values

  • "button"
  • "reset"
  • "submit"

Default value details

Resolved value
undefined

Source

Button.vue:29

packages/ui/src/components/button/Button.vue

loading
boolean | undefined
false
Shows a loading icon and places the button in its disabled state.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
false

Source

Button.vue:31

packages/ui/src/components/button/Button.vue

disabled
boolean | undefined
false
Disables the button’s normal user interaction.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
false

Source

Button.vue:33

packages/ui/src/components/button/Button.vue

pendingText
string | undefined
undefined

Runtime fallback:When `pendingText` is `undefined` or `null`, the component reads `submitButton.submitting`, whose English text is “Submitting...”.

Text used as the default slot fallback while a submit button is loading. Explicit slot content takes precedence.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined
Runtime fallback
When `pendingText` is `undefined` or `null`, the component reads `submitButton.submitting`, whose English text is “Submitting...”.

Applied by the component under the documented runtime conditions.

Source

Button.vue:35

packages/ui/src/components/button/Button.vue

pressed
boolean | undefined
undefined
Sets the pressed state for a toggle button and is reflected through aria-pressed.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
undefined

Source

Button.vue:37

packages/ui/src/components/button/Button.vue

expanded
boolean | undefined
undefined
Sets whether the content controlled by the button is expanded and is reflected through aria-expanded.
Details

Declared type

boolean | undefined

Literal values

  • false
  • true

Default value details

Resolved value
undefined

Source

Button.vue:39

packages/ui/src/components/button/Button.vue

effect
"none" | "glitch" | undefined
"none"
Enables or disables the glitch visual effect. The effect is disabled by default.
Details

Declared type

"none" | "glitch" | undefined

Literal values

  • "glitch"
  • "none"

Default value details

Resolved value
"none"

Source

Button.vue:41

packages/ui/src/components/button/Button.vue

glitchTrigger
GlitchTrigger | undefined
"hover"
Selects how the glitch effect starts: on hover, on click, on autoplay, or never. It applies only when effect="glitch".
Details

Declared type

GlitchTrigger | undefined

Literal values

  • "autoplay"
  • "click"
  • "hover"
  • "none"

Referenced types

GlitchTrigger
Type definition — GlitchTrigger
export type GlitchTrigger = 'hover' | 'click' | 'autoplay' | 'none'

Default value details

Resolved value
"hover"

Source

Button.vue:43

packages/ui/src/components/button/Button.vue

glitchInterval
number | undefined
3000
Sets the autoplay interval for the glitch effect in milliseconds. It applies only when glitchTrigger="autoplay" and is clamped to the effect timing limits.
Details

Declared type

number | undefined

Default value details

Declaration
DEFAULT_AUTOPLAY_INTERVAL_MS

Source: packages/ui/src/components/button/Button.vue

Resolved value
3000

Source

Button.vue:45

packages/ui/src/components/button/Button.vue

glitchSpeed
ButtonGlitchSpeed | undefined
"medium"
Controls the playback speed of the glitch animation.
Details

Declared type

ButtonGlitchSpeed | undefined

Literal values

  • "fast"
  • "medium"
  • "slow"

Referenced types

ButtonGlitchSpeed
Type definition — ButtonGlitchSpeed
type ButtonGlitchSpeed = NonNullable<ButtonVariantProps['glitchSpeed']>

Default value details

Resolved value
"medium"

Source

Button.vue:47

packages/ui/src/components/button/Button.vue

glitchDirection
ButtonGlitchDirection | undefined
"horizontal"
Controls the direction of the glitch distortion.
Details

Declared type

ButtonGlitchDirection | undefined

Literal values

  • "both"
  • "horizontal"
  • "vertical"

Referenced types

ButtonGlitchDirection
Type definition — ButtonGlitchDirection
type ButtonGlitchDirection = NonNullable<ButtonVariantProps['glitchDirection']>

Default value details

Declaration
'horizontal'

Source: packages/ui/src/components/button/Button.vue

Resolved value
"horizontal"

Source

Button.vue:49

packages/ui/src/components/button/Button.vue

class
string | undefined
undefined
Additional CSS classes merged into the button root element.
Details

Declared type

string | undefined

Default value details

Resolved value
undefined

Source

Button.vue:50

packages/ui/src/components/button/Button.vue

Button — Events
NameSignature or typeDescription
@click
MouseEvent
The rendered root’s native click event is available to consumers through Vue attribute fallthrough; Button does not declare a custom event with this name.
  • When disabled or loading is true, the internal click handler calls preventDefault() and stopPropagation(). Native button mode also sets disabled; asChild mode uses aria-disabled and pointer-events-none.
Details

Declared type

MouseEvent

Source

Button.vue

packages/ui/src/components/button/Button.vue

Button — Slots
NameSignature or typeDescription
#default
{}
The button content. If no slot content is provided, pending text is shown only when type="submit" and loading are both true. Explicit slot content takes precedence.
Details

Declared type

{}

Source

Button.vue

packages/ui/src/components/button/Button.vue

Button — Exposes
NameSignature or typeDescription
play
() => void
Manually activates the glitch animation. It takes effect only when effect="glitch"; it bypasses the trigger and disabled checks, while a reduced-motion preference still hides the animation.
Details

Declared type

() => void

Source

Button.vue:211

packages/ui/src/components/button/Button.vue

stop
() => void
Immediately clears the active glitch animation state.
Details

Declared type

() => void

Source

Button.vue:212

packages/ui/src/components/button/Button.vue

Accessibility ​

  • Keyboard: Supports Space / Enter to trigger click
  • ARIA Attributes: Automatically sets the disabled attribute (non-asChild mode) or aria-disabled="true" (asChild mode) when disabled; automatically sets aria-busy="true" when loading
  • Focus Management: Supports keyboard navigation and focus styles (focus:outline)

Brute force builds.