Button

GitHub à
Un élément de bouton qui peut agir comme un lien ou déclencher une action.

Utilisation

Utilisez l'emplacement par défaut pour définir l'étiquette du bouton.

<template>
  <UButton>Button</UButton>
</template>

étiquette

Utilisez le prop label pour définir l'étiquette du bouton.

<template>
  <UButton label="Button" />
</template>

Couleur

Utilisez le prop color pour changer la couleur du bouton.

<template>
  <UButton color="neutral">Button</UButton>
</template>

Variant

Utilisez le prop variant pour changer la variante du bouton.

<template>
  <UButton color="neutral" variant="outline">Button</UButton>
</template>

Size

Utilisez le prop size pour modifier la taille du bouton.

<template>
  <UButton size="xl">Button</UButton>
</template>

Icône

Utilisez la prop icon pour afficher un Icon à l'intérieur du bouton.

<template>
  <UButton icon="i-lucide-rocket" size="md" color="primary" variant="solid">Button</UButton>
</template>

Utilisez les accessoires leading et trailing pour définir la position de l'icône ou les accessoires leading-icon et trailing-icon pour définir une icône différente pour chaque position.

<template>
  <UButton trailing-icon="i-lucide-arrow-right" size="md">Button</UButton>
</template>

Le label comme accessoire ou fente est facultatif afin que vous puissiez utiliser le bouton comme bouton d'icône uniquement.

<template>
  <UButton icon="i-lucide-search" size="md" color="primary" variant="solid" />
</template>

Avatars

Utilisez la prop avatar pour afficher un Avatar à l'intérieur du bouton.

<template>
  <UButton
    :avatar="{
      src: 'https://github.com/nuxt.png',
      loading: 'lazy'
    }"
    size="md"
    color="neutral"
    variant="outline"
  >
    Button
  </UButton>
</template>

Le label en tant qu 'accessoire ou fente est facultatif, vous pouvez donc utiliser le bouton comme bouton d'avatar uniquement.

<template>
  <UButton
    :avatar="{
      src: 'https://github.com/nuxt.png',
      loading: 'lazy'
    }"
    size="md"
    color="neutral"
    variant="outline"
  />
</template>

Vous pouvez passer n'importe quelle propriété du composant Link telle que to, target, etc.

<template>
  <UButton to="https://github.com/nuxt/ui" target="_blank">Button</UButton>
</template>

Lorsque le bouton est un lien ou lorsque vous utilisez la prop active, vous pouvez utiliser les props active-color et active-variant pour personnaliser l'état actif.

<template>
  <UButton active color="neutral" variant="outline" active-color="primary" active-variant="solid">
    Button
  </UButton>
</template>

Vous pouvez également utiliser les accessoires active-class et inactive-class pour personnaliser l'état actif.

<template>
  <UButton active active-class="font-bold" inactive-class="font-light">Button</UButton>
</template>
Vous pouvez configurer ces styles globalement dans votre fichier app.config.ts sous la touche ui.button.variants.active.
export default defineAppConfig({
  ui: {
    button: {
      variants: {
        active: {
          true: {
            base: 'font-bold'
          }
        }
      }
    }
  }
})

Chargement

Utilisez le prop loading pour afficher une icône de chargement et désactiver le bouton.

<template>
  <UButton loading>Button</UButton>
</template>

Utilisez la prop loading-auto pour afficher l'icône de chargement automatiquement pendant que la promesse @click est en attente.

<script setup lang="ts">
async function onClick() {
  return new Promise<void>(res => setTimeout(res, 1000))
}
</script>

<template>
  <UButton loading-auto @click="onClick">
    Button
  </UButton>
</template>

Cela fonctionne également avec le composant Form.

<script setup lang="ts">
const state = reactive({ fullName: '' })

async function onSubmit() {
  return new Promise<void>(res => setTimeout(res, 1000))
}

async function validate(data: Partial<typeof state>) {
  if (!data.fullName?.length) return [{ name: 'fullName', message: 'Required' }]
  return []
}
</script>

<template>
  <UForm :state="state" :validate="validate" @submit="onSubmit">
    <UFormField name="fullName" label="Full name">
      <UInput v-model="state.fullName" />
    </UFormField>
    <UButton type="submit" class="mt-2" loading-auto>
      Submit
    </UButton>
  </UForm>
</template>
<script setup lang="ts">
import { reactive } from 'vue'

