export default plugin({
start(api) {
api.toasts.show({
content: 'Saved to your library',
variant: 'success',
})
},
})
Unscoped access
export default plugin({
start(api) {
api.unscoped.toasts.show('Saved to your library')
},
})
The scoped API is attached to your plugin by the Toast API
dependency. The unscoped form comes from the shared API registry;
both references point to the same instance, toast stack, and
settings. Pick whichever access path fits the surrounding code.
Try the update flow
This browser preview is illustrative. In your plugin, call
show() once and update the returned ID.
✓Ready when you are
Choose what to read next
Toast options covers message content, variants,
icons, custom presses, and all fields accepted by
ToastInput. Methods & lifecycle
explains de-duplication, updates, timers, subscriptions, and
dismissal callbacks.
Shared settings documents each setting and its
default. These settings are shared by every plugin using this
API, so prefer per-toast options when a choice only belongs to
one message.
Pass a string for a quick message, or an object when the toast needs
a subtitle, a status icon, or an action. Every option below can be
passed to show(); update() accepts a
partial object.
A toast with an action
const id = toasts.show({
key: 'library:save',
content: 'Saved to your library',
subtitle: 'Available on this device',
variant: 'success',
duration: 3000,
position: 'bottom',
onPress: () => openLibrary(),
})
!
Icons are selected by precedence. A supplied
custom icon is used with the variant icon on the opposite side
when showSecondIcon is enabled. An explicit
secondIcon takes precedence over that automatic
variant icon.
Message and identity
contentReactNoderequired
This is the primary message and the only required field when
passing an object to show(). Keep it concise:
toasts are transient and may be limited to a few lines by
the shared lineClamp setting.
show() also accepts a plain string as shorthand
for { content: string }. String messages are
deduplicated by their text unless you supply an explicit
key.
subtitleReactNode—
Secondary text appears below the main message when the
shared showSubtitle setting is enabled. Use it
for a filename, a short status detail, or a useful next step
rather than repeating the title.
The subtitle is still part of the toast entry when it is
hidden by settings. Updating it does not change the main
message or the toast's identity.
keystringderived
An explicit key makes repeated show() calls
return the existing toast ID instead of adding a duplicate.
This is useful for a stable operation such as
upload:avatar.
Without a key, string content is used as the de-duplication
identity; non-string content gets a fresh identity. Updating
a toast preserves its original key.
variantToastVariant"default"
Choose default, success,
critical, warning, or
info to select the semantic status icon. The
default variant is used when this field is omitted.
The variant affects icon choice, not the card's background
color. Colors and icon visibility are controlled by shared
settings and any explicit icon options.
Timing and placement
durationnumber · millisecondsmode-dependent
In durationMode: "toast", this is the timeout
requested for this toast; if omitted, the shared
defaultDurationMs is used. The shared minimum
and maximum can clamp the resolved value.
A resolved duration of 0 means no timer is
started, so the toast remains until closed. The
default and override duration modes
ignore this per-toast value.
position"top" | "bottom"shared setting
This chooses which edge of the screen receives the toast.
When omitted, the shared position setting is
used.
Changing the shared position does not move an already-created
entry; set this field in an update() patch when
you want to move a particular toast.
Icons
iconnumber | () => ReactNodevariant icon
Pass a packager asset ID or a function that returns React
nodes to render a custom primary icon. When no custom icon is
provided, the variant's generated icon is used where one
exists.
Use iconEntity or IconComponent
when those better match your source. A custom icon can sit
beside the variant icon when
settings.showSecondIcon is enabled.
iconEntityToastIconEntity—
Use an entity for an emoji or remote image: set
type: "emoji" with unicode, or
provide src for an image. The renderer uses the
emoji when both the type and Unicode value match; otherwise
it renders the source URL if present.
The entity's alt value is retained in the entry
but is not currently applied to the rendered image. Do not
rely on it to provide an accessibility label.
ToastIconEntity.typestringrequired
Set this to emoji when the entity should render
its Unicode value. The current renderer treats other values as
non-emoji and attempts to display src when it is
present.
The TypeScript interface accepts any string, but only
emoji has special behavior. Prefer
image for image entities to keep the value
self-explanatory.
ToastIconEntity.unicodestring—
This is the emoji character shown when
type is emoji. If it is missing or
empty, the entity renderer falls through to src
if a source URL exists.
Provide the actual Unicode character or sequence, not a
Discord custom emoji name. This field does not cause the
renderer to download or resolve emoji metadata.
ToastIconEntity.srcstring · URI—
This is the URI passed to React Native's image component when
the entity is not rendered as a Unicode emoji. Use a URL the
client can access and that returns an image.
The image is displayed with contain sizing at the shared
iconSize. An invalid or inaccessible URI may
leave the icon blank.
ToastIconEntity.altstring—
This field can carry a short text description alongside the
entity data. The current renderer does not pass it to the
image component or expose it as an accessibility label.
Do not rely on alt alone to make an image
accessible. Put essential meaning in the toast's message or
provide an appropriately labeled press action.
IconComponentComponentType—
Provide a React component to render as the primary icon.
The API invokes it with a small size, the resolved icon
color, and a width/height style based on
iconSize.
This takes precedence over icon and
iconEntity. If the variant has an icon and
showSecondIcon is enabled, the variant can be
shown on the opposite side.
iconColorstringDiscord heading token
This color is passed to component and generated icons, and
can tint a packager asset when
recolorLegacyIcon is true. Use a Discord
semantic token name or a hexadecimal color such as
#78a98c.
If omitted, the renderer uses
MOBILE_TEXT_HEADING_PRIMARY. An asset keeps
its own artwork colors unless recoloring is explicitly
requested.
recolorLegacyIconbooleanfalse
When true, a primary numeric packager asset receives
iconColor as a tint. This is intended for
monochrome legacy assets that should follow Discord's icon
color.
It does not recolor React-node icons, entity images, or the
second icon. Leave it off for full-color artwork.
secondIconnumber | () => ReactNode—
This renders an additional numeric asset or React-node icon
on the side opposite the primary icon. It is an explicit
second icon, so it takes precedence over an automatically
shown variant icon.
If an entry has no primary icon, setting
showSecondIcon does not invent one; use a
primary icon or provide the second icon explicitly.
secondIconEntityToastIconEntity—
This uses the entity renderer for the icon opposite the
primary icon. Provide emoji Unicode or an image source using
the same fields as iconEntity.
It takes precedence over secondIcon and
SecondIconComponent only according to the
renderer's explicit second-icon order: component first,
entity next, then numeric asset or node function.
SecondIconComponentComponentType—
Provide a React component to render opposite the primary
icon. It receives the shared icon size and
secondIconColor, or the default icon color if
that color is omitted.
When multiple second-icon fields are set, this component
wins over secondIconEntity and
secondIcon. Prefer setting only one so the
rendering choice stays clear.
secondIconColorstringDiscord heading token
This sets the resolved color passed to the second icon
component or generated variant icon. It accepts a semantic
Discord token or a hexadecimal color.
If omitted, the second icon uses
MOBILE_TEXT_HEADING_PRIMARY. Entity images
and numeric packager assets preserve their artwork unless
otherwise tinted by their own rendering path.
iconSide"left" | "right"shared setting
This selects which side of the text holds the primary icon;
any second icon is placed on the opposite side. If omitted,
the shared iconSide setting is used.
The content area keeps the renderer's legacy spacing on the
left. Use this per-toast field when a specific toast needs a
different arrangement.
Appearance and interaction
containerStyleStyleProp<ViewStyle>—
Apply React Native view styles to the toast card or
pressable container. This style is applied after the
renderer's built-in style, so matching properties can
override its computed values.
Use this sparingly for a one-off adjustment; the shared
settings are a better fit for appearance that should stay
consistent across messages.
onPress(id: string) => void—
When supplied, the toast becomes pressable and the callback
receives its entry ID. Use it to navigate to relevant
content, open a detail view, or surface an undo action.
The callback is invoked before the default close behavior.
Exceptions are reported through the Toast API plugin's error
reporter rather than the console.
closeOnPressbooleantrue
By default, tapping a toast with onPress
closes it after the callback runs. Set this to false when
the toast should remain visible after its action.
This option has no effect unless the toast is pressable.
Closing the toast still runs onDismiss as usual.
onDismiss() => void—
This callback runs when the toast is removed by its timeout
or by a close action such as close(id) or
pop(). Use it to release toast-specific
resources or update related state.
It does not run when the API evicts an entry to enforce
maxVisible, or when the plugin internally
clears all entries during shutdown. Callback errors are
reported by the API.
A toast is more than a one-off message. The returned ID gives you a
handle for progress, completion, cancellation, and cleanup.
One operation, three states
const id = toasts.show({
key: 'export:monthly-report',
content: 'Preparing report…',
duration: 0,
})
toasts.update(id, {
content: 'Report ready',
variant: 'success',
duration: 2500,
})
// If the operation is cancelled:
toasts.close(id)
API methods
show(input: ToastInput | string): stringreturns toast ID
Add a toast and return the ID to use with
update() and close(). If the
identity is already present, the existing ID is returned
instead of creating a duplicate.
update(id, patch): booleanfalse if ID is not active
Merge the supplied fields into an active toast and keep all
fields not mentioned in the patch. A changed
duration recalculates and restarts its timer;
omitting duration leaves the current timer alone.
close(id?): voidone toast or all
Pass an ID to close that entry and run its dismissal callback.
Call without an ID to close every entry; this is equivalent to
closeAll().
closeAll(): voidclose every active toast
Remove all current entries, clear their timers, and invoke each
entry's onDismiss callback. Each callback is
isolated, so an error in one does not prevent the others from
running.
pop(): voidclose newest entry
Close the most recently added entry in the active list. If the
list is empty, nothing happens.
list(): ToastEntry[]read active entries
Return the current toast entries in their store order. Each
entry includes the original input fields and the resolved ID,
key, variant, position, duration, and creation timestamp.
subscribe(callback): () => voidobserve list changes
Subscribe to changes in the active toast list; the callback
receives no arguments, so call list() to read the
new entries. The returned function unsubscribes that listener.
What update changes
An update is a shallow merge, not a replacement. For example,
updating only content leaves the previous subtitle,
icon, position, callbacks, and variant intact.
The entry ID and de-duplication key are fixed after creation.
Setting duration to a different value re-resolves
the timeout through the current duration mode and resets the
timer; setting the same value does not reset it.
i
Keep progress toasts open intentionally. Use
duration: 0 when the result depends on an ongoing
operation, then set a finite duration on a completion update or
close it when the operation is cancelled.
ToastEntry fields
list() returns entries with the original
ToastInput options plus the resolved fields below.
Use update() to change an entry; changing the object
returned from list() directly does not notify the
renderer.
Field
Type
Meaning
id
string
Unique handle returned by show(). Use this value to update or close this entry.
key
string
De-duplication identity assigned at creation. Explicit keys are preserved across updates.
variant
ToastVariant
The resolved variant, defaulting to default when omitted. This determines semantic icon choice.
durationMs
number
Resolved timer length after duration mode and min/max rules. A value of zero means no automatic timer.
position
ToastPosition
The resolved edge used by the toast stack. It defaults to the shared position when not specified on input.
createdAt
number
Creation time as a Unix timestamp in milliseconds. Updating the toast does not change this value.
Dismissal and capacity
onDismiss runs when a timer expires or a close
method removes the entry. It does not run when
the stack drops its oldest entry to obey maxVisible;
that capacity eviction only clears the timer.
The capacity limit is enforced when a new toast is shown.
Changing maxVisible does not retroactively trim the
active list, and a setting change does not recalculate timers for
toasts already on screen.
Shared settings control how every API toast looks and behaves.
They're persisted by the Toast API plugin, so a change here affects
other plugins using the same renderer.
Keep changes narrow. Use
settings.set() for a real preference that should
apply across plugins. Per-toast position,
duration, icons, and container styles are better for
one-off cases.
Settings methods
settings.get(): ToastApiSettingscurrent snapshot
Read the current merged settings, including defaults and
persisted values. Treat the result as a snapshot and call
get() again after a notification.
settings.set(patch): voidpersist partial changes
Merge your patch into the existing settings and persist the
result through the Toast API plugin's storage. Fields you omit
are preserved.
settings.reset(): voidrestore defaults
Replace the current settings with the built-in defaults. This
is a global change for the shared toast renderer, not a
per-plugin reset.
Subscribe to settings changes; the callback receives no
arguments, so call get() for the current snapshot.
The returned function removes the listener.
Every setting
Each option includes its built-in default. Blank color and font
values mean “use Discord's current theme or component defaults,” not
a literal empty color.
Stack and timing
Setting
Type · default
What it controls
position
ToastPosition · "top"
Default screen edge for new toasts without a per-toast position. An explicit ToastInput.position takes precedence.
maxVisible
number · 3
Maximum number of active toasts kept in the visible stack. Zero means unlimited; lowering this setting does not trim entries already shown.
durationMode
ToastDurationMode · "toast"
Selects whether a toast's requested timeout, the shared default, or the shared override is used. The mode applies when a toast is created or its duration is changed.
defaultDurationMs
number · 2000
Timeout used when mode is default, or when mode is toast and the toast omits duration. This value is in milliseconds.
overrideDurationMs
number · 3000
Timeout used for every toast in override mode. Per-toast duration is ignored while this mode is active.
minDurationMs
number · 0
Lower bound applied after resolving the duration mode. Zero disables the minimum; a positive value can turn a requested zero into a timed toast.
maxDurationMs
number · 0
Upper bound applied after resolving the duration mode. Zero disables the maximum; set a positive value to prevent toasts lingering too long.
Card, spacing, and icons
Setting
Type · default
What it controls
radius
number · 8
Corner radius of the toast card in React Native layout units. Larger values make the card rounder; zero produces square corners.
paddingY
number · 8
Vertical space inside the card above and below its content. This value is applied to both top and bottom padding.
paddingX
number · 12
Horizontal space inside the card before its first item and after its last item. It does not replace the content-to-icon spacing.
gap
number · 8
Space between neighboring cards in the stack. It affects both top and bottom toast groups.
borderWidth
number · 1
Card border thickness in layout units. Set to zero to remove the border's visible width.
shadow
boolean · true
Enables the theme-aware high shadow used to lift the card from the screen. Disable it for a flatter appearance.
maxWidth
number · 0
Maximum card width in layout units. Zero chooses the available screen width with a built-in side margin.
iconSize
number · 24
Width and height supplied to generated icons, custom icon components, and entity emojis. Components receive the library's small-size prop as well.
iconSide
ToastIconSide · "left"
Default side for the primary icon relative to the text. A per-toast iconSide overrides it.
showSecondIcon
boolean · false
When a toast provides a custom primary icon, this setting can place its variant icon on the other side. An explicit second icon takes precedence over the automatic variant icon.
lineClamp
number · 3
Maximum number of lines passed to both title and subtitle text components. Keep the value modest so a toast does not occupy too much of the screen.
Text and color
Setting
Type · default
What it controls
textVariant
string · "text-sm/semibold"
Design-system text variant used for the main message. Use a variant supported by Discord's Mana text component.
textSize
number · 0
Optional explicit font size for the main message. Zero leaves sizing to textVariant.
textColor
string · ""
Optional text color, resolved from a semantic token name or hexadecimal value. Empty leaves the text component's mobile-text-heading-primary color in place.
fontFamily
string · ""
Optional font family applied to both title and subtitle. Empty keeps the design system's normal font selection.
backgroundColor
string · ""
Card fill color, resolved from a token name or hexadecimal value. Empty uses MOBILE_TOAST_BACKGROUND_DEFAULT for the current theme.
borderColor
string · ""
Card outline color, resolved from a token name or hexadecimal value. Empty uses Discord's BORDER_SUBTLE token.
showSubtitle
boolean · true
Controls whether subtitle content is rendered beneath the main message. A per-toast subtitle remains in its entry while hidden.
subtitleVariant
string · "text-sm/normal"
Design-system text variant used by subtitle text. It is separate from the main message's variant and font-size override.
Discord integration
Setting
Type · default
What it controls
overrideDiscordToasts
boolean · false
Routes supported Discord toast action calls through this shared renderer. Leave disabled if your plugin only needs to create its own toasts.
Duration resolution
Mode
Value used
Then
toast
ToastInput.duration, or defaultDurationMs
Apply minDurationMs and maxDurationMs when positive.
default
defaultDurationMs
Ignore ToastInput.duration, then apply min/max.
override
overrideDurationMs
Ignore ToastInput.duration, then apply min/max.
The bounds are applied in order: minimum first, maximum second,
then the result is clamped to at least zero. If both bounds are
set inconsistently, the maximum can reduce the result below the
minimum.