Toast
View .mdA toast displays temporary content that can be dismissed by user action or an application timeout.
Default
Loading interactive example. Full source is available below.
View example source
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { ToastBody } from "@coreai-ds/react-components";
import { ToastFooter } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
export const Default = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast>
<ToastTitle action={<Link>Undo</Link>}>Email sent</ToastTitle>
<ToastBody subtitle="Subtitle">This is a toast body</ToastBody>
<ToastFooter>
<Link>Action</Link>
<Link>Action</Link>
</ToastFooter>
</Toast>, { intent: 'success' });
return (<>
<Toaster toasterId={toasterId}/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default Default;
Resources
Best practices
Do
- Use toasts for non-critical messages.
- Configure defaults on the toaster.
- Let people view toast content in the application after the toast is dismissed.
- Create a keyboard shortcut to move focus to actionable toasts.
Don't
- Render too many toasts at once.
- Use different positions for toasts.
- Use more than one toaster in an application.
- Make every toast use assertive politeness.
Behavior and states
- Use toasts to communicate task status, progress, required actions, application updates, or errors.
- Make notifications available on a permanent surface so important information remains accessible.
API referenceGenerated CoreAI prop and type summaries
API
Generated CoreAI prop summaries, not replacement type declarations. Most native DOM/event and ARIA props are omitted. ? means optional; JSDoc shows defaults, deprecations, and conditional requirements. Defaults assume the standard CoreAI provider.
Toast API
Toast component
interface ToastProps {
appearance?: "brand" | "inverted";
as?: "div";
children?: any;
className?: string;
ref?: Ref<HTMLDivElement>;
style?: CSSProperties;
}
ToastBody API
ToastBody component
interface ToastBodyProps {
as?: "div";
children?: any;
className?: string;
ref?: Ref<HTMLDivElement>;
style?: CSSProperties;
subtitle?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;
}
ToastFooter API
ToastFooter component
interface ToastFooterProps {
as?: "div";
children?: any;
className?: string;
ref?: Ref<HTMLDivElement>;
style?: CSSProperties;
}
ToastTitle API
ToastTitle component
interface ToastTitleProps {
action?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;
as?: "div";
children?: any;
className?: string;
media?: WithSlotShorthandValue<{ as?: "div"; } & Omit<Omit<DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & { ref?: ((instance: HTMLDivElement | null) => void) | RefObject<HTMLDivElement> | null; }, "children"> & { children?: any; }> | null | undefined;
ref?: Ref<HTMLDivElement>;
style?: CSSProperties;
}
Toaster API
Toaster component - renders a collection of toasts dispatched imperatively
interface ToasterProps {
/**
* User override API for aria-live narration for toasts
*/
announce?: ToastAnnounce;
as?: "div";
className?: string;
inline?: boolean;
limit?: number;
/**
* Where the portal children are mounted on DOM
* @default a new element on document.body without any styling
*/
mountNode?: HTMLElement | { element?: HTMLElement | null; className?: string; } | null | undefined;
offset?: ToastOffset;
/**
* Toast timeout pauses while user cursor is on the toast
* @default false
*/
pauseOnHover?: boolean;
/**
* Toast timeout pauses while focus is on another window
* @default false
*/
pauseOnWindowBlur?: boolean;
/**
* The position the toast should render to
*/
position?: "top" | "bottom" | "top-end" | "top-start" | "bottom-end" | "bottom-start";
/**
* Higher priority toasts will be rendered before lower priority toasts
*/
priority?: number;
shortcuts?: ToasterShortcuts;
style?: CSSProperties;
/**
* Auto dismiss timeout in milliseconds
* @default 3000
*/
timeout?: number;
toasterId?: string;
}
Implementation
CoreAI 0.12.0; Fluent 9.74.9.
Import components from @coreai-ds/react-components. CoreAI guidance above takes precedence over API demonstration examples.
Custom Timeout
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import * as React from 'react';
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { ToastTrigger } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { SpinButton } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
export const CustomTimeout = (): JSXElement => {
const [timeout, setDismissTimeout] = React.useState(1000);
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast>
<ToastTitle action={<ToastTrigger>
<Link>Dismiss</Link>
</ToastTrigger>}>
{timeout >= 0 ? `Custom timeout ${timeout}ms` : `Dismiss manually`}
</ToastTitle>
</Toast>, { timeout, intent: 'info' });
return (<>
<Field label="Timeout" hint="Timeout is in milliseconds">
<SpinButton value={timeout} onChange={(e, data) => {
if (data.value) {
setDismissTimeout(data.value);
}
else if (data.displayValue !== undefined) {
const newValue = parseFloat(data.displayValue);
if (!Number.isNaN(newValue)) {
setDismissTimeout(newValue);
}
}
}}/>
</Field>
<br />
<Toaster toasterId={toasterId}/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default CustomTimeout;
Default Toast Options
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
export const DefaultToastOptions = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast>
<ToastTitle>Options configured in Toaster</ToastTitle>
</Toast>, { intent: 'info' });
return (<>
<Toaster toasterId={toasterId} position="top-end" pauseOnHover pauseOnWindowBlur timeout={1000}/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default DefaultToastOptions;
Dismiss All
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
export const DismissAll = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast, dismissAllToasts } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast>
<ToastTitle>This is a toast</ToastTitle>
</Toast>, { intent: 'info' });
const dismissAll = () => dismissAllToasts();
return (<>
<Toaster toasterId={toasterId}/>
<Button onClick={notify}>Make toast</Button>
<Button onClick={dismissAll}>Dismiss all toasts</Button>
</>);
};
export default DismissAll;
Dismiss Toast
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import * as React from 'react';
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
export const DismissToast = (): JSXElement => {
const toasterId = useId('toaster');
const toastId = useId('example');
const [unmounted, setUnmounted] = React.useState(true);
const { dispatchToast, dismissToast } = useToastController(toasterId);
const notify = () => {
dispatchToast(<Toast>
<ToastTitle>This is a toast</ToastTitle>
</Toast>, { toastId, intent: 'success', onStatusChange: (e, { status }) => setUnmounted(status === 'unmounted') });
setUnmounted(false);
};
const dismiss = () => dismissToast(toastId);
return (<>
<Toaster toasterId={toasterId}/>
<Button onClick={unmounted ? notify : dismiss}>{unmounted ? 'Make' : 'Dismiss'} toast</Button>
</>);
};
export default DismissToast;
Dismiss Toast With Action
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { ToastTrigger } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
export const DismissToastWithAction = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast>
<ToastTitle action={<ToastTrigger>
<Link>Dismiss</Link>
</ToastTrigger>}>
Dismiss me
</ToastTitle>
</Toast>, { intent: 'success' });
return (<>
<Toaster toasterId={toasterId}/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default DismissToastWithAction;
Focus Keyboard Shortcut
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { ToastTrigger } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { ToastBody } from "@coreai-ds/react-components";
import { ToastFooter } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
export const FocusKeyboardShortcut = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast>
<ToastTitle action={<ToastTrigger>
<Link>Dismiss</Link>
</ToastTrigger>}>
Email sent
</ToastTitle>
<ToastBody subtitle="Subtitle">This is a toast body</ToastBody>
<ToastFooter>
<Link>Action</Link>
<Link>Action</Link>
</ToastFooter>
</Toast>, { intent: 'success' });
return (<>
<Toaster limit={3} shortcuts={{ focus: e => e.ctrlKey && e.key === 'm' }} toasterId={toasterId}/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default FocusKeyboardShortcut;
Inline
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import * as React from 'react';
const useStyles = makeStyles({
container: {
border: '2px dashed green',
height: '500px',
width: '500px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
position: 'relative',
marginTop: '20px',
},
});
export const Inline = (): JSXElement => {
const styles = useStyles();
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast>
<ToastTitle action={<Link>Undo</Link>}>Email sent</ToastTitle>
</Toast>, { intent: 'success' });
return (<>
<Button onClick={notify}>Make toast</Button>
<div className={styles.container}>
<Text weight="bold">Toasts appear here</Text>
<Toaster inline toasterId={toasterId} position="bottom"/>
</div>
</>);
};
export default Inline;
Intent
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ToastIntent } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Spinner } from "@coreai-ds/react-components";
import { Avatar } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
export const Intent = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const [intent, setIntent] = React.useState<ToastIntent | 'progress' | 'avatar'>('success');
const notify = () => {
switch (intent) {
case 'progress':
dispatchToast(<Toast>
<ToastTitle media={<Spinner size="tiny"/>}>Progress toast</ToastTitle>
</Toast>);
break;
case 'avatar':
dispatchToast(<Toast>
<ToastTitle media={<Avatar name="Erika Mustermann" size={16}/>}>Avatar toast</ToastTitle>
</Toast>);
break;
case 'error':
case 'info':
case 'success':
case 'warning':
dispatchToast(<Toast>
<ToastTitle>Toast intent: {intent}</ToastTitle>
</Toast>, { intent });
break;
}
};
return (<>
<Field label="Select a intent">
<RadioGroup value={intent} onChange={(e, data) => setIntent(data.value as ToastIntent)}>
<Radio label="success" value="success"/>
<Radio label="info" value="info"/>
<Radio label="warning" value="warning"/>
<Radio label="error" value="error"/>
<Radio label="progress (custom media slot)" value="progress"/>
<Radio label="avatar (custom media slot)" value="avatar"/>
</RadioGroup>
</Field>
<Toaster toasterId={toasterId}/>
<Button onClick={() => notify()}>Make toast</Button>
</>);
};
export default Intent;
Inverted Appearance
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { ToastBody } from "@coreai-ds/react-components";
import { ToastFooter } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
export const InvertedAppearance = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast appearance="inverted">
<ToastTitle action={<Link>Undo</Link>}>Email sent</ToastTitle>
<ToastBody subtitle="Subtitle">This is a toast body</ToastBody>
<ToastFooter>
<Link>Action</Link>
<Link>Action</Link>
</ToastFooter>
</Toast>, { intent: 'success' });
return (<>
<Toaster toasterId={toasterId}/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default InvertedAppearance;
Multiple Toasters
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import * as React from 'react';
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
export const MultipleToasters = (): JSXElement => {
const first = useId('toaster-1');
const second = useId('toaster-2');
const [toaster, setToaster] = React.useState(first);
const { dispatchToast: dispatchFirstToast } = useToastController(first);
const { dispatchToast: dispatchSecondToast } = useToastController(second);
const notify = () => {
if (toaster === first) {
dispatchFirstToast(<Toast>
<ToastTitle>First toaster</ToastTitle>
</Toast>, { intent: 'info' });
}
else {
dispatchSecondToast(<Toast>
<ToastTitle>Second toaster</ToastTitle>
</Toast>, { intent: 'info' });
}
};
return (<>
<Field label="Choose toaster">
<RadioGroup value={toaster} onChange={(e, data) => setToaster(data.value)}>
<Radio label="First toaster" value={first}/>
<Radio label="Second toaster" value={second}/>
</RadioGroup>
</Field>
<Toaster toasterId={first} position="bottom-end"/>
<Toaster toasterId={second} position="top-end"/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default MultipleToasters;
Offset
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ToastPosition } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { SpinButton } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
const useStyles = makeStyles({
playground: {
display: 'grid',
gridTemplateColumns: '25% 75%',
columnGap: '20px',
rowGap: '20px',
},
horizontal: {
gridColumnEnd: 2,
},
vertical: {
gridRowStart: 2,
gridColumnEnd: 2,
},
positions: {
gridRowStart: 1,
gridRowEnd: 3,
gridColumnStart: 2,
},
});
export const Offset = (): JSXElement => {
const styles = useStyles();
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const [horizontal, setHorizontal] = React.useState(20);
const [vertical, setVertical] = React.useState(16);
const [position, setPosition] = React.useState<ToastPosition>('bottom-end');
const notify = () => dispatchToast(<Toast>
<ToastTitle>
Offset: {horizontal}, {vertical}
</ToastTitle>
</Toast>, { position, intent: 'info' });
return (<>
<div className={styles.playground}>
<Field label="Horizontal offset" className={styles.horizontal}>
<SpinButton value={horizontal} onChange={(e, data) => {
if (data.value) {
setHorizontal(data.value);
}
else if (data.displayValue !== undefined) {
const newValue = parseFloat(data.displayValue);
if (!Number.isNaN(newValue)) {
setHorizontal(newValue);
}
}
}}/>
</Field>
<Field label="Vertical offset" className={styles.vertical}>
<SpinButton value={vertical} onChange={(e, data) => {
if (data.value) {
setVertical(data.value);
}
else if (data.displayValue !== undefined) {
const newValue = parseFloat(data.displayValue);
if (!Number.isNaN(newValue)) {
setVertical(newValue);
}
}
}}/>
</Field>
<Field label="Toast position" className={styles.positions}>
<RadioGroup value={position} onChange={(e, data) => setPosition(data.value as ToastPosition)}>
<Radio label="bottom" value="bottom"/>
<Radio label="bottom-start" value="bottom-start"/>
<Radio label="bottom-end" value="bottom-end"/>
<Radio label="top" value="top"/>
<Radio label="top-start" value="top-start"/>
<Radio label="top-end" value="top-end"/>
</RadioGroup>
</Field>
</div>
<br />
<Button onClick={() => notify()}>Make toast</Button>
<Toaster toasterId={toasterId} offset={{ horizontal, vertical }}/>
</>);
};
export default Offset;
Pause And Play
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import * as React from 'react';
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { ToggleButton } from "@coreai-ds/react-components";
import { PlayFilled } from "@fluentui/react-icons";
import { PauseFilled } from "@fluentui/react-icons";
export const PauseAndPlay = (): JSXElement => {
const toasterId = useId('toaster');
const toastId = useId('example');
const [unmounted, setUnmounted] = React.useState(true);
const [paused, setPaused] = React.useState(false);
const { pauseToast, playToast, dispatchToast } = useToastController(toasterId);
const notify = () => {
dispatchToast(<Toast>
<ToastTitle>This is a toast</ToastTitle>
</Toast>, {
toastId,
intent: 'success',
onStatusChange: (e, { status }) => {
setUnmounted(status === 'unmounted');
setPaused(false);
},
});
setUnmounted(false);
};
const toggle = () => {
if (paused) {
playToast(toastId);
setPaused(false);
}
else {
pauseToast(toastId);
setPaused(true);
}
};
return (<>
<Toaster toasterId={toasterId}/>
<Button disabledFocusable={!unmounted} onClick={notify}>
Make toast
</Button>
<ToggleButton icon={paused ? <PlayFilled /> : <PauseFilled />} disabledFocusable={unmounted} onClick={toggle} checked={paused}>
{paused ? 'Play' : 'Pause'} toast
</ToggleButton>
</>);
};
export default PauseAndPlay;
Pause On Hover
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
export const PauseOnHover = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast>
<ToastTitle>Hover me!</ToastTitle>
</Toast>, { pauseOnHover: true, intent: 'info' });
return (<>
<Toaster toasterId={toasterId}/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default PauseOnHover;
Pause On Window Blur
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import * as React from 'react';
export const PauseOnWindowBlur = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const notify = () => dispatchToast(<Toast>
<ToastTitle>Click on another window!</ToastTitle>
</Toast>, { pauseOnWindowBlur: true, intent: 'info' });
return (<>
<Toaster toasterId={toasterId}/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default PauseOnWindowBlur;
Progress Toast
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import * as React from 'react';
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { ToastTrigger } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { ToastBody } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { ProgressBar } from "@coreai-ds/react-components";
import { ToastFooter } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
const intervalIncrement = 5;
const intervalDelay = 100;
const DownloadProgressBar: React.FC<{
onDownloadEnd: () => void;
}> = ({ onDownloadEnd }) => {
const [value, setValue] = React.useState(100);
// This effect simulates progress value based on state/remote data
React.useEffect(() => {
if (value > 0) {
const timeout = setTimeout(() => {
setValue(v => Math.max(v - intervalIncrement, 0));
}, intervalDelay);
return () => clearTimeout(timeout);
}
if (value === 0) {
onDownloadEnd();
}
}, [value, onDownloadEnd]);
return <ProgressBar value={value} max={100}/>;
};
export const ProgressToast = (): JSXElement => {
const toasterId = useId('toaster');
const toastId = useId('toast');
const [unmounted, setUnmounted] = React.useState(true);
const { dispatchToast, dismissToast } = useToastController(toasterId);
const dismiss = React.useCallback(() => dismissToast(toastId), [dismissToast, toastId]);
const notify = () => dispatchToast(<Toast>
<ToastTitle action={<ToastTrigger>
<Link>Dismiss</Link>
</ToastTrigger>}>
Downloading file
</ToastTitle>
<ToastBody>
<Text>This may take a while</Text>
<DownloadProgressBar onDownloadEnd={dismiss}/>
</ToastBody>
<ToastFooter>
<Link>Action</Link>
<Link>Action</Link>
</ToastFooter>
</Toast>, {
intent: 'success',
timeout: -1,
toastId,
onStatusChange: (e, { status }) => setUnmounted(status === 'unmounted'),
});
return (<>
<Toaster toasterId={toasterId}/>
<Button disabledFocusable={!unmounted} onClick={notify}>
Make toast
</Button>
</>);
};
export default ProgressToast;
Toast Lifecycle
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { makeStyles } from "@coreai-ds/react-components";
import { tokens } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ToastStatus } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Link } from "@coreai-ds/react-components";
import { ToastBody } from "@coreai-ds/react-components";
import { ToastFooter } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
import { Text } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
const useStyles = makeStyles({
root: {
display: 'flex',
gap: '20px',
},
button: {
display: 'block',
},
logContainer: {
display: 'flex',
flexDirection: 'column',
},
logLabel: {
color: tokens.colorNeutralForegroundOnBrand,
backgroundColor: tokens.colorBrandBackground,
width: 'fit-content',
fontWeight: tokens.fontWeightBold,
padding: '2px 12px',
},
log: {
overflowY: 'auto',
boxShadow: tokens.shadow16,
position: 'relative',
minWidth: '200px',
height: '200px',
border: `2px solid ${tokens.colorBrandBackground}`,
padding: '12px',
},
});
export const ToastLifecycle = (): JSXElement => {
const styles = useStyles();
const toasterId = useId('toaster');
const labelId = useId();
const { dispatchToast } = useToastController(toasterId);
const [statusLog, setStatusLog] = React.useState<[
number,
ToastStatus
][]>([]);
const [dismissed, setDismissed] = React.useState(true);
const notify = () => {
dispatchToast(<Toast>
<ToastTitle action={<Link>Undo</Link>}>Email sent</ToastTitle>
<ToastBody subtitle="Subtitle">This is a toast body</ToastBody>
<ToastFooter>
<Link>Action</Link>
<Link>Action</Link>
</ToastFooter>
</Toast>, {
timeout: 1000,
intent: 'success',
onStatusChange: (e, { status: toastStatus }) => {
setDismissed(toastStatus === 'unmounted');
setStatusLog(prev => [[Date.now(), toastStatus], ...prev]);
},
});
};
return (<>
<div className={styles.root}>
<div>
<Button className={styles.button} disabledFocusable={!dismissed} onClick={notify}>
Make toast
</Button>
<Button className={styles.button} onClick={() => setStatusLog([])}>
Clear log
</Button>
</div>
<div className={styles.logContainer}>
<div className={styles.logLabel} id={labelId}>
Status log
</div>
<div role="log" aria-labelledby={labelId} className={styles.log}>
{statusLog.map(([time, toastStatus], i) => {
const date = new Date(time);
return (<div key={i}>
{date.toLocaleTimeString()} <Text weight="bold">{toastStatus}</Text>
</div>);
})}
</div>
</div>
</div>
<Toaster toasterId={toasterId}/>
</>);
};
export default ToastLifecycle;
Toast Positions
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import * as React from 'react';
import type { ToastPosition } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { RadioGroup } from "@coreai-ds/react-components";
import { Radio } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
export const ToastPositions = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const [position, setPosition] = React.useState<ToastPosition>('top');
const notify = () => dispatchToast(<Toast>
<ToastTitle>This toast is {position}</ToastTitle>
</Toast>, { position, intent: 'success' });
return (<>
<Field label="Select a position">
<RadioGroup value={position} onChange={(e, data) => setPosition(data.value as ToastPosition)}>
<Radio label="bottom" value="bottom"/>
<Radio label="bottom-start" value="bottom-start"/>
<Radio label="bottom-end" value="bottom-end"/>
<Radio label="top" value="top"/>
<Radio label="top-start" value="top-start"/>
<Radio label="top-end" value="top-end"/>
</RadioGroup>
</Field>
<Toaster toasterId={toasterId}/>
<Button onClick={() => notify()}>Make toast</Button>
</>);
};
export default ToastPositions;
Toaster Limit
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import { useToastController } from "@coreai-ds/react-components";
import * as React from 'react';
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Field } from "@coreai-ds/react-components";
import { SpinButton } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
export const ToasterLimit = (): JSXElement => {
const toasterId = useId('toaster');
const { dispatchToast } = useToastController(toasterId);
const [limit, setLimit] = React.useState(3);
const notify = () => dispatchToast(<Toast>
<ToastTitle>Limited to 3 toasts</ToastTitle>
</Toast>, { intent: 'success' });
return (<>
<Field label="Toaster Limit">
<SpinButton value={limit} onChange={(e, data) => {
if (data.value) {
setLimit(data.value);
}
else if (data.displayValue !== undefined) {
const newValue = parseFloat(data.displayValue);
if (!Number.isNaN(newValue)) {
setLimit(newValue);
}
}
}}/>
</Field>
<br />
<Toaster toasterId={toasterId} limit={limit}/>
<Button onClick={notify}>Make toast</Button>
</>);
};
export default ToasterLimit;
Update Toast
Loading interactive example. Full source is available below.
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import type { JSXElement } from "@coreai-ds/react-components";
import { useId } from "@coreai-ds/react-components";
import * as React from 'react';
import { useToastController } from "@coreai-ds/react-components";
import { Toast } from "@coreai-ds/react-components";
import { ToastTitle } from "@coreai-ds/react-components";
import { Toaster } from "@coreai-ds/react-components";
import { Button } from "@coreai-ds/react-components";
export const UpdateToast = (): JSXElement => {
const toastId = useId('toast');
const toasterId = useId('toaster');
const [unmounted, setUnmounted] = React.useState(true);
const { dispatchToast, updateToast } = useToastController(toasterId);
const notify = () => {
dispatchToast(<Toast>
<ToastTitle>This toast never closes</ToastTitle>
</Toast>, {
toastId,
intent: 'warning',
timeout: -1,
onStatusChange: (e, { status }) => setUnmounted(status === 'unmounted'),
});
setUnmounted(false);
};
const update = () => updateToast({
content: (<Toast>
<ToastTitle>This toast will close soon</ToastTitle>
</Toast>),
intent: 'success',
toastId,
timeout: 2000,
});
return (<>
<Toaster toasterId={toasterId}/>
<Button onClick={unmounted ? notify : update}>{unmounted ? 'Make toast' : 'Update toast'}</Button>
</>);
};
export default UpdateToast;