Use the useToast composable to display a toast in your application.
<script setup lang="ts">
import { useToast } from '#imports'
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>
<PButton
label="Add to calendar"
color="neutral"
variant="outline"
icon="i-lucide:plus"
@click="addToCalendar"
/>
</template>
App component which uses our Toaster component which uses the AToastProvider component from Akar.Pass a title field to the toast.add method to display a title.
<script setup lang="ts">
import { useToast } from '#imports';
const props = defineProps<{
title: string;
}>();
const toast = useToast();
function showToast() {
toast.add(props);
}
</script>
<template>
<PButton
label="Show toast"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Pass a description field to the toast.add method to display a description.
<script setup lang="ts">
import { useToast } from '#imports';
const props = defineProps<{
title: string;
description: string;
}>();
const toast = useToast();
function showToast() {
toast.add(props);
}
</script>
<template>
<PButton
label="Show toast"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Pass an icon field to the toast.add method to display an Icon.
<script setup lang="ts">
import { useToast } from '#imports';
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>
<PButton
label="Show toast"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Pass an avatar field to the toast.add method to display an Avatar.
<script setup lang="ts">
import type { PAvatarProps } from 'pohon-ui';
import { useToast } from '#imports';
const props = defineProps<{
avatar: PAvatarProps;
}>();
const toast = useToast();
function showToast() {
toast.add({
title: 'User invited',
description: 'praburangki was invited to the team.',
avatar: props.avatar,
});
}
</script>
<template>
<PButton
label="Invite user"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Pass a color field to the toast.add method to change the color of the Toast.
<script setup lang="ts">
import type { PToastProps } from 'pohon-ui';
import { useToast } from '#imports';
const props = defineProps<{
color: PToastProps['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>
<PButton
label="Show toast"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Pass a close field to customize or hide the close Button (with false value).
<script setup lang="ts">
import { useToast } from '#imports';
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>
<PButton
label="Show toast"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Pass a closeIcon field to customize the close button Icon. Default to i-lucide:x.
<script setup lang="ts">
import { useToast } from '#imports';
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>
<PButton
label="Show toast"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Pass an actions field to add some Button actions to the Toast.
<script setup lang="ts">
import { useToast } from '#imports';
const props = defineProps<{
description: string;
}>();
const toast = useToast();
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>
<PButton
label="Show toast"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Pass a progress field to customize or hide the Progress bar (with false value).
progress.color field.<script setup lang="ts">
import { useToast } from '#imports';
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',
progress: false,
});
}
</script>
<template>
<PButton
label="Show toast"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Pass an orientation field to the toast.add method to change the orientation of the Toast.
<script setup lang="ts">
import { useToast } from '#imports';
const props = defineProps<{
orientation: 'horizontal' | 'vertical';
}>();
const toast = useToast();
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>
<PButton
label="Show toast"
color="neutral"
variant="outline"
@click="showToast"
/>
</template>
Change the toaster.position prop on the App component to change the position of the toasts.
<script setup lang="ts">
const toaster = { position: 'bottom-right' };
</script>
<template>
<PApp :toaster="toaster">
<NuxtPage />
</PApp>
</template>
AppConfig to configure the position prop of the Toaster component globally.Change the toaster.duration prop on the App component to change the duration of the toasts.
<script setup lang="ts">
const toaster = { duration: 5000 };
</script>
<template>
<PApp :toaster="toaster">
<NuxtPage />
</PApp>
</template>
AppConfig to configure the duration prop of the Toaster component globally.Change the toaster.max prop on the App component to change the max number of toasts displayed at once.
<script setup lang="ts">
const toaster = { max: 3 };
</script>
<template>
<PApp :toaster="toaster">
<NuxtPage />
</PApp>
</template>
Set the toaster.expand prop to false on the App component to display stacked toasts (inspired by Sonner).
<script setup lang="ts">
const toaster = { expand: true };
</script>
<template>
<PApp :toaster="toaster">
<NuxtPage />
</PApp>
</template>
<script setup lang="ts">
import { useToast } from '#imports'
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>
<PButton
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.| Prop | Default | Type |
|---|
| Slot | Type |
|---|
| Event | Type |
|---|
When accessing the component via a template ref, you can use the following:
| Name | Type |
|---|---|
height | Ref<number> |
Below is the theme configuration skeleton for the PToast. Since the component is provided unstyled by default, you will need to fill in these values to apply your own custom look and feel. If you prefer to use our pre-built, opinionated styling, you can instead use our UnoCSS preset, this docs is using it as well.
export default defineAppConfig({
pohon: {
toast: {
slots: {
root: '',
wrapper: '',
title: '',
description: '',
icon: '',
avatar: '',
avatarSize: '',
actions: '',
progress: '',
close: ''
},
variants: {
color: {
primary: {
root: '',
icon: ''
},
secondary: {
root: '',
icon: ''
},
success: {
root: '',
icon: ''
},
info: {
root: '',
icon: ''
},
warning: {
root: '',
icon: ''
},
error: {
root: '',
icon: ''
},
neutral: {
root: '',
icon: ''
}
},
orientation: {
horizontal: {
root: '',
actions: ''
},
vertical: {
root: '',
actions: ''
}
},
title: {
true: {
description: ''
}
}
},
compoundVariants: [],
defaultVariants: {
color: 'primary'
}
}
}
};
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import pohon from 'pohon-ui/vite'
export default defineAppConfig({
pohon: {
toast: {
slots: {
root: '',
wrapper: '',
title: '',
description: '',
icon: '',
avatar: '',
avatarSize: '',
actions: '',
progress: '',
close: ''
},
variants: {
color: {
primary: {
root: '',
icon: ''
},
secondary: {
root: '',
icon: ''
},
success: {
root: '',
icon: ''
},
info: {
root: '',
icon: ''
},
warning: {
root: '',
icon: ''
},
error: {
root: '',
icon: ''
},
neutral: {
root: '',
icon: ''
}
},
orientation: {
horizontal: {
root: '',
actions: ''
},
vertical: {
root: '',
actions: ''
}
},
title: {
true: {
description: ''
}
}
},
compoundVariants: [],
defaultVariants: {
color: 'primary'
}
}
}
};
With Pohon UI, you can achieve similar component functionality with less code and effort, as it comes with built-in styles mechanism and behaviors that are optimized for common use cases. Since it's using unocss-variants it adds a runtime cost, but it can be worth it if you prioritize development speed and ease of use over fine-grained control.
If this is a deal breaker for you, you can always stick to using Akar and build your own custom components on top of it.