Empty

GitHub à
Un composant pour afficher un état vide.

Utilisation

Utilisez le composant vide pour afficher un état d'espace réservé lorsqu 'il n'y a pas de contenu à afficher.

No projects found

It looks like you haven't added any projects. Create one to get started.

Titre

Utilisez la prop title pour définir le titre de l'état vide.

No projects found

<template>
  <UEmpty title="No projects found" />
</template>

Description

Utilisez la prop description pour définir la description de l'état vide.

No projects found

It looks like you haven't added any projects. Create one to get started.
<template>
  <UEmpty
    title="No projects found"
    description="It looks like you haven't added any projects. Create one to get started."
  />
</template>

Icône

Utilisez le prop icon pour définir l'icône de l'état vide.

No projects found

It looks like you haven't added any projects. Create one to get started.
<template>
  <UEmpty
    icon="i-lucide-file"
    title="No projects found"
    description="It looks like you haven't added any projects. Create one to get started."
  />
</template>

Avatars

Utilisez le prop avatar pour définir l'avatar de l'état vide.

No projects found

It looks like you haven't added any projects. Create one to get started.
<template>
  <UEmpty
    :avatar="{
      src: 'https://github.com/nuxt.png'
    }"
    title="No projects found"
    description="It looks like you haven't added any projects. Create one to get started."
  />
</template>

Chargement: badge{label="4.10+" class="align-text-top"}

Utilisez la prop loading pour afficher une icône de chargement à la place de l'icône. La mise en page reste identique, de sorte que vous pouvez basculer entre les états de chargement et vide sans changement de mise en page.

Loading projects

Please wait while we fetch your projects.
<template>
  <UEmpty
    icon="i-lucide-file"
    loading
    title="Loading projects"
    description="Please wait while we fetch your projects."
  />
</template>

Icône de chargement: badge{label="4.10+" class="align-text-top"}

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

Loading projects

Please wait while we fetch your projects.
<template>
  <UEmpty
    icon="i-lucide-file"
    loading
    loading-icon="i-lucide-loader"
    title="Loading projects"
    description="Please wait while we fetch your projects."
  />
</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 clé ui.icons.loading.

Actions

Utilisez la prop actions pour ajouter des actions Button à l'état vide.

No projects found

It looks like you haven't added any projects. Create one to get started.
<template>
  <UEmpty
    icon="i-lucide-file"
    title="No projects found"
    description="It looks like you haven't added any projects. Create one to get started."
    :actions="[
      {
        icon: 'i-lucide-plus',
        label: 'Create new'
      },
      {
        icon: 'i-lucide-refresh-cw',
        label: 'Refresh',
        color: 'neutral',
        variant: 'subtle'
      }
    ]"
  />
</template>

Variant

Utilisez le prop variant pour changer la variante de l'état vide.

No notifications

You're all caught up. New notifications will appear here.
<template>
  <UEmpty
    variant="naked"
    icon="i-lucide-bell"
    title="No notifications"
    description="You're all caught up. New notifications will appear here."
    :actions="[
      {
        icon: 'i-lucide-refresh-cw',
        label: 'Refresh',
        color: 'neutral',
        variant: 'subtle'
      }
    ]"
  />
</template>

Size équivalent

Utilisez la prop size pour modifier la taille de l'état vide.

No notifications

You're all caught up. New notifications will appear here.
<template>
  <UEmpty
    size="xl"
    icon="i-lucide-bell"
    title="No notifications"
    description="You're all caught up. New notifications will appear here."
    :actions="[
      {
        icon: 'i-lucide-refresh-cw',
        label: 'Refresh',
        color: 'neutral',
        variant: 'subtle'
      }
    ]"
  />
</template>

Exemples

Avec slots

Utilisez les slots disponibles pour créer un état vide plus complexe.

UnjsNuxt

No team members

Invite your team to collaborate on this project.
danielroe

Daniel Roe

danielroe

pi0

Pooya Parsa

pi0

atinux

Sébastien Chopin

atinux

benjamincanac

Benjamin Canac

benjamincanac

<script setup lang="ts">
import type { UserProps } from '@nuxt/ui'

const members: UserProps[] = [
  {
    name: 'Daniel Roe',
    description: 'danielroe',
    to: 'https://github.com/danielroe',
    target: '_blank',
    avatar: {
      src: 'https://github.com/danielroe.png',
      alt: 'danielroe',
      loading: 'lazy' as const
    }
  },
  {
    name: 'Pooya Parsa',
    description: 'pi0',
    to: 'https://github.com/pi0',
    target: '_blank',
    avatar: {
      src: 'https://github.com/pi0.png',
      alt: 'pi0',
      loading: 'lazy' as const
    }
  },
  {
    name: 'Sébastien Chopin',
    description: 'atinux',
    to: 'https://github.com/atinux',
    target: '_blank',
    avatar: {
      src: 'https://github.com/atinux.png',
      alt: 'atinux',
      loading: 'lazy' as const
    }
  },
  {
    name: 'Benjamin Canac',
    description: 'benjamincanac',
    to: 'https://github.com/benjamincanac',
    target: '_blank',
    avatar: {
      src: 'https://github.com/benjamincanac.png',
      alt: 'benjamincanac',
      loading: 'lazy' as const
    }
  }
]
</script>

<template>
  <UEmpty
    title="No team members"
    description="Invite your team to collaborate on this project."
    variant="naked"
    :actions="[{
      label: 'Invite members',
      icon: 'i-lucide-user-plus',
      color: 'neutral'
    }]"
  >
    <template #leading>
      <UAvatarGroup size="xl">
        <UAvatar src="https://github.com/nuxt.png" alt="Nuxt" loading="lazy" />
        <UAvatar src="https://github.com/unjs.png" alt="Unjs" loading="lazy" />
      </UAvatarGroup>
    </template>

    <template #footer>
      <USeparator class="my-4" />

      <div class="grid grid-cols-2 gap-4">
        <UPageCard
          v-for="(member, index) in members"
          :key="index"
          :to="member.to"
          :ui="{ container: 'sm:p-4' }"
        >
          <UUser
            :avatar="member.avatar"
            :name="member.name"
            :description="member.description"
            :ui="{ name: 'truncate' }"
          />
        </UPageCard>
      </div>
    </template>
  </UEmpty>
</template>

API

Props

Prop Default Type
as
'div'
any

The element or component this component should render as.

icon
any

The icon displayed above the title.

avatar
AvatarProps
loading
boolean

When true, the loading icon will be displayed.

loadingIcon
appConfig.ui.icons.loading
any

The icon when the loading prop is true.

title
string
description
string
actions
ButtonProps[]

Display a list of Button in the body.

variant
'outline'
"outline" | "solid" | "soft" | "subtle" | "naked"
size
'md'
"md" | "xs" | "sm" | "lg" | "xl"
ui
{ root?: SlotClass; header?: SlotClass; avatar?: SlotClass; title?: SlotClass; description?: SlotClass; body?: SlotClass; actions?: SlotClass; footer?: SlotClass; }

Slots

Slot Type
header
{}
leading
{ ui: object; }
title
{}
description
{}
body
{}
actions
{}
footer
{}

Thème

app.config.ts
export default defineAppConfig({
  ui: {
    empty: {
      slots: {
        root: 'relative flex flex-col items-center justify-center gap-4 rounded-lg p-4 sm:p-6 lg:p-8 min-w-0',
        header: 'flex flex-col items-center gap-2 max-w-sm text-center',
        avatar: 'shrink-0 mb-2',
        title: 'text-highlighted text-pretty font-medium',
        description: 'text-balance text-center',
        body: 'flex flex-col items-center gap-4 max-w-sm',
        actions: 'flex flex-wrap justify-center gap-2 shrink-0',
        footer: 'flex flex-col items-center gap-2 max-w-sm'
      },
      variants: {
        size: {
          xs: {
            avatar: 'size-8 text-base',
            title: 'text-sm',
            description: 'text-xs'
          },
          sm: {
            avatar: 'size-9 text-lg',
            title: 'text-sm',
            description: 'text-xs'
          },
          md: {
            avatar: 'size-10 text-xl',
            title: 'text-base',
            description: 'text-sm'
          },
          lg: {
            avatar: 'size-11 text-[22px]',
            title: 'text-base',
            description: 'text-sm'
          },
          xl: {
            avatar: 'size-12 text-2xl',
            title: 'text-lg',
            description: 'text-base'
          }
        },
        variant: {
          solid: {
            root: 'bg-inverted',
            title: 'text-inverted',
            description: 'text-dimmed'
          },
          outline: {
            root: 'bg-default ring ring-default',
            description: 'text-muted'
          },
          soft: {
            root: 'bg-elevated/50',
            description: 'text-toned'
          },
          subtle: {
            root: 'bg-elevated/50 ring ring-default',
            description: 'text-toned'
          },
          naked: {
            description: 'text-muted'
          }
        },
        loading: {
          true: {
            avatar: '[&>[data-slot=icon]]:animate-spin'
          }
        }
      },
      defaultVariants: {
        variant: 'outline',
        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: {
        empty: {
          slots: {
            root: 'relative flex flex-col items-center justify-center gap-4 rounded-lg p-4 sm:p-6 lg:p-8 min-w-0',
            header: 'flex flex-col items-center gap-2 max-w-sm text-center',
            avatar: 'shrink-0 mb-2',
            title: 'text-highlighted text-pretty font-medium',
            description: 'text-balance text-center',
            body: 'flex flex-col items-center gap-4 max-w-sm',
            actions: 'flex flex-wrap justify-center gap-2 shrink-0',
            footer: 'flex flex-col items-center gap-2 max-w-sm'
          },
          variants: {
            size: {
              xs: {
                avatar: 'size-8 text-base',
                title: 'text-sm',
                description: 'text-xs'
              },
              sm: {
                avatar: 'size-9 text-lg',
                title: 'text-sm',
                description: 'text-xs'
              },
              md: {
                avatar: 'size-10 text-xl',
                title: 'text-base',
                description: 'text-sm'
              },
              lg: {
                avatar: 'size-11 text-[22px]',
                title: 'text-base',
                description: 'text-sm'
              },
              xl: {
                avatar: 'size-12 text-2xl',
                title: 'text-lg',
                description: 'text-base'
              }
            },
            variant: {
              solid: {
                root: 'bg-inverted',
                title: 'text-inverted',
                description: 'text-dimmed'
              },
              outline: {
                root: 'bg-default ring ring-default',
                description: 'text-muted'
              },
              soft: {
                root: 'bg-elevated/50',
                description: 'text-toned'
              },
              subtle: {
                root: 'bg-elevated/50 ring ring-default',
                description: 'text-toned'
              },
              naked: {
                description: 'text-muted'
              }
            },
            loading: {
              true: {
                avatar: '[&>[data-slot=icon]]:animate-spin'
              }
            }
          },
          defaultVariants: {
            variant: 'outline',
            size: 'md'
          }
        }
      }
    })
  ]
})

Changelog

No recent changes