const state = reactive({ fullName: '' })

async function onSubmit() {
  return new Promise<void>(res => setTimeout(res, 1000))
}

async function validate(data: Partial<typeof state>) {
  if (!data.fullName?.length) return [{ name: 'fullName', message: 'Required' }]
  return []
}
</script>

<template>
  <UForm :state="state" :validate="validate" @submit="onSubmit">
    <UFormField name="fullName" label="Full name">
      <UInput v-model="state.fullName" />
    </UFormField>
    <UButton type="submit" class="mt-2" loading-auto>
      Submit
    </UButton>
  </UForm>
</template>

Chargement Icône

Utilisez la prop loading-icon pour personnaliser l'icône de chargement. Par défaut, i-lucide-loader-circle.

<template>
  <UButton loading loading-icon="i-lucide-loader">Button</UButton>
</template>
Vous pouvez personnaliser cette icône globalement dans votre app.config.ts sous la touche ui.icons.loading.
Vous pouvez personnaliser cette icône globalement dans votre vite.config.ts sous la touche ui.icons.loading.

Désactivé

Utilisez le prop disabled pour désactiver le bouton.

<template>
  <UButton disabled>Button</UButton>
</template>

Exemples

class avec prop

Utilisez la prop class pour remplacer les styles de base du bouton.

<template>
  <UButton class="font-bold rounded-full">Button</UButton>
</template>

ui prop

Utilisez la prop ui pour remplacer les styles de slots du bouton.

<template>
  <UButton
    icon="i-lucide-rocket"
    color="neutral"
    variant="outline"
    :ui="{
      leadingIcon: 'text-primary'
    }"
  >
    Button
  </UButton>
</template>

API

Props équipement

Prop Default Type
as
'button'
any

The element or component this component should render as when not a link.

label
string
color
'primary'
"error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"
activeColor
"error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"
variant
'solid'
"solid" | "outline" | "soft" | "subtle" | "ghost" | "link"
activeVariant
"solid" | "outline" | "soft" | "subtle" | "ghost" | "link"
size
'md'
"xs" | "sm" | "md" | "lg" | "xl"
square
boolean

Render the button with equal padding on all sides.

block
boolean

Render the button full width.

loadingAuto
boolean

Set loading state automatically based on the @click promise state

icon
any

Display an icon based on the leading and trailing props.

avatar
AvatarProps

Display an avatar on the left side.

leading
boolean

When true, the icon will be displayed on the left side.

leadingIcon
any

Display an icon on the left side.

trailing
boolean

When true, the icon will be displayed on the right side.

trailingIcon
any

Display an icon on the right side.

loading
boolean

When true, the loading icon will be displayed.

loadingIcon
appConfig.ui.icons.loading
any

The icon when the loading prop is true.

to
string | it | et

Route Location the link should navigate to when clicked on.

autofocus
false | true | "true" | "false"
disabled
boolean
name
string
type
'button'
"reset" | "submit" | "button"

The type of the button when not a link.

download
any
hreflang
string
media
string
ping
string
target
null | string | "_blank" | "_parent" | "_self" | "_top"

Where to display the linked URL, as the name for a browsing context.

referrerpolicy
"" | "no-referrer" | "no-referrer-when-downgrade" | "origin" | "origin-when-cross-origin" | "same-origin" | "strict-origin" | "strict-origin-when-cross-origin" | "unsafe-url"
active
boolean

Force the link to be active independent of the current route.

locale
string | false | true

Control i18n auto-localization when @nuxtjs/i18n is installed.

  • undefined / true (default): auto-localizes to the current locale using $localePath. Paths already carrying a locale prefix (from e.g. switchLocalePath()) are detected and left untouched to prevent double-prefixing.
  • false: explicitly disables auto-localization.
  • string: localizes to a specific locale (e.g. 'fr').
trailingSlash
"remove" | "append"

An option to either add or remove trailing slashes in the href for this specific link. Overrides the global trailingSlash option if provided.

ui
{ base?: SlotClass; label?: SlotClass; leadingIcon?: SlotClass; leadingAvatar?: SlotClass; leadingAvatarSize?: SlotClass; trailingIcon?: SlotClass; }
Ce composant prend également en charge tous les attributs HTML natifs <button>.
Le composant Button étend le composant Link.Consultez le code source sur GitHub.

Slots

Slot Type
leading
{ ui: object; }
default
{ ui: object; }
trailing
{ ui: object; }

