Skip to content
75NeoUI

component · vue

Button

Six variants across seven colors and five sizes, with block, square, loading and icon slots.

button

variant and color are independent, so the two together describe a table of forty-two cells rather than a list of named buttons. Pick the weight from variant and the meaning from color.

<Button variant="solid" color="primary">Save</Button>
<Button variant="outline" color="neutral">Cancel</Button>
<Button variant="ghost" color="error">Delete</Button>
<Button variant="solid" color="primary">Save</Button>
<Button variant="outline" color="neutral">Cancel</Button>
<Button variant="ghost" color="error">Delete</Button>

Size is padding rather than a fixed height, so a button grows with whatever type scale it inherits instead of clipping.

Icons

Pass a rendered icon to leadingIcon or trailingIcon. In Vue the leading and trailing slots take arbitrary markup and win over the props of the same name.

import { ArrowRight } from "lucide-react";

<Button trailingIcon={<ArrowRight />}>Continue</Button>;
<script setup lang="ts">
import { ArrowRight } from "@lucide/vue";
</script>

<template>
  <Button :trailing-icon="ArrowRight">Continue</Button>
</template>

An empty icon slot still costs width, so a slot renders only when something fills it or leading / trailing reserved it on purpose. Reserve one when a column of buttons should keep its labels aligned.

A button with an icon and no label sets square for itself, so an icon button needs nothing said about its padding.

Loading

loading disables the button and spins whichever icon slot is showing. A button already showing a trailing icon and nothing leading spins that one in place, rather than growing a second icon box on the other side.

<Button loading>Saving</Button>
<Button loading loadingIcon={<Spinner />}>Saving</Button>
<Button loading>Saving</Button>
<Button loading :loading-icon="Spinner">Saving</Button>

Slots

The same word names the recipe slot, the data-slot attribute and the key in ui.

  • base
  • label
  • leadingIcon
  • trailingIcon

Variants

Read off the recipe, so these are the values that actually resolve. A Theme layer can change which one is the default; it cannot add a value.

variant
solidoutlinesoftsubtleghostlink
color
primarysecondarysuccessinfowarningerrorneutral
size
xssmmdlgxl
block
true
square
true
leading
true
trailing
true
loading
true

Props

Taken by both adapters, read out of the component module. The same names and the same types work in React and Vue.

ui

ButtonUI

Per-slot class overrides.

variant

"solid" | "outline" | "soft" | "subtle" | "ghost" | "link"

Defaults to "solid"

size

"xs" | "sm" | "md" | "lg" | "xl"

Defaults to "md"

color

"primary" | "secondary" | "success" | "info" | "warning" | "error" | "neutral"

Defaults to "primary"

block

boolean

Fill the container's width.

square

boolean

Equal padding on all sides. Defaults to whether the button has a label, so an icon-only button is square without being told.

disabled

boolean

loading

boolean

Spins whichever icon slot is showing, and disables the button.

loadingIcon

Component

Replaces the default spinner.

leading

boolean

Reserve the leading slot even when it holds nothing, to keep labels aligned.

trailing

boolean

Reserve the trailing slot even when it holds nothing.

leadingIcon

Component

trailingIcon

Component

Vue only

type

"button" | "submit" | "reset"

class

unknown

#default
The label.
#leading
Content before the label. Falls back to `leadingIcon`.
#trailing
Content after the label. Falls back to `trailingIcon`.
#loadingIcon
Replaces the spinner shown while loading.