@xsolla/xui-toast
v0.162.0
Published
A cross-platform toast notification system matching the base Figma toast. Use it for short, non-blocking feedback with a title, optional description, optional action, and automatic or manual dismissal.
Readme
Toast
A cross-platform toast notification system matching the base Figma toast. Use it for short, non-blocking feedback with a title, optional description, optional action, and automatic or manual dismissal.
Installation
npm install @xsolla/xui-toastImports
import {
Toast,
ToastProvider,
ToastGroup,
ToastContext,
useToast,
type ToastProps,
type ToastOptions,
type ToastType,
type ToastPosition,
type ToastAlign,
type UseToastReturn,
} from "@xsolla/xui-toast";Quick start
Wrap your app with ToastProvider, then call useToast from any descendant.
import * as React from "react";
import { XUIProvider } from "@xsolla/xui-core";
import { ToastProvider, useToast } from "@xsolla/xui-toast";
function SaveButton() {
const toast = useToast();
return (
<button onClick={() => toast.success({ title: "Saved successfully" })}>
Save
</button>
);
}
export default function App() {
return (
<XUIProvider initialMode="dark">
<ToastProvider>
<SaveButton />
</ToastProvider>
</XUIProvider>
);
}React Native: ensure the root container under
ToastProviderhasflex: 1so absolute-positioned toasts have a reference height.
API Reference
<ToastProvider>
Root provider. Manages toast state, auto-dismiss timers, and renders the ToastGroup.
| Prop | Type | Default | Description |
| ----------------- | ------------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------- |
| testID | string | - | Test ID for testing frameworks. On web this renders as data-testid; on React Native it renders as testID. |
| children | ReactNode | - | Application content. |
| position | "top" \| "bottom" | "top" | Vertical anchor of the toast container. |
| align | "left" \| "center" \| "right" | "center" | Horizontal alignment of toasts within the container. |
| defaultDuration | number | 5000 | Default auto-dismiss duration in ms. Set 0 to disable auto-dismiss globally. |
| maxWidth | number | - | Maximum width in px of the toast stack. |
<Toast>
The individual toast cell. Used internally by ToastGroup, but can be rendered standalone for static display.
| Prop | Type | Default | Description |
| ----------------- | ------------------------------------------------ | ----------- | ------------------------------------------------------------------ |
| id | string | - | Required unique identifier. |
| type | "alert" \| "success" \| "neutral" \| "warning" | "neutral" | Visual and accessibility type. |
| title | string | - | Short primary text, ideally 1 to 5 words. |
| description | string | - | Optional supporting text. |
| icon | boolean \| ReactNode | true | Show the default icon, hide it with false, or pass a custom one. |
| action | ReactElement | - | Optional action element, typically a FlexButton. |
| showCloseButton | boolean | true | Show the trailing dismiss control when onClose is provided. |
| progress | boolean | false | Show the bottom progress strip. |
| duration | number | - | Auto-dismiss duration in ms. 0 or omitted = no auto-dismiss. |
| onClose | () => void | - | Close handler. Required for the close button to render. |
Inherits ThemeOverrideProps (themeMode, themeProductContext).
<ToastGroup>
Renders the stack of visible toasts. On web uses ReactDOM.createPortal to escape stacking contexts; on React Native uses absolute positioning.
| Prop | Type | Default | Description |
| ----------- | ------------------------------- | ---------- | --------------------------- |
| toasts | ToastData[] | - | Toasts to render. |
| position | "top" \| "bottom" | "top" | Vertical anchor. |
| align | "left" \| "center" \| "right" | "center" | Horizontal alignment. |
| maxWidth | number | - | Maximum width in px. |
| onDismiss | (id: string) => void | - | Dismiss callback per toast. |
Inherits ThemeOverrideProps.
useToast()
Hook that returns toast helpers. Throws if called outside a ToastProvider.
| Method | Signature | Description |
| ------------ | ------------------------------------------------- | ----------------------------------------------------- |
| toast | (options: ToastOptions) => string | Show a toast with full options. Returns the toast ID. |
| alert | (options: Omit<ToastOptions, "type">) => string | Show an alert toast. |
| success | (options: Omit<ToastOptions, "type">) => string | Show a success toast. |
| neutral | (options: Omit<ToastOptions, "type">) => string | Show a neutral toast. |
| warning | (options: Omit<ToastOptions, "type">) => string | Show a warning toast. |
| dismiss | (id: string) => void | Dismiss a specific toast by ID. |
| dismissAll | () => void | Dismiss all visible toasts. |
ToastOptions
| Property | Type | Default | Description |
| ----------------- | ------------------------------------------------ | ---------------------------- | ------------------------------------------------------------------ |
| type | "alert" \| "success" \| "neutral" \| "warning" | "neutral" | Visual and accessibility type. |
| title | string | - | Short primary text. |
| description | string | - | Optional supporting text. |
| icon | boolean \| ReactNode | true | Show, hide, or override the icon. |
| action | ReactElement | - | Optional action element. |
| showCloseButton | boolean | true | Show the close button when the toast is dismissible. |
| progress | boolean | false | Show the bottom progress strip. |
| duration | number | provider's defaultDuration | Auto-dismiss duration. 0 keeps the toast until dismissed manually. |
ToastData
Internal shape exposed via ToastContext.toasts.
| Property | Type | Description |
| ------------- | ----------- | -------------------------------------------- |
| id | string | Unique identifier generated by the provider. |
| type | ToastType | Toast type. |
| title | string | Primary text. |
| description | string | Supporting text. |
| duration | number | Auto-dismiss duration. |
ToastContext
React context with { toasts, addToast, dismissToast, dismissAllToasts }. Typically consumed via useToast; available for advanced use cases:
import { useContext } from "react";
import { ToastContext } from "@xsolla/xui-toast";
function ActiveCount() {
const ctx = useContext(ToastContext);
if (!ctx) throw new Error("Must be within ToastProvider");
return <span>Active toasts: {ctx.toasts.length}</span>;
}Examples
Types
import * as React from "react";
import { useToast } from "@xsolla/xui-toast";
export default function Types() {
const toast = useToast();
return (
<div style={{ display: "flex", gap: 8 }}>
<button onClick={() => toast.neutral({ title: "Reward claimed" })}>
Neutral
</button>
<button onClick={() => toast.success({ title: "Quest activated" })}>
Success
</button>
<button onClick={() => toast.warning({ title: "Session expires soon" })}>
Warning
</button>
<button onClick={() => toast.alert({ title: "Connection lost" })}>
Alert
</button>
</div>
);
}Standalone Toast With Action
import * as React from "react";
import { FlexButton } from "@xsolla/xui-button";
import { Toast } from "@xsolla/xui-toast";
export default function Standalone() {
return (
<Toast
id="retry"
type="alert"
title="Connection lost"
description="Check your network and try again"
action={<FlexButton>Retry</FlexButton>}
progress
onClose={() => {}}
/>
);
}Custom duration
import * as React from "react";
import { useToast } from "@xsolla/xui-toast";
export default function Duration() {
const toast = useToast();
return (
<button
onClick={() =>
toast.toast({
type: "neutral",
title: "Manual dismiss",
duration: 0,
})
}
>
Show sticky toast
</button>
);
}Position and alignment
import * as React from "react";
import { ToastProvider, useToast } from "@xsolla/xui-toast";
function Trigger() {
const toast = useToast();
return (
<button onClick={() => toast.neutral({ title: "Bottom-right toast" })}>
Show
</button>
);
}
export default function BottomRight() {
return (
<ToastProvider position="bottom" align="right" maxWidth={440}>
<Trigger />
</ToastProvider>
);
}Platform support
| Aspect | Web | React Native |
| -------------- | ------------------------------------------ | --------------------------------- |
| Rendering | ReactDOM.createPortal to document.body | Absolute-positioned Box in tree |
| Event handlers | onClick | onPress |
| Root container | Any element | Must have flex: 1 |
Accessibility
- Neutral and success toasts render with
role="status"and polite announcements. - Warning and alert toasts render with
role="alert"and assertive announcements. - The close button has
aria-label="Dismiss notification". - Do not rely on color alone; the icon and text also communicate the type.
Troubleshooting
- "useToast must be used within a ToastProvider" - ensure the calling component is a descendant of
ToastProvider. - Toasts hidden on React Native - wrap content in
<View style={{ flex: 1 }}>insideToastProvider. - Toasts appear behind a modal (web) -
ToastGroupusesz-index: 9999. PlaceToastProviderabove the modal in the tree, or adjust z-index. - Auto-dismiss not working -
duration: 0disables auto-dismiss; check both per-toast and provider defaults.