Thème

app.config.ts
export default defineAppConfig({
  ui: {
    button: {
      slots: {
        base: [
          'rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75',
          'transition-colors'
        ],
        label: 'truncate',
        leadingIcon: 'shrink-0',
        leadingAvatar: 'shrink-0',
        leadingAvatarSize: '',
        trailingIcon: 'shrink-0'
      },
      variants: {
        fieldGroup: {
          horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]',
          vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
        },
        color: {
          primary: '',
          secondary: '',
          success: '',
          info: '',
          warning: '',
          error: '',
          neutral: ''
        },
        variant: {
          solid: '',
          outline: '',
          soft: '',
          subtle: '',
          ghost: '',
          link: ''
        },
        size: {
          xs: {
            base: 'px-2 py-1 text-xs gap-1',
            leadingIcon: 'size-4',
            leadingAvatarSize: '3xs',
            trailingIcon: 'size-4'
          },
          sm: {
            base: 'px-2.5 py-1.5 text-xs gap-1.5',
            leadingIcon: 'size-4',
            leadingAvatarSize: '3xs',
            trailingIcon: 'size-4'
          },
          md: {
            base: 'px-2.5 py-1.5 text-sm gap-1.5',
            leadingIcon: 'size-5',
            leadingAvatarSize: '2xs',
            trailingIcon: 'size-5'
          },
          lg: {
            base: 'px-3 py-2 text-sm gap-2',
            leadingIcon: 'size-5',
            leadingAvatarSize: '2xs',
            trailingIcon: 'size-5'
          },
          xl: {
            base: 'px-3 py-2 text-base gap-2',
            leadingIcon: 'size-6',
            leadingAvatarSize: 'xs',
            trailingIcon: 'size-6'
          }
        },
        block: {
          true: {
            base: 'w-full justify-center',
            trailingIcon: 'ms-auto'
          }
        },
        square: {
          true: ''
        },
        leading: {
          true: ''
        },
        trailing: {
          true: ''
        },
        loading: {
          true: ''
        },
        active: {
          true: {
            base: ''
          },
          false: {
            base: ''
          }
        }
      },
      compoundVariants: [
        {
          color: 'primary',
          variant: 'solid',
          class: 'text-inverted bg-primary hover:bg-primary/75 active:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary outline-primary/25 focus-visible:outline-3'
        },
        {
          color: 'primary',
          variant: 'outline',
          class: 'ring ring-inset ring-primary/50 text-primary hover:bg-primary/10 active:bg-primary/10 disabled:bg-transparent aria-disabled:bg-transparent dark:disabled:bg-transparent dark:aria-disabled:bg-transparent outline-primary/25 focus-visible:outline-3 focus-visible:ring-primary'
        },
        {
          color: 'primary',
          variant: 'soft',
          class: 'text-primary bg-primary/10 hover:bg-primary/15 active:bg-primary/15 outline-primary/25 focus-visible:outline-3 disabled:bg-primary/10 aria-disabled:bg-primary/10'
        },
        {
          color: 'primary',
          variant: 'subtle',
          class: 'text-primary ring ring-inset ring-primary/25 bg-primary/10 hover:bg-primary/15 active:bg-primary/15 disabled:bg-primary/10 aria-disabled:bg-primary/10 outline-primary/25 focus-visible:outline-3 focus-visible:ring-primary'
        },
        {
          color: 'primary',
          variant: 'ghost',
          class: 'text-primary hover:bg-primary/10 active:bg-primary/10 outline-primary/25 focus-visible:outline-3 disabled:bg-transparent aria-disabled:bg-transparent dark:disabled:bg-transparent dark:aria-disabled:bg-transparent'
        },
        {
          color: 'primary',
          variant: 'link',
          class: 'text-primary hover:text-primary/75 active:text-primary/75 disabled:text-primary aria-disabled:text-primary outline-primary/25 focus-visible:outline-3'
        },
        {
          color: 'neutral',
          variant: 'solid',
          class: 'text-inverted bg-inverted hover:bg-inverted/90 active:bg-inverted/90 disabled:bg-inverted aria-disabled:bg-inverted outline-inverted/25 focus-visible:outline-3'
        },
        {
          color: 'neutral',
          variant: 'outline',
          class: 'ring ring-inset ring-accented text-default bg-default hover:bg-elevated active:bg-elevated disabled:bg-default aria-disabled:bg-default outline-inverted/25 focus-visible:outline-3 focus-visible:ring-inverted'
        },
        {
          color: 'neutral',
          variant: 'soft',
          class: 'text-default bg-elevated hover:bg-accented/75 active:bg-accented/75 outline-inverted/25 focus-visible:outline-3 disabled:bg-elevated aria-disabled:bg-elevated'
        },
        {
          color: 'neutral',
          variant: 'subtle',
          class: 'ring ring-inset ring-accented text-default bg-elevated hover:bg-accented/75 active:bg-accented/75 disabled:bg-elevated aria-disabled:bg-elevated outline-inverted/25 focus-visible:outline-3 focus-visible:ring-inverted'
        },
        {
          color: 'neutral',
          variant: 'ghost',
          class: 'text-default hover:bg-elevated active:bg-elevated outline-inverted/25 focus-visible:outline-3 hover:disabled:bg-transparent dark:hover:disabled:bg-transparent hover:aria-disabled:bg-transparent dark:hover:aria-disabled:bg-transparent'
        },
        {
          color: 'neutral',
          variant: 'link',
          class: 'text-muted hover:text-default active:text-default disabled:text-muted aria-disabled:text-muted outline-inverted/25 focus-visible:outline-3'
        },
        {
          size: 'xs',
          square: true,
          class: 'p-1'
        },
        {
          size: 'sm',
          square: true,
          class: 'p-1.5'
        },
        {
          size: 'md',
          square: true,
          class: 'p-1.5'
        },
        {
          size: 'lg',
          square: true,
          class: 'p-2'
        },
        {
          size: 'xl',
          square: true,
          class: 'p-2'
        },
        {
          loading: true,
          leading: true,
          class: {
            leadingIcon: 'animate-spin'
          }
        },
        {
          loading: true,
          leading: false,
          trailing: true,
          class: {
            trailingIcon: 'animate-spin'
          }
        }
      ],
      defaultVariants: {
        color: 'primary',
        variant: 'solid',
        size: 'md'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        button: {
          slots: {
            base: [
              'rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75',
              'transition-colors'
            ],
            label: 'truncate',
            leadingIcon: 'shrink-0',
            leadingAvatar: 'shrink-0',
            leadingAvatarSize: '',
            trailingIcon: 'shrink-0'
          },
          variants: {
            fieldGroup: {
              horizontal: 'not-only:first:rounded-e-none not-only:last:rounded-s-none not-last:not-first:rounded-none focus-visible:z-[1]',
              vertical: 'not-only:first:rounded-b-none not-only:last:rounded-t-none not-last:not-first:rounded-none focus-visible:z-[1]'
            },
            color: {
              primary: '',
              secondary: '',
              success: '',
              info: '',
              warning: '',
              error: '',
              neutral: ''
            },
            variant: {
              solid: '',
              outline: '',
              soft: '',
              subtle: '',
              ghost: '',
              link: ''
            },
            size: {
              xs: {
                base: 'px-2 py-1 text-xs gap-1',
                leadingIcon: 'size-4',
                leadingAvatarSize: '3xs',
                trailingIcon: 'size-4'
              },
              sm: {
                base: 'px-2.5 py-1.5 text-xs gap-1.5',
                leadingIcon: 'size-4',
                leadingAvatarSize: '3xs',
                trailingIcon: 'size-4'
              },
              md: {
                base: 'px-2.5 py-1.5 text-sm gap-1.5',
                leadingIcon: 'size-5',
                leadingAvatarSize: '2xs',
                trailingIcon: 'size-5'
              },
              lg: {
                base: 'px-3 py-2 text-sm gap-2',
                leadingIcon: 'size-5',
                leadingAvatarSize: '2xs',
                trailingIcon: 'size-5'
              },
              xl: {
                base: 'px-3 py-2 text-base gap-2',
                leadingIcon: 'size-6',
                leadingAvatarSize: 'xs',
                trailingIcon: 'size-6'
              }
            },
            block: {
              true: {
                base: 'w-full justify-center',
                trailingIcon: 'ms-auto'
              }
            },
            square: {
              true: ''
            },
            leading: {
              true: ''
            },
            trailing: {
              true: ''
            },
            loading: {
              true: ''
            },
            active: {
              true: {
                base: ''
              },
              false: {
                base: ''
              }
            }
          },
          compoundVariants: [
            {
              color: 'primary',
              variant: 'solid',
              class: 'text-inverted bg-primary hover:bg-primary/75 active:bg-primary/75 disabled:bg-primary aria-disabled:bg-primary outline-primary/25 focus-visible:outline-3'
            },
            {
              color: 'primary',
              variant: 'outline',
              class: 'ring ring-inset ring-primary/50 text-primary hover:bg-primary/10 active:bg-primary/10 disabled:bg-transparent aria-disabled:bg-transparent dark:disabled:bg-transparent dark:aria-disabled:bg-transparent outline-primary/25 focus-visible:outline-3 focus-visible:ring-primary'
            },
            {
              color: 'primary',
              variant: 'soft',
              class: 'text-primary bg-primary/10 hover:bg-primary/15 active:bg-primary/15 outline-primary/25 focus-visible:outline-3 disabled:bg-primary/10 aria-disabled:bg-primary/10'
            },
            {
              color: 'primary',
              variant: 'subtle',
              class: 'text-primary ring ring-inset ring-primary/25 bg-primary/10 hover:bg-primary/15 active:bg-primary/15 disabled:bg-primary/10 aria-disabled:bg-primary/10 outline-primary/25 focus-visible:outline-3 focus-visible:ring-primary'
            },
            {
              color: 'primary',
              variant: 'ghost',
              class: 'text-primary hover:bg-primary/10 active:bg-primary/10 outline-primary/25 focus-visible:outline-3 disabled:bg-transparent aria-disabled:bg-transparent dark:disabled:bg-transparent dark:aria-disabled:bg-transparent'
            },
            {
              color: 'primary',
              variant: 'link',
              class: 'text-primary hover:text-primary/75 active:text-primary/75 disabled:text-primary aria-disabled:text-primary outline-primary/25 focus-visible:outline-3'
            },
            {
              color: 'neutral',
              variant: 'solid',
              class: 'text-inverted bg-inverted hover:bg-inverted/90 active:bg-inverted/90 disabled:bg-inverted aria-disabled:bg-inverted outline-inverted/25 focus-visible:outline-3'
            },
            {
              color: 'neutral',
              variant: 'outline',
              class: 'ring ring-inset ring-accented text-default bg-default hover:bg-elevated active:bg-elevated disabled:bg-default aria-disabled:bg-default outline-inverted/25 focus-visible:outline-3 focus-visible:ring-inverted'
            },
            {
              color: 'neutral',
              variant: 'soft',
              class: 'text-default bg-elevated hover:bg-accented/75 active:bg-accented/75 outline-inverted/25 focus-visible:outline-3 disabled:bg-elevated aria-disabled:bg-elevated'
            },
            {
              color: 'neutral',
              variant: 'subtle',
              class: 'ring ring-inset ring-accented text-default bg-elevated hover:bg-accented/75 active:bg-accented/75 disabled:bg-elevated aria-disabled:bg-elevated outline-inverted/25 focus-visible:outline-3 focus-visible:ring-inverted'
            },
            {
              color: 'neutral',
              variant: 'ghost',
              class: 'text-default hover:bg-elevated active:bg-elevated outline-inverted/25 focus-visible:outline-3 hover:disabled:bg-transparent dark:hover:disabled:bg-transparent hover:aria-disabled:bg-transparent dark:hover:aria-disabled:bg-transparent'
            },
            {
              color: 'neutral',
              variant: 'link',
              class: 'text-muted hover:text-default active:text-default disabled:text-muted aria-disabled:text-muted outline-inverted/25 focus-visible:outline-3'
            },
            {
              size: 'xs',
              square: true,
              class: 'p-1'
            },
            {
              size: 'sm',
              square: true,
              class: 'p-1.5'
            },
            {
              size: 'md',
              square: true,
              class: 'p-1.5'
            },
            {
              size: 'lg',
              square: true,
              class: 'p-2'
            },
            {
              size: 'xl',
              square: true,
              class: 'p-2'
            },
            {
              loading: true,
              leading: true,
              class: {
                leadingIcon: 'animate-spin'
              }
            },
            {
              loading: true,
              leading: false,
              trailing: true,
              class: {
                trailingIcon: 'animate-spin'
              }
            }
          ],
          defaultVariants: {
            color: 'primary',
            variant: 'solid',
            size: 'md'
          }
        }
      }
    })
  ]
})
Some colors in compoundVariants are omitted for readability. Check out the source code on GitHub.

Changelog

No recent changes