Usage
Use the useToast composable to display a toast in your application.
App
component which uses our Toaster
component which uses the ToastProvider
component from Reka UI.Title
Pass a title
field to the toast.add
method to display a title.
<script setup lang="ts">
const props = defineProps<{
title: string
}>()
const toast = useToast()
function showToast() {
toast.add(props)
}
</script>
<template>
<UButton label="Show toast" color="neutral" variant="outline" @click="showToast" />
</template>
Description
Pass a description
field to the toast.add
method to display a description.
<script setup lang="ts">
const props = defineProps<{
title: string
description: string
}>()
const toast = useToast()
function showToast() {
toast.add(props)
}
</script>
<template>
<UButton label="Show toast" color="neutral" variant="outline" @click="showToast" />
</template>
Icon
Pass an icon
field to the toast.add
method to display an Icon.
<script setup lang="ts">
const props = defineProps<{
icon: string
}>()
const toast = useToast()
function showToast() {
toast.add({
title: 'Uh oh! Something went wrong.',
description: 'There was a problem with your request.',
icon: props.icon
})
}
</script>
<template>
<UButton label="Show toast" color="neutral" variant="outline" @click="showToast" />
</template>
Avatar
Pass an avatar
field to the toast.add
method to display an Avatar.
<script setup lang="ts">
import type { AvatarProps } from '@nuxt/ui'
const props = defineProps<{
avatar: AvatarProps
}>()
const toast = useToast()
function showToast() {
toast.add({
title: 'User invited',
description: 'benjamincanac was invited to the team.',
avatar: props.avatar
})
}
</script>
<template>
<UButton label="Invite user" color="neutral" variant="outline" @click="showToast" />
</template>
Color
Pass a color
field to the toast.add
method to change the color of the Toast.
<script setup lang="ts">
import type { ToastProps } from '@nuxt/ui'
const props = defineProps<{
color: ToastProps['color']
}>()
const toast = useToast()
function showToast() {
toast.add({
title: 'Uh oh! Something went wrong.',
description: 'There was a problem with your request.',
icon: 'i-lucide-wifi',
color: props.color
})
}
</script>
<template>
<UButton label="Show toast" color="neutral" variant="outline" @click="showToast" />
</template>
Close
Pass a close
field to customize or hide the close button (with false
value).
<script setup lang="ts">
const toast = useToast()
function showToast() {
toast.add({
title: 'Uh oh! Something went wrong.',
description: 'There was a problem with your request.',
icon: 'i-lucide-wifi',
close: {
color: 'primary',
variant: 'outline',
class: 'rounded-full'
}
})
}
</script>
<template>
<UButton label="Show toast" color="neutral" variant="outline" @click="showToast" />
</template>
Close Icon
Pass a closeIcon
field to customize the close button Icon. Default to i-lucide-x
.
<script setup lang="ts">
const props = defineProps<{
closeIcon: string
}>()
const toast = useToast()
function showToast() {
toast.add({
title: 'Uh oh! Something went wrong.',
description: 'There was a problem with your request.',
closeIcon: props.closeIcon
})
}
</script>
<template>
<UButton label="Show toast" color="neutral" variant="outline" @click="showToast" />
</template>
Actions
Pass an actions
field to add some Button actions to the Alert.
<script setup lang="ts">
const toast = useToast()
const props = defineProps<{
description: string
}>()
function showToast() {
toast.add({
title: 'Uh oh! Something went wrong.',
description: props.description,
actions: [{
icon: 'i-lucide-refresh-cw',
label: 'Retry',
color: 'neutral',
variant: 'outline',
onClick: (e) => {
e?.stopPropagation()
}
}]
})
}
</script>
<template>
<UButton label="Show toast" color="neutral" variant="outline" @click="showToast" />
</template>
Orientation
Use the orientation
prop to change the orientation of the Toast.
<script setup lang="ts">
const toast = useToast()
const props = defineProps<{
orientation: 'horizontal' | 'vertical'
}>()
function showToast() {
toast.add({
title: 'Uh oh! Something went wrong.',
orientation: props.orientation,
actions: [{
icon: 'i-lucide-refresh-cw',
label: 'Retry',
color: 'neutral',
variant: 'outline',
onClick: (e) => {
e?.stopPropagation()
}
}]
})
}
</script>
<template>
<UButton label="Show toast" color="neutral" variant="outline" @click="showToast" />
</template>
Examples
Change global position
Change the toaster.position
prop on the App component to change the position of the toasts.
<script setup lang="ts">
const toast = useToast()
function addToCalendar() {
const eventDate = new Date(Date.now() + Math.random() * 31536000000)
const formattedDate = eventDate.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
})
toast.add({
title: 'Event added to calendar',
description: `This event is scheduled for ${formattedDate}.`,
icon: 'i-lucide-calendar-days'
})
}
</script>
<template>
<UButton
label="Add to calendar"
color="neutral"
variant="outline"
icon="i-lucide-plus"
@click="addToCalendar"
/>
</template>
AppConfig
to configure the position
prop of the Toaster
component globally.Change global duration
Change the toaster.duration
prop on the App component to change the duration of the toasts.
<script setup lang="ts">
const toast = useToast()
function addToCalendar() {
const eventDate = new Date(Date.now() + Math.random() * 31536000000)
const formattedDate = eventDate.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
})
toast.add({
title: 'Event added to calendar',
description: `This event is scheduled for ${formattedDate}.`,
icon: 'i-lucide-calendar-days'
})
}
</script>
<template>
<UButton
label="Add to calendar"
color="neutral"
variant="outline"
icon="i-lucide-plus"
@click="addToCalendar"
/>
</template>
AppConfig
to configure the duration
prop of the Toaster
component globally.Stacked toasts
Set the toaster.expand
prop to false
on the App component to display stacked toasts.
<script setup lang="ts">
const toast = useToast()
function addToCalendar() {
const eventDate = new Date(Date.now() + Math.random() * 31536000000)
const formattedDate = eventDate.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric'
})
toast.add({
title: 'Event added to calendar',
description: `This event is scheduled for ${formattedDate}.`,
icon: 'i-lucide-calendar-days'
})
}
</script>
<template>
<UButton
label="Add to calendar"
color="neutral"
variant="outline"
icon="i-lucide-plus"
@click="addToCalendar"
/>
</template>
AppConfig
to configure the expand
prop of the Toaster
component globally.API
Props
Prop | Default | Type |
---|---|---|
as |
|
The element or component this component should render as. |
title |
| |
description |
| |
icon |
| |
avatar |
| |
color |
|
|
orientation |
|
|
actions |
Display a list of actions:
| |
close |
|
Display a close button to dismiss the toast.
|
closeIcon |
|
The icon displayed in the close button. |
type |
Control the sensitivity of the toast for accessibility purposes. For toasts that are the result of a user action, choose | |
duration |
Time in milliseconds that toast should remain visible for. Overrides value
given to | |
defaultOpen |
The open state of the dialog when it is initially rendered. Use when you do not need to control its open state. | |
open |
The controlled open state of the dialog. Can be bind as | |
ui |
|
Slots
Slot | Type |
---|---|
leading |
|
title |
|
description |
|
actions |
|
close |
|
Emits
Event | Type |
---|---|
pause |
|
update:open |
|
escapeKeyDown |
|
resume |
|
swipeStart |
|
swipeMove |
|
swipeCancel |
|
swipeEnd |
|
Theme
export default defineAppConfig({
ui: {
toast: {
slots: {
root: 'relative group overflow-hidden bg-(--ui-bg) shadow-lg rounded-[calc(var(--ui-radius)*2)] ring ring-(--ui-border) p-4 flex gap-2.5 focus:outline-none',
wrapper: 'w-0 flex-1 flex flex-col',
title: 'text-sm font-medium text-(--ui-text-highlighted)',
description: 'text-sm text-(--ui-text-muted)',
icon: 'shrink-0 size-5',
avatar: 'shrink-0',
avatarSize: '2xl',
actions: 'flex gap-1.5 shrink-0',
progress: 'absolute inset-x-0 bottom-0 h-1 z-[-1]',
close: 'p-0'
},
variants: {
color: {
primary: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-primary)',
icon: 'text-(--ui-primary)',
progress: 'bg-(--ui-primary)'
},
secondary: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-secondary)',
icon: 'text-(--ui-secondary)',
progress: 'bg-(--ui-secondary)'
},
success: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-success)',
icon: 'text-(--ui-success)',
progress: 'bg-(--ui-success)'
},
info: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-info)',
icon: 'text-(--ui-info)',
progress: 'bg-(--ui-info)'
},
warning: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-warning)',
icon: 'text-(--ui-warning)',
progress: 'bg-(--ui-warning)'
},
error: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-error)',
icon: 'text-(--ui-error)',
progress: 'bg-(--ui-error)'
},
neutral: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-border-inverted)',
icon: 'text-(--ui-text-highlighted)',
progress: 'bg-(--ui-bg-inverted)'
}
},
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: 'primary'
}
}
}
})
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'
export default defineConfig({
plugins: [
vue(),
ui({
ui: {
toast: {
slots: {
root: 'relative group overflow-hidden bg-(--ui-bg) shadow-lg rounded-[calc(var(--ui-radius)*2)] ring ring-(--ui-border) p-4 flex gap-2.5 focus:outline-none',
wrapper: 'w-0 flex-1 flex flex-col',
title: 'text-sm font-medium text-(--ui-text-highlighted)',
description: 'text-sm text-(--ui-text-muted)',
icon: 'shrink-0 size-5',
avatar: 'shrink-0',
avatarSize: '2xl',
actions: 'flex gap-1.5 shrink-0',
progress: 'absolute inset-x-0 bottom-0 h-1 z-[-1]',
close: 'p-0'
},
variants: {
color: {
primary: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-primary)',
icon: 'text-(--ui-primary)',
progress: 'bg-(--ui-primary)'
},
secondary: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-secondary)',
icon: 'text-(--ui-secondary)',
progress: 'bg-(--ui-secondary)'
},
success: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-success)',
icon: 'text-(--ui-success)',
progress: 'bg-(--ui-success)'
},
info: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-info)',
icon: 'text-(--ui-info)',
progress: 'bg-(--ui-info)'
},
warning: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-warning)',
icon: 'text-(--ui-warning)',
progress: 'bg-(--ui-warning)'
},
error: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-error)',
icon: 'text-(--ui-error)',
progress: 'bg-(--ui-error)'
},
neutral: {
root: 'focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-(--ui-border-inverted)',
icon: 'text-(--ui-text-highlighted)',
progress: 'bg-(--ui-bg-inverted)'
}
},
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: 'primary'
}
}
}
})
]
})