diff --git a/src/components/Toaster/README.md b/src/components/Toaster/README.md index c56f348e37..f4b8de7990 100644 --- a/src/components/Toaster/README.md +++ b/src/components/Toaster/README.md @@ -125,6 +125,7 @@ Accepts the argument `toastOptions` with ongoing notification details: | isClosable | `boolean` | | `true` | A configuration that manages the visibility of the X icon, which allows the user to close the notification | | actions | `ToastAction[]` | | `undefined` | An array of [actions](./types.ts#L9) that display after `content` | | renderIcon | `(toastProps: ToastProps) => ReactNode` | | `undefined` | Used to customize the toast icon. Type-based behavior is used by default | +| onClose | `() => void` | | `undefined` | Callback which calls when close button is clicked | Every `action` is an object with following parameters: diff --git a/src/components/Toaster/Toast/Toast.tsx b/src/components/Toaster/Toast/Toast.tsx index c385392653..539e4e70b5 100644 --- a/src/components/Toaster/Toast/Toast.tsx +++ b/src/components/Toaster/Toast/Toast.tsx @@ -94,12 +94,19 @@ export const Toast = React.forwardRef(function autoHiding: timeoutProp = DEFAULT_TIMEOUT, isClosable = true, mobile = false, + onClose, removeCallback, } = props; - const onClose = React.useCallback(() => removeCallback(name), [removeCallback, name]); + const handleClose = React.useCallback(() => { + removeCallback(name); + + if (onClose) { + onClose(); + } + }, [removeCallback, onClose, name]); const timeout = typeof timeoutProp === 'number' ? timeoutProp : undefined; - const closeOnTimeoutProps = useCloseOnTimeout({onClose, timeout}); + const closeOnTimeoutProps = useCloseOnTimeout({onClose: handleClose, timeout}); const mods = { mobile, @@ -120,7 +127,7 @@ export const Toast = React.forwardRef(function size="s" view="flat" className={b('btn-close')} - onClick={onClose} + onClick={handleClose} extraProps={{'aria-label': i18n('label_close-button')}} > @@ -129,7 +136,7 @@ export const Toast = React.forwardRef(function {hasContent && (
{content}
)} - {renderActions({actions, onClose})} + {renderActions({actions, onClose: handleClose})} ); diff --git a/src/components/Toaster/__tests__/ToasterProvider.test.tsx b/src/components/Toaster/__tests__/ToasterProvider.test.tsx index 0e99a42b13..78494ae8e2 100644 --- a/src/components/Toaster/__tests__/ToasterProvider.test.tsx +++ b/src/components/Toaster/__tests__/ToasterProvider.test.tsx @@ -409,4 +409,23 @@ describe('modal remains open after toaster close', () => { expect(toast).not.toBeInTheDocument(); expect(modal).toBeInTheDocument(); }); + + it('Toaster calls onClose callback when close icon is clicked', async () => { + const {providerAPI} = setup(); + + const mockOnCloseFn = jest.fn(); + + act(() => { + providerAPI.add({...toastProps, isClosable: true, onClose: mockOnCloseFn}); + }); + + const toast = getToast(); + + const closeToastButton = await within(toast).findByRole('button'); + + fireEvent.click(closeToastButton); + tick(toast, 0); + + expect(mockOnCloseFn).toHaveBeenCalled(); + }); }); diff --git a/src/components/Toaster/types.ts b/src/components/Toaster/types.ts index 5beb50758e..3161e05f22 100644 --- a/src/components/Toaster/types.ts +++ b/src/components/Toaster/types.ts @@ -26,6 +26,8 @@ export type ToastProps = { isClosable?: boolean; actions?: ToastAction[]; + onClose?: () => void; + /** Function. Use for toast icon customization. By default type-based behavior is used */ renderIcon?: (toastProps: ToastProps) => React.ReactNode; };