Toast
Displays temporary feedback for background actions.
See it in context
Preview
Copy a working example
Usage
Astro examples assume UIPrimitives is mounted once in your root layout. Do not add the runtime next to each component instance.
---
import {
Button,
Sonner,
Toast
} from '@santi020k/lumen-astro'
---
<lumen-toast-demo style="display: block;">
<Sonner aria-label="Notifications" placement="bottom-right" maxCount={4} />
<div style="display: grid; gap: 1.25rem;">
<div>
<strong style="display: block; margin-bottom: 0.625rem;">Common feedback</strong>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem;">
<Button data-ex-toast="default" variant="outline">Default</Button>
<Button data-ex-toast="success">Success</Button>
<Button data-ex-toast="warning" variant="secondary">Warning</Button>
<Button data-ex-toast="error" variant="destructive">Error</Button>
</div>
</div>
<div>
<strong style="display: block; margin-bottom: 0.625rem;">Interactive patterns</strong>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem;">
<Button data-ex-toast="action" variant="outline">With action</Button>
<Button data-ex-toast="progress" variant="secondary">Loading → success</Button>
<Button data-ex-toast="dismiss" variant="ghost">Dismiss all</Button>
</div>
</div>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.25rem;">
<Toast style="min-width: min(100%, 18rem);">
<strong>Static toast</strong>
<p>Useful when feedback already exists in the page markup.</p>
</Toast>
<Toast variant="success" style="min-width: min(100%, 18rem);">
<strong>Changes saved</strong>
<p>Static Toast markup remains readable without JavaScript.</p>
</Toast>
</div>
</lumen-toast-demo>
<script>
class LumenToastDemo extends HTMLElement {
connectedCallback() {
if (this.dataset.ready) return
this.dataset.ready = 'true'
const lumenWindow = window as Window & {
LumenToast?: {
create: (detail: Record<string, unknown>) => string
dismiss: (id?: string) => void
update: (id: string, detail: Record<string, unknown>) => void
}
}
const createToast = (detail: Record<string, unknown>) => {
document.dispatchEvent(new CustomEvent('ui:toast', { detail }))
}
this.addEventListener('click', (e) => {
const target = e.target as HTMLElement
const btn = target.closest('[data-ex-toast]')
if (!btn) return
const type = btn.getAttribute('data-ex-toast')
switch (type) {
case 'default': {
createToast({
description: 'Your draft is ready to keep editing.',
title: 'Draft saved'
})
break;
}
case 'success': {
createToast({
description: 'The latest version is now live.',
title: 'Published',
variant: 'success'
})
break;
}
case 'warning': {
createToast({
description: 'We will keep retrying in the background.',
title: 'Connection interrupted',
variant: 'warning'
})
break;
}
case 'error': {
createToast({
description: 'Check the required fields and try again.',
title: 'Could not save changes',
variant: 'destructive'
})
break;
}
case 'action': {
lumenWindow.LumenToast?.create({
action: { label: 'Undo', value: 'deploy' },
description: 'lumen-docs was moved to production.',
duration: 8000,
title: 'Deployment complete',
variant: 'success'
})
break;
}
case 'progress': {
const toastId = lumenWindow.LumenToast?.create({
description: 'Preparing the production bundle.',
duration: 10000,
title: 'Deploying…'
})
if (!toastId) return
window.setTimeout(() => {
lumenWindow.LumenToast?.update(toastId, {
description: 'The production bundle is live.',
duration: 4000,
title: 'Deployment complete',
variant: 'success'
})
}, 1600)
break;
}
case 'dismiss': {
lumenWindow.LumenToast?.dismiss()
break;
}
// No default
}
})
}
}
if (!customElements.get('lumen-toast-demo')) {
customElements.define('lumen-toast-demo', LumenToastDemo)
}
</script>---
import {
Button,
Sonner,
Toast
} from '@santi020k/lumen-astro'
---
<lumen-toast-demo style="display: block;">
<Sonner aria-label="Notifications" placement="bottom-right" maxCount={4} />
<div style="display: grid; gap: 1.25rem;">
<div>
<strong style="display: block; margin-bottom: 0.625rem;">Common feedback</strong>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem;">
<Button data-ex-toast="default" variant="outline">Default</Button>
<Button data-ex-toast="success">Success</Button>
<Button data-ex-toast="warning" variant="secondary">Warning</Button>
<Button data-ex-toast="error" variant="destructive">Error</Button>
</div>
</div>
<div>
<strong style="display: block; margin-bottom: 0.625rem;">Interactive patterns</strong>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem;">
<Button data-ex-toast="action" variant="outline">With action</Button>
<Button data-ex-toast="progress" variant="secondary">Loading → success</Button>
<Button data-ex-toast="dismiss" variant="ghost">Dismiss all</Button>
</div>
</div>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.25rem;">
<Toast style="min-width: min(100%, 18rem);">
<strong>Static toast</strong>
<p>Useful when feedback already exists in the page markup.</p>
</Toast>
<Toast variant="success" style="min-width: min(100%, 18rem);">
<strong>Changes saved</strong>
<p>Static Toast markup remains readable without JavaScript.</p>
</Toast>
</div>
</lumen-toast-demo>
<script>
class LumenToastDemo extends HTMLElement {
connectedCallback() {
if (this.dataset.ready) return
this.dataset.ready = 'true'
const lumenWindow = window as Window & {
LumenToast?: {
create: (detail: Record<string, unknown>) => string
dismiss: (id?: string) => void
update: (id: string, detail: Record<string, unknown>) => void
}
}
const createToast = (detail: Record<string, unknown>) => {
document.dispatchEvent(new CustomEvent('ui:toast', { detail }))
}
this.addEventListener('click', (e) => {
const target = e.target as HTMLElement
const btn = target.closest('[data-ex-toast]')
if (!btn) return
const type = btn.getAttribute('data-ex-toast')
switch (type) {
case 'default': {
createToast({
description: 'Your draft is ready to keep editing.',
title: 'Draft saved'
})
break;
}
case 'success': {
createToast({
description: 'The latest version is now live.',
title: 'Published',
variant: 'success'
})
break;
}
case 'warning': {
createToast({
description: 'We will keep retrying in the background.',
title: 'Connection interrupted',
variant: 'warning'
})
break;
}
case 'error': {
createToast({
description: 'Check the required fields and try again.',
title: 'Could not save changes',
variant: 'destructive'
})
break;
}
case 'action': {
lumenWindow.LumenToast?.create({
action: { label: 'Undo', value: 'deploy' },
description: 'lumen-docs was moved to production.',
duration: 8000,
title: 'Deployment complete',
variant: 'success'
})
break;
}
case 'progress': {
const toastId = lumenWindow.LumenToast?.create({
description: 'Preparing the production bundle.',
duration: 10000,
title: 'Deploying…'
})
if (!toastId) return
window.setTimeout(() => {
lumenWindow.LumenToast?.update(toastId, {
description: 'The production bundle is live.',
duration: 4000,
title: 'Deployment complete',
variant: 'success'
})
}, 1600)
break;
}
case 'dismiss': {
lumenWindow.LumenToast?.dismiss()
break;
}
// No default
}
})
}
}
if (!customElements.get('lumen-toast-demo')) {
customElements.define('lumen-toast-demo', LumenToastDemo)
}
</script>import { Button, Sonner, Toast } from '@santi020k/lumen-react'
export const Example = () => (
<>
<lumen-toast-demo style={{ display: 'block' }}>
<Sonner aria-label="Notifications" placement="bottom-right" maxCount={4} />
<div style={{ display: 'grid', gap: '1.25rem' }}>
<div>
<strong style={{ display: 'block', marginBottom: '0.625rem' }}>Common feedback</strong>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem' }}>
<Button data-ex-toast="default" variant="outline">Default</Button>
<Button data-ex-toast="success">Success</Button>
<Button data-ex-toast="warning" variant="secondary">Warning</Button>
<Button data-ex-toast="error" variant="destructive">Error</Button>
</div>
</div>
<div>
<strong style={{ display: 'block', marginBottom: '0.625rem' }}>Interactive patterns</strong>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem' }}>
<Button data-ex-toast="action" variant="outline">With action</Button>
<Button data-ex-toast="progress" variant="secondary">Loading → success</Button>
<Button data-ex-toast="dismiss" variant="ghost">Dismiss all</Button>
</div>
</div>
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem', marginTop: '1.25rem' }}>
<Toast style={{ minWidth: 'min(100%, 18rem)' }}>
<strong>Static toast</strong>
<p>Useful when feedback already exists in the page markup.</p>
</Toast>
<Toast variant="success" style={{ minWidth: 'min(100%, 18rem)' }}>
<strong>Changes saved</strong>
<p>Static Toast markup remains readable without JavaScript.</p>
</Toast>
</div>
</lumen-toast-demo>
<script>
class LumenToastDemo extends HTMLElement {
connectedCallback() {
if (this.dataset.ready) return
this.dataset.ready = 'true'
const lumenWindow = window as Window & {
LumenToast?: {
create: (detail: Record<string, unknown>) => string
dismiss: (id?: string) => void
update: (id: string, detail: Record<string, unknown>) => void
}
}
const createToast = (detail: Record<string, unknown>) => {
document.dispatchEvent(new CustomEvent('ui:toast', { detail }))
}
this.addEventListener('click', (e) => {
const target = e.target as HTMLElement
const btn = target.closest('[data-ex-toast]')
if (!btn) return
const type = btn.getAttribute('data-ex-toast')
switch (type) {
case 'default': {
createToast({
description: 'Your draft is ready to keep editing.',
title: 'Draft saved'
})
break;
}
case 'success': {
createToast({
description: 'The latest version is now live.',
title: 'Published',
variant: 'success'
})
break;
}
case 'warning': {
createToast({
description: 'We will keep retrying in the background.',
title: 'Connection interrupted',
variant: 'warning'
})
break;
}
case 'error': {
createToast({
description: 'Check the required fields and try again.',
title: 'Could not save changes',
variant: 'destructive'
})
break;
}
case 'action': {
lumenWindow.LumenToast?.create({
action: { label: 'Undo', value: 'deploy' },
description: 'lumen-docs was moved to production.',
duration: 8000,
title: 'Deployment complete',
variant: 'success'
})
break;
}
case 'progress': {
const toastId = lumenWindow.LumenToast?.create({
description: 'Preparing the production bundle.',
duration: 10000,
title: 'Deploying…'
})
if (!toastId) return
window.setTimeout(() => {
lumenWindow.LumenToast?.update(toastId, {
description: 'The production bundle is live.',
duration: 4000,
title: 'Deployment complete',
variant: 'success'
})
}, 1600)
break;
}
case 'dismiss': {
lumenWindow.LumenToast?.dismiss()
break;
}
// No default
}
})
}
}
if (!customElements.get('lumen-toast-demo')) {
customElements.define('lumen-toast-demo', LumenToastDemo)
}
</script>
</>
)import { Button, Sonner, Toast } from '@santi020k/lumen-react'
export const Example = () => (
<>
<lumen-toast-demo style={{ display: 'block' }}>
<Sonner aria-label="Notifications" placement="bottom-right" maxCount={4} />
<div style={{ display: 'grid', gap: '1.25rem' }}>
<div>
<strong style={{ display: 'block', marginBottom: '0.625rem' }}>Common feedback</strong>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem' }}>
<Button data-ex-toast="default" variant="outline">Default</Button>
<Button data-ex-toast="success">Success</Button>
<Button data-ex-toast="warning" variant="secondary">Warning</Button>
<Button data-ex-toast="error" variant="destructive">Error</Button>
</div>
</div>
<div>
<strong style={{ display: 'block', marginBottom: '0.625rem' }}>Interactive patterns</strong>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem' }}>
<Button data-ex-toast="action" variant="outline">With action</Button>
<Button data-ex-toast="progress" variant="secondary">Loading → success</Button>
<Button data-ex-toast="dismiss" variant="ghost">Dismiss all</Button>
</div>
</div>
</div>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: '0.75rem', marginTop: '1.25rem' }}>
<Toast style={{ minWidth: 'min(100%, 18rem)' }}>
<strong>Static toast</strong>
<p>Useful when feedback already exists in the page markup.</p>
</Toast>
<Toast variant="success" style={{ minWidth: 'min(100%, 18rem)' }}>
<strong>Changes saved</strong>
<p>Static Toast markup remains readable without JavaScript.</p>
</Toast>
</div>
</lumen-toast-demo>
<script>
class LumenToastDemo extends HTMLElement {
connectedCallback() {
if (this.dataset.ready) return
this.dataset.ready = 'true'
const lumenWindow = window as Window & {
LumenToast?: {
create: (detail: Record<string, unknown>) => string
dismiss: (id?: string) => void
update: (id: string, detail: Record<string, unknown>) => void
}
}
const createToast = (detail: Record<string, unknown>) => {
document.dispatchEvent(new CustomEvent('ui:toast', { detail }))
}
this.addEventListener('click', (e) => {
const target = e.target as HTMLElement
const btn = target.closest('[data-ex-toast]')
if (!btn) return
const type = btn.getAttribute('data-ex-toast')
switch (type) {
case 'default': {
createToast({
description: 'Your draft is ready to keep editing.',
title: 'Draft saved'
})
break;
}
case 'success': {
createToast({
description: 'The latest version is now live.',
title: 'Published',
variant: 'success'
})
break;
}
case 'warning': {
createToast({
description: 'We will keep retrying in the background.',
title: 'Connection interrupted',
variant: 'warning'
})
break;
}
case 'error': {
createToast({
description: 'Check the required fields and try again.',
title: 'Could not save changes',
variant: 'destructive'
})
break;
}
case 'action': {
lumenWindow.LumenToast?.create({
action: { label: 'Undo', value: 'deploy' },
description: 'lumen-docs was moved to production.',
duration: 8000,
title: 'Deployment complete',
variant: 'success'
})
break;
}
case 'progress': {
const toastId = lumenWindow.LumenToast?.create({
description: 'Preparing the production bundle.',
duration: 10000,
title: 'Deploying…'
})
if (!toastId) return
window.setTimeout(() => {
lumenWindow.LumenToast?.update(toastId, {
description: 'The production bundle is live.',
duration: 4000,
title: 'Deployment complete',
variant: 'success'
})
}, 1600)
break;
}
case 'dismiss': {
lumenWindow.LumenToast?.dismiss()
break;
}
// No default
}
})
}
}
if (!customElements.get('lumen-toast-demo')) {
customElements.define('lumen-toast-demo', LumenToastDemo)
}
</script>
</>
)<script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<lumen-toast-demo style="display: block;">
<lumen-sonner aria-label="Notifications" placement="bottom-right" maxCount="4"></lumen-sonner>
<div style="display: grid; gap: 1.25rem;">
<div>
<strong style="display: block; margin-bottom: 0.625rem;">Common feedback</strong>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem;">
<lumen-button data-ex-toast="default" variant="outline">Default</lumen-button>
<lumen-button data-ex-toast="success">Success</lumen-button>
<lumen-button data-ex-toast="warning" variant="secondary">Warning</lumen-button>
<lumen-button data-ex-toast="error" variant="destructive">Error</lumen-button>
</div>
</div>
<div>
<strong style="display: block; margin-bottom: 0.625rem;">Interactive patterns</strong>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem;">
<lumen-button data-ex-toast="action" variant="outline">With action</lumen-button>
<lumen-button data-ex-toast="progress" variant="secondary">Loading → success</lumen-button>
<lumen-button data-ex-toast="dismiss" variant="ghost">Dismiss all</lumen-button>
</div>
</div>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.25rem;">
<lumen-toast style="min-width: min(100%, 18rem);">
<strong>Static toast</strong>
<p>Useful when feedback already exists in the page markup.</p>
</lumen-toast>
<lumen-toast variant="success" style="min-width: min(100%, 18rem);">
<strong>Changes saved</strong>
<p>Static Toast markup remains readable without JavaScript.</p>
</lumen-toast>
</div>
</lumen-toast-demo>
<script>
class LumenToastDemo extends HTMLElement {
connectedCallback() {
if (this.dataset.ready) return
this.dataset.ready = 'true'
const lumenWindow = window as Window & {
LumenToast?: {
create: (detail: Record<string, unknown>) => string
dismiss: (id?: string) => void
update: (id: string, detail: Record<string, unknown>) => void
}
}
const createToast = (detail: Record<string, unknown>) => {
document.dispatchEvent(new CustomEvent('ui:toast', { detail }))
}
this.addEventListener('click', (e) => {
const target = e.target as HTMLElement
const btn = target.closest('[data-ex-toast]')
if (!btn) return
const type = btn.getAttribute('data-ex-toast')
switch (type) {
case 'default': {
createToast({
description: 'Your draft is ready to keep editing.',
title: 'Draft saved'
})
break;
}
case 'success': {
createToast({
description: 'The latest version is now live.',
title: 'Published',
variant: 'success'
})
break;
}
case 'warning': {
createToast({
description: 'We will keep retrying in the background.',
title: 'Connection interrupted',
variant: 'warning'
})
break;
}
case 'error': {
createToast({
description: 'Check the required fields and try again.',
title: 'Could not save changes',
variant: 'destructive'
})
break;
}
case 'action': {
lumenWindow.LumenToast?.create({
action: { label: 'Undo', value: 'deploy' },
description: 'lumen-docs was moved to production.',
duration: 8000,
title: 'Deployment complete',
variant: 'success'
})
break;
}
case 'progress': {
const toastId = lumenWindow.LumenToast?.create({
description: 'Preparing the production bundle.',
duration: 10000,
title: 'Deploying…'
})
if (!toastId) return
window.setTimeout(() => {
lumenWindow.LumenToast?.update(toastId, {
description: 'The production bundle is live.',
duration: 4000,
title: 'Deployment complete',
variant: 'success'
})
}, 1600)
break;
}
case 'dismiss': {
lumenWindow.LumenToast?.dismiss()
break;
}
// No default
}
})
}
}
if (!customElements.get('lumen-toast-demo')) {
customElements.define('lumen-toast-demo', LumenToastDemo)
}
</script><script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<lumen-toast-demo style="display: block;">
<lumen-sonner aria-label="Notifications" placement="bottom-right" maxCount="4"></lumen-sonner>
<div style="display: grid; gap: 1.25rem;">
<div>
<strong style="display: block; margin-bottom: 0.625rem;">Common feedback</strong>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem;">
<lumen-button data-ex-toast="default" variant="outline">Default</lumen-button>
<lumen-button data-ex-toast="success">Success</lumen-button>
<lumen-button data-ex-toast="warning" variant="secondary">Warning</lumen-button>
<lumen-button data-ex-toast="error" variant="destructive">Error</lumen-button>
</div>
</div>
<div>
<strong style="display: block; margin-bottom: 0.625rem;">Interactive patterns</strong>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem;">
<lumen-button data-ex-toast="action" variant="outline">With action</lumen-button>
<lumen-button data-ex-toast="progress" variant="secondary">Loading → success</lumen-button>
<lumen-button data-ex-toast="dismiss" variant="ghost">Dismiss all</lumen-button>
</div>
</div>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.25rem;">
<lumen-toast style="min-width: min(100%, 18rem);">
<strong>Static toast</strong>
<p>Useful when feedback already exists in the page markup.</p>
</lumen-toast>
<lumen-toast variant="success" style="min-width: min(100%, 18rem);">
<strong>Changes saved</strong>
<p>Static Toast markup remains readable without JavaScript.</p>
</lumen-toast>
</div>
</lumen-toast-demo>
<script>
class LumenToastDemo extends HTMLElement {
connectedCallback() {
if (this.dataset.ready) return
this.dataset.ready = 'true'
const lumenWindow = window as Window & {
LumenToast?: {
create: (detail: Record<string, unknown>) => string
dismiss: (id?: string) => void
update: (id: string, detail: Record<string, unknown>) => void
}
}
const createToast = (detail: Record<string, unknown>) => {
document.dispatchEvent(new CustomEvent('ui:toast', { detail }))
}
this.addEventListener('click', (e) => {
const target = e.target as HTMLElement
const btn = target.closest('[data-ex-toast]')
if (!btn) return
const type = btn.getAttribute('data-ex-toast')
switch (type) {
case 'default': {
createToast({
description: 'Your draft is ready to keep editing.',
title: 'Draft saved'
})
break;
}
case 'success': {
createToast({
description: 'The latest version is now live.',
title: 'Published',
variant: 'success'
})
break;
}
case 'warning': {
createToast({
description: 'We will keep retrying in the background.',
title: 'Connection interrupted',
variant: 'warning'
})
break;
}
case 'error': {
createToast({
description: 'Check the required fields and try again.',
title: 'Could not save changes',
variant: 'destructive'
})
break;
}
case 'action': {
lumenWindow.LumenToast?.create({
action: { label: 'Undo', value: 'deploy' },
description: 'lumen-docs was moved to production.',
duration: 8000,
title: 'Deployment complete',
variant: 'success'
})
break;
}
case 'progress': {
const toastId = lumenWindow.LumenToast?.create({
description: 'Preparing the production bundle.',
duration: 10000,
title: 'Deploying…'
})
if (!toastId) return
window.setTimeout(() => {
lumenWindow.LumenToast?.update(toastId, {
description: 'The production bundle is live.',
duration: 4000,
title: 'Deployment complete',
variant: 'success'
})
}, 1600)
break;
}
case 'dismiss': {
lumenWindow.LumenToast?.dismiss()
break;
}
// No default
}
})
}
}
if (!customElements.get('lumen-toast-demo')) {
customElements.define('lumen-toast-demo', LumenToastDemo)
}
</script>Choose your target
Add this component
Choose the package for your runtime. All adapters share the Lumen stylesheet. Use the matching registry command when you want a local wrapper for that framework.
pnpm add @santi020k/lumen-astropnpm add @santi020k/lumen-astrolumen add Toastlumen add Toastpnpm add @santi020k/lumen-reactpnpm add @santi020k/lumen-reactlumen add Toast --target reactlumen add Toast --target reactpnpm add @santi020k/lumen-elementspnpm add @santi020k/lumen-elementslumen add Toast --target elementslumen add Toast --target elementsGlass
Add the glass prop to apply the shared blur, saturation, border, and highlight tokens. Glass reads best over vivid content, so place the surface above imagery or color.
---
import { Toast } from '@santi020k/lumen-astro'
---
<div class="docs-glass-demo docs-glass-demo--stack" style="justify-items: center;">
<Toast glass style="min-width: min(100%, 20rem);">
<strong>Build complete</strong>
<p>The glass toast floats over content with a slightly stronger fill for readability.</p>
</Toast>
<Toast variant="success" glass style="min-width: min(100%, 20rem);">
<strong>Published</strong>
<p>Status tints layer on top of the frosted surface.</p>
</Toast>
</div>---
import { Toast } from '@santi020k/lumen-astro'
---
<div class="docs-glass-demo docs-glass-demo--stack" style="justify-items: center;">
<Toast glass style="min-width: min(100%, 20rem);">
<strong>Build complete</strong>
<p>The glass toast floats over content with a slightly stronger fill for readability.</p>
</Toast>
<Toast variant="success" glass style="min-width: min(100%, 20rem);">
<strong>Published</strong>
<p>Status tints layer on top of the frosted surface.</p>
</Toast>
</div>import { Toast } from '@santi020k/lumen-react'
export const Example = () => (
<>
<div className="docs-glass-demo docs-glass-demo--stack" style={{ justifyItems: 'center' }}>
<Toast glass style={{ minWidth: 'min(100%, 20rem)' }}>
<strong>Build complete</strong>
<p>The glass toast floats over content with a slightly stronger fill for readability.</p>
</Toast>
<Toast variant="success" glass style={{ minWidth: 'min(100%, 20rem)' }}>
<strong>Published</strong>
<p>Status tints layer on top of the frosted surface.</p>
</Toast>
</div>
</>
)import { Toast } from '@santi020k/lumen-react'
export const Example = () => (
<>
<div className="docs-glass-demo docs-glass-demo--stack" style={{ justifyItems: 'center' }}>
<Toast glass style={{ minWidth: 'min(100%, 20rem)' }}>
<strong>Build complete</strong>
<p>The glass toast floats over content with a slightly stronger fill for readability.</p>
</Toast>
<Toast variant="success" glass style={{ minWidth: 'min(100%, 20rem)' }}>
<strong>Published</strong>
<p>Status tints layer on top of the frosted surface.</p>
</Toast>
</div>
</>
)<script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<div class="docs-glass-demo docs-glass-demo--stack" style="justify-items: center;">
<lumen-toast glass style="min-width: min(100%, 20rem);">
<strong>Build complete</strong>
<p>The glass toast floats over content with a slightly stronger fill for readability.</p>
</lumen-toast>
<lumen-toast variant="success" glass style="min-width: min(100%, 20rem);">
<strong>Published</strong>
<p>Status tints layer on top of the frosted surface.</p>
</lumen-toast>
</div><script type="module">
import { defineLumenElements } from '@santi020k/lumen-elements/define'
defineLumenElements()
</script>
<div class="docs-glass-demo docs-glass-demo--stack" style="justify-items: center;">
<lumen-toast glass style="min-width: min(100%, 20rem);">
<strong>Build complete</strong>
<p>The glass toast floats over content with a slightly stronger fill for readability.</p>
</lumen-toast>
<lumen-toast variant="success" glass style="min-width: min(100%, 20rem);">
<strong>Published</strong>
<p>Status tints layer on top of the frosted surface.</p>
</lumen-toast>
</div>API reference
Lumen-specific props and runtime attributes for the Astro primitive. React props follow the same names; Elements use equivalent kebab-case attributes where custom elements expose them.
| Attribute | Values | Default | Description |
|---|---|---|---|
| glass | boolean | "subtle" | "strong" | false | Applies the tokenized liquid-glass surface treatment with backdrop-filter fallbacks; "subtle" and "strong" adjust the fill intensity. |
| variant | "default" | "destructive" | "success" | "warning" | "default" | Controls the toast tone. |
| Sonner placement | "top-left" | "top-center" | "top-right" | "bottom-left" | "bottom-center" | "bottom-right" | "bottom-right" | Positions the toast viewport mounted for programmatic notifications. |
| Sonner maxCount | number | 5 | Limits the number of runtime toasts kept in the viewport. |
| window.LumenToast.create(detail) | function | - | Creates a runtime toast and returns its id. Also available through document ui:toast. |
| window.LumenToast.update(id, detail) | function | - | Updates the title, description, variant, action, or duration for a runtime toast. |
| window.LumenToast.dismiss(id?) | function | - | Dismisses one runtime toast, or all runtime toasts when id is omitted. |
| surface | "default" | "glass" | "default" | Deprecated alias for glass; surface="glass" maps to glass={true}. |
| class, className | string | "" | Merges custom classes with the generated ui-* root classes. |
| ...native attributes | HTML attributes | - | Forwards standard attributes to the root element unless the component consumes them. |
Keyboard interactions
Keyboard behavior provided by the Astro UIPrimitives runtime for this component.
| Key | Action |
|---|---|
| Escape in a toast | Dismiss the focused toast. |
Runtime events
CustomEvents dispatched by the Astro UIPrimitives runtime for this component.
| Event | Target | Detail | When |
|---|---|---|---|
| ui:toast | Document | { id?: string, title?: string, description?: string, variant?: string, duration?: number, placement?: string, action?: { label: string } } | Creates a programmatic toast in the matching Sonner viewport. |
| ui:toast-update | Document | { id: string, title?: string, description?: string, variant?: string, duration?: number } | Updates a programmatic toast created by ui:toast or window.LumenToast.create(detail). |
| ui:toast-dismiss | Document | { id?: string } | Dismisses one programmatic toast by id, or all runtime toasts when id is omitted. |
| ui:toast-action | Toast ([data-ui-toast]) | { id: string, value?: unknown } | Fires after a programmatic toast action button is pressed unless the action specifies a custom event name. |