vyrn

A tiny, accessible toast engine for React and Next.js. Zero dependencies.

GitHub

Installation

Latest version: 5.0.0

Usage

Render the toaster in the root of your app.

import { Toaster, toast } from 'vyrn'

function App() {
  return (
    
) }

Types

Customize the type of toast and pass an options object as the second argument.

toast('Event has been created')

Position

Swipe directions are derived from the position automatically.

Layout

Stack layers toasts on top of each other. Normal stacks them vertically.

Rich colors

Semantic surfaces for success, error, info, and warning toasts.

Other

Close button and countdown bar.

Advanced

Inline inputs, grouping, determinate progress, and more.

toast.info('Enter your name', {
  duration: 0,
  input: {
    placeholder: 'Your name',
    onSubmit: (value) => toast.success(value),
  },
})

API Reference

Provider props, toast methods, and options.

Toaster props

Multiple Toasters are safe: only the first one still mounted paints the toasts, so a stray Toaster can never double-render. When it unmounts, the next takes over.

NameTypeDefaultDescription
position
'top-left''top-center''top-right''bottom-left''bottom-center''bottom-right'
'bottom-right'Viewport corner where toasts mount. A toast can override this individually.
layout
'stack''normal'
'normal'stack collapses toasts into a deck that expands on hover; normal lists them vertically.
visibleToasts
number
5Maximum on screen at once. Extras are queued and shown as space frees up — never discarded.
duration
number
4000Default auto-dismiss time in ms. Errors default to 5000, loading toasts never auto-dismiss.
theme
'light''dark''system'
'system'With 'system', your app outranks the OS: a .dark/.light class, a data-theme attribute, or an inline color-scheme is used first, and prefers-color-scheme only if you declare nothing. Theme changes are picked up live.
dir
'ltr''rtl''auto'
'auto'Text direction. auto reads document.dir.
richColors
falsetrue'minimal''soft''solid'
falseSemantic surfaces. true maps to 'minimal'; 'soft' adds a border, 'solid' is high contrast.
expand
boolean
falseKeep a stack layout permanently expanded instead of collapsing it.
closeButton
boolean
trueRender the close button. Alias: showCloseButton.
showProgressBar
boolean
trueShow the countdown bar. Driven by one CSS animation, so it costs nothing per frame.
color
boolean
trueApply a subtle semantic tint per type. Turn off for uniform neutral surfaces.
size
'sm''md''lg'
'md'Global density — padding, radius and font size.
invert
boolean
falseFlip every toast against the page theme.
gap
number
14Gap between toasts in px.
offset
stringnumber{ top, right, bottom, left }
'24px'Distance from the viewport edge. Numbers are px; an object sets each side independently.
mobileOffset
stringnumber{ top, right, bottom, left }
'16px'Edge distance below 600px wide. Accepts the same object form.
swipeDirections
SwipeDirection[]
derived from positionDirections a toast can be swiped away in. Legacy swipeDirection sets a single one.
swipeThreshold
number
0.35Fraction of the toast's width or height a swipe must cover to dismiss.
toastOptions
ToastOptions & { types? }
Defaults merged into every toast, including classNames. Its types key narrows them per variant, e.g. { types: { error: { duration: 8000 } } }.
hotkey
string[]
['altKey', 'KeyT']Key combo that moves focus into the toast list.
pauseWhenPageIsHidden
boolean
falsePause countdowns while the tab is hidden. Off by default: timers are setTimeout-based, so toasts dismiss on schedule either way.
pauseOnFocusLoss
boolean
falsePause countdowns while the window is not focused, so a toast never expires while you are in another app.
newestFirst
boolean
trueNewest toast sits nearest the viewport edge. Set false to keep the oldest in front and append behind it.
closeOnClick
boolean
falseDismiss a toast when its body is clicked. Action and close buttons are excluded.
loadingIcon
ReactNode
Replace the loading spinner. Shorthand for icons.loading.
containerAriaLabel
string
'Notifications'Accessible label for the toast region.
closeButtonAriaLabel
string
'Close'Accessible label for the close button. Translate this for non-English apps.
icons
{ success, info, warning, error, loading, close }
Replace any built-in icon with your own node.
zIndex
number
9999Base stacking order for the toast region.
className
string
Class on the toast list element. Alias: containerClassName.

toast methods

Every method returns the toast id.

NameTypeDefaultDescription
fntoast
(message, options?)
Neutral toast.
fntoast.message
(message, options?)
Alias for toast().
fntoast.success
(message, options?)
Success variant.
fntoast.error
(message, options?)
Error variant. Announced assertively and defaults to a 5000ms duration.
fntoast.info
(message, options?)
Info variant.
fntoast.warning
(message, options?)
Warning variant. Alias: toast.warn.
fntoast.loading
(message, options?)
Spinner that never auto-dismisses until updated or dismissed.
fntoast.custom
(node(id) => node, options?)
No semantic styling. Accepts a render function that receives the toast id, so the node can dismiss itself — the Sonner form.
fntoast.promise
(promise, options)
Drives one toast through loading, success and error. Returns { id, unwrap() } — unwrap re-throws on rejection. Never causes an unhandled rejection.
fntoast.update
(id, patch)
Patch an existing toast. Fields you omit are preserved.
fntoast.dismiss
(id?)
Dismiss one toast, or every toast when called with no argument.
fntoast.remove
(id)
Remove without firing onDismiss.
fntoast.clearAll
()
Legacy alias for toast.dismiss().
fntoast.getToasts
()
The current queue.
fntoast.getHistory
()
Toasts that have already closed, oldest first.
fntoast.isActive
(id)
Whether a toast is still queued or on screen.
fnuseVyrn
() => { toasts }
Headless hook — render the queue yourself. Alias: useSonner.

Toast options

Second argument to every toast method.

NameTypeDefaultDescription
id
stringnumber
Stable id. Passing one that already exists updates that toast instead of adding a duplicate.
description
ReactNode
Secondary line below the message.
duration
number
4000ms before auto-dismiss. 0 or Infinity keeps it open.
icon
ReactNode
Override the icon for this toast.
action
{ label, onClick, style?, dismiss?, altText? }
Single action button. dismiss: false keeps the toast open after the click; altText gives an icon-only button an accessible name.
actions
ToastAction[]
Several action buttons — a Vyrn extension over Sonner's single action.
cancel
{ label, onClick?, className? }
Secondary cancel button.
input
{ placeholder, onSubmit, submitLabel?, defaultValue?, allowEmpty? }
Inline text field. The countdown pauses while it has focus.
position
ToastPosition
Place this toast in its own corner.
dismissible
boolean
truefalse hides the close button and blocks swipe and Escape.
important
boolean
falseAnnounce assertively regardless of type.
progress
number
0-100 determinate progress. Replaces the duration countdown with a measured bar.
groupId
string
Toasts sharing a group occupy one slot — each new message replaces the last.
preventDuplicate
boolean
Identical text of the same type refreshes the existing toast instead of stacking a second copy. Ideal for retry loops.
closeOnClick
boolean
Per-toast override of the global click-to-dismiss setting.
priority
'low''normal''high'
'normal'Visual emphasis. high gets an accent ring, low is subdued.
expandable
boolean
falseKeep actions collapsed until the toast is clicked. Pair with expanded to control it.
size
'sm''md''lg'
Per-toast density override.
richColors
boolean'minimal''soft''solid'
Per-toast override of the global rich colors setting.
invert
boolean
Invert just this toast.
className
string
Class on the toast element.
classNames
ToastClassNames
Per-part classes: toast, title, description, icon, content, actionButton, cancelButton, closeButton, progressBar, input, plus one per type.
style
CSSProperties
Inline styles. Legacy alias: customStyles.
unstyled
boolean
falseStrip all built-in styling, keeping only positioning.
jsx
ReactNode(id) => ReactNode
Replace the toast's entire contents. A function receives the toast id.
customComponent
ComponentType<{ toast, dismiss }>
Replace the toast element itself.
soundEffect
string
URL played when the toast appears.

Callbacks

NameTypeDefaultDescription
onClick
(event) => void
Makes the whole toast a button, with Enter and Space support.
onDismiss
(toast) => void
Closed by the user or programmatically — not by the timer.
onAutoClose
(toast) => void
Closed because its duration elapsed.
onClose
() => void
Legacy: fires on any close, after onDismiss / onAutoClose.

Accessibility

Built in — nothing to configure.

NameTypeDefaultDescription
Live regions
one politeone assertive
Announcements come from a single pair of off-screen regions. Toasts themselves carry no live semantics, so nothing is announced twice and a dismissed toast is never re-read.
Markup
region > ol > li
A labelled region wrapping a semantic ordered list.
Keyboard
Alt+TEscapeEnter
Alt+T moves focus into the list, Escape dismisses, Enter or Space activates a clickable or expandable toast.
Hover pause
all toasts
Hovering or focusing the list pauses every countdown, not just the one under the pointer.
Motion
prefers-reduced-motion
All motion is removed when the OS asks for it. forced-colors is supported too.
Focus return
automatic
Dismissing a focused toast moves focus to the next toast, or back to whatever was focused before you entered the list — never to the document body.
Hydration
SSR safe
The server emits no toast markup, so hydration cannot mismatch even if a toast was dispatched before the Toaster mounted.