Toast

ToastGitLab
Uma mensagem sucinta para fornecer informação ou feedback ao usuário.

Uso

Use o composable useToast para exibir um toast na sua aplicação.

Certifique-se de envolver seu app com o componente App, que usa nosso componente Toaster, que por sua vez usa o componente ToastProvider do Reka UI.
Você pode conferir a prop toaster do componente App para ver como configurar o Toaster globalmente.

Título

Passe um campo title para o método toast.add para exibir um título.

Descrição

Passe um campo description para o método toast.add para exibir uma descrição.

Ícone

Passe um campo icon para o método toast.add para exibir um Icon.

Avatar

Passe um campo avatar para o método toast.add para exibir um Avatar.

Cor

Passe um campo color para o método toast.add para alterar a cor do Toast.

Fechar

Passe um campo close para personalizar ou ocultar o Button de fechar (com o valor false).

Ícone de fechar

Passe um campo closeIcon para personalizar o Icon do botão de fechar. O padrão é i-lucide-x.

Você pode personalizar esse ícone globalmente no seu app.config.ts na chave ui.icons.close.
Você pode personalizar esse ícone globalmente no seu vite.config.ts na chave ui.icons.close.

Ações

Passe um campo actions para adicionar algumas ações de Button ao Toast.

Duração

Passe um campo duration para o método toast.add para alterar por quanto tempo o Toast permanece visível (em milissegundos). O padrão é 5000.

Defina o campo duration como 0 para manter o Toast aberto até ser fechado manualmente.

Progresso

Passe um campo progress para personalizar ou ocultar a barra de Progress (com o valor false).

A barra de Progress herda a cor do Toast por padrão, mas você pode sobrescrevê-la usando o campo progress.color.

Orientação

Passe um campo orientation para o método toast.add para alterar a orientação do Toast.

Exemplos

O Nitro UI fornece um componente App que envolve seu app para fornecer configurações globais.

Alterar a posição global

Altere a prop toaster.position no componente App para alterar a posição dos toasts.

app.vue
<script setup lang="ts">
const toaster = { position: 'bottom-right' }
</script>

<template>
  <NApp :toaster="toaster">
    <NuxtPage />
  </NApp>
</template>

Alterar a duração global

Altere a prop toaster.duration no componente App para alterar a duração dos toasts.

app.vue
<script setup lang="ts">
const toaster = { duration: 5000 }
</script>

<template>
  <NApp :toaster="toaster">
    <NuxtPage />
  </NApp>
</template>

Alterar o máximo global 4.1+

Altere a prop toaster.max no componente App para alterar o número máximo de toasts exibidos ao mesmo tempo.

app.vue
<script setup lang="ts">
const toaster = { max: 3 }
</script>

<template>
  <NApp :toaster="toaster">
    <NuxtPage />
  </NApp>
</template>

Toasts empilhados

Defina a prop toaster.expand como false no componente App para exibir toasts empilhados (inspirado no Sonner).

app.vue
<script setup lang="ts">
const toaster = { expand: true }
</script>

<template>
  <NApp :toaster="toaster">
    <NuxtPage />
  </NApp>
</template>
Você pode passar o mouse sobre os toasts para expandi-los. Isso também pausa o cronômetro dos toasts.

Toasts sem duplicação 4.5+

Ao chamar toast.add com um id que já existe, o toast existente pulsa em vez de criar uma duplicata.

Com callback

Passe um campo onUpdateOpen para executar um callback quando o toast é fechado (seja por expiração ou por dispensa do usuário).

Com conteúdo HTML

Use a função de renderização h() nos campos title ou description para renderizar elementos HTML ou componentes Vue com estilização personalizada.

API

Props

Prop Default Type
as'li'any

The element or component this component should render as.

title string | VNode<RendererNode, RendererElement, { [key: string]: any; }> | (): VNode<RendererNode, RendererElement, { [key: string]: any; }>
description string | VNode<RendererNode, RendererElement, { [key: string]: any; }> | (): VNode<RendererNode, RendererElement, { [key: string]: any; }>
iconany
avatar AvatarProps
color'primary' "error" | "neutral" | "primary" | "secondary" | "accent" | "success" | "info" | "warning"
orientation'vertical' "vertical" | "horizontal"

The orientation between the content and the actions.

closetrueboolean | Omit<ButtonProps, LinkPropsKeys>

Display a close button to dismiss the toast. { size: 'md', color: 'neutral', variant: 'link' }

closeIconappConfig.ui.icons.closeany

The icon displayed in the close button.

actions ButtonProps[]

Display a list of actions:

  • under the title and description when orientation is vertical
  • next to the close button when orientation is horizontal{ size: 'xs' }
progresstrueboolean | Pick<ProgressProps, "color" | "ui">

Display a progress bar showing the toast's remaining duration. { size: 'sm' }

defaultOpenboolean

The open state of the dialog when it is initially rendered. Use when you do not need to control its open state.

openboolean

The controlled open state of the dialog. Can be bind as v-model:open.

type "foreground" | "background"

Control the sensitivity of the toast for accessibility purposes.

For toasts that are the result of a user action, choose foreground. Toasts generated from background tasks should use background.

duration number

Time in milliseconds that toast should remain visible for. Overrides value given to ToastProvider.

ui { root?: SlotClass; wrapper?: SlotClass; title?: SlotClass; description?: SlotClass; icon?: SlotClass; avatar?: SlotClass; avatarSize?: SlotClass; actions?: SlotClass; progress?: SlotClass; close?: SlotClass; }

Slots

Slot Type
leading{ ui: object; }
title{}
description{}
actions{}
close{ ui: object; }

Emits

Event Type
pause[]
escapeKeyDown[event: KeyboardEvent]
resume[]
swipeStart[event: SwipeEvent]
swipeMove[event: SwipeEvent]
swipeCancel[event: SwipeEvent]
swipeEnd[event: SwipeEvent]
update:open[value: boolean]

Expose

Ao acessar o componente por meio de um template ref, você pode usar o seguinte:

NameType
heightRef<number>

Tema

app.config.ts
export default defineAppConfig({
  ui: {
    toast: {
      slots: {
        root: 'relative group overflow-hidden bg-default shadow-lg rounded-lg ring ring-default p-4 flex gap-2.5 focus-visible:outline-2 focus-visible:outline-offset-2',
        wrapper: 'w-0 flex-1 flex flex-col',
        title: 'text-sm font-semibold text-highlighted',
        description: 'text-sm text-default',
        icon: 'shrink-0 size-5',
        avatar: 'shrink-0',
        avatarSize: '2xl',
        actions: 'flex gap-1.5 shrink-0',
        progress: 'absolute inset-x-0 bottom-0',
        close: 'p-0'
      },
      variants: {
        color: {
          primary: {
            root: 'ring-inset ring-primary  focus-visible:outline-primary',
            title: 'text-primary',
            description: 'text-primary',
            icon: 'text-primary'
          },
          secondary: {
            root: 'ring-inset ring-secondary  focus-visible:outline-secondary',
            title: 'text-secondary',
            description: 'text-secondary',
            icon: 'text-secondary'
          },
          accent: {
            root: 'ring-inset ring-accent  focus-visible:outline-accent',
            title: 'text-accent',
            description: 'text-accent',
            icon: 'text-accent'
          },
          success: {
            root: 'ring-inset ring-success  focus-visible:outline-success',
            title: 'text-success',
            description: 'text-success',
            icon: 'text-success'
          },
          info: {
            root: 'ring-inset ring-info  focus-visible:outline-info',
            title: 'text-info',
            description: 'text-info',
            icon: 'text-info'
          },
          warning: {
            root: 'ring-inset ring-warning  focus-visible:outline-warning',
            title: 'text-warning',
            description: 'text-warning',
            icon: 'text-warning'
          },
          error: {
            root: 'ring-inset ring-error  focus-visible:outline-error',
            title: 'text-error',
            description: 'text-error',
            icon: 'text-error'
          },
          neutral: {
            root: 'focus-visible:outline-default',
            icon: 'text-highlighted'
          }
        },
        orientation: {
          horizontal: {
            root: 'items-center',
            actions: 'items-center'
          },
          vertical: {
            root: 'items-start',
            actions: 'items-start mt-2.5'
          }
        },
        title: {
          true: {
            description: 'mt-1'
          }
        }
      },
      defaultVariants: {
        color: 'neutral'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nitro/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      ui: {
        toast: {
          slots: {
            root: 'relative group overflow-hidden bg-default shadow-lg rounded-lg ring ring-default p-4 flex gap-2.5 focus-visible:outline-2 focus-visible:outline-offset-2',
            wrapper: 'w-0 flex-1 flex flex-col',
            title: 'text-sm font-semibold text-highlighted',
            description: 'text-sm text-default',
            icon: 'shrink-0 size-5',
            avatar: 'shrink-0',
            avatarSize: '2xl',
            actions: 'flex gap-1.5 shrink-0',
            progress: 'absolute inset-x-0 bottom-0',
            close: 'p-0'
          },
          variants: {
            color: {
              primary: {
                root: 'ring-inset ring-primary  focus-visible:outline-primary',
                title: 'text-primary',
                description: 'text-primary',
                icon: 'text-primary'
              },
              secondary: {
                root: 'ring-inset ring-secondary  focus-visible:outline-secondary',
                title: 'text-secondary',
                description: 'text-secondary',
                icon: 'text-secondary'
              },
              accent: {
                root: 'ring-inset ring-accent  focus-visible:outline-accent',
                title: 'text-accent',
                description: 'text-accent',
                icon: 'text-accent'
              },
              success: {
                root: 'ring-inset ring-success  focus-visible:outline-success',
                title: 'text-success',
                description: 'text-success',
                icon: 'text-success'
              },
              info: {
                root: 'ring-inset ring-info  focus-visible:outline-info',
                title: 'text-info',
                description: 'text-info',
                icon: 'text-info'
              },
              warning: {
                root: 'ring-inset ring-warning  focus-visible:outline-warning',
                title: 'text-warning',
                description: 'text-warning',
                icon: 'text-warning'
              },
              error: {
                root: 'ring-inset ring-error  focus-visible:outline-error',
                title: 'text-error',
                description: 'text-error',
                icon: 'text-error'
              },
              neutral: {
                root: 'focus-visible:outline-default',
                icon: 'text-highlighted'
              }
            },
            orientation: {
              horizontal: {
                root: 'items-center',
                actions: 'items-center'
              },
              vertical: {
                root: 'items-start',
                actions: 'items-start mt-2.5'
              }
            },
            title: {
              true: {
                description: 'mt-1'
              }
            }
          },
          defaultVariants: {
            color: 'neutral'
          }
        }
      }
    })
  ]
})

Changelog

No recent changes