import { useCallback, useState } from "react";
import { GlobalModal } from "stream-chat-react";
const Example = () => {
const [open, setOpen] = useState(false);
const closeModal = useCallback(() => setOpen(false), []);
return (
<>
<button onClick={() => setOpen(true)}>Open modal</button>
<GlobalModal onClose={closeModal} open={open}>
<div className="custom-modal-body">Custom content</div>
</GlobalModal>
</>
);
};Modal
GlobalModal is the public modal component in the React SDK. It renders through the chat-level modal dialog manager provided by Chat.
Best Practices
- Use
GlobalModalfor app-owned modals rendered inside the chat tree. - Use
WithComponentsto override SDK-owned modal surfaces such as delete dialogs, poll dialogs, or selector dialogs. - Keep modal content lightweight and controlled by a single
openstate. - Use
onCloseAttemptwhen overlay or escape dismissal should be blocked.
Basic Usage
SDK Modal Overrides
SDK surfaces that open modal content use the shared Modal override from ComponentContext. To change that behavior across a subtree, register a compatible modal component with WithComponents.
import {
Channel,
GlobalModal,
MessageComposer,
WithComponents,
} from "stream-chat-react";
import type { ModalProps } from "stream-chat-react";
const CustomModal = (props: ModalProps) => (
<GlobalModal {...props} className="custom-modal-shell" />
);
const App = () => (
<WithComponents overrides={{ Modal: CustomModal }}>
<Channel>
<MessageComposer />
</Channel>
</WithComponents>
);Props
| Prop | Description | Type |
|---|---|---|
children | Modal contents. | ReactNode |
className | Additional class name for the modal overlay root. | string |
CloseButtonOnOverlay | Optional close-button component rendered on the overlay layer. | React.ComponentType<ComponentProps<"button">> |
onClose | Called when the modal should close. Your handler should update open. ModalCloseEvent is KeyboardEvent | React.KeyboardEvent | React.MouseEvent<HTMLButtonElement | HTMLDivElement>. | (event: ModalCloseEvent) => void |
onCloseAttempt | Intercepts close attempts. Return false to keep the modal open. ModalCloseSource is "overlay" | "button" | "escape". | (source: ModalCloseSource, event: ModalCloseEvent) => boolean |
open | Controls whether the modal is rendered. Defaults to false. | boolean |
Examples
Intercept close attempts
import { GlobalModal } from "stream-chat-react";
import type { ModalCloseSource, ModalProps } from "stream-chat-react";
const onCloseAttempt = (source: ModalCloseSource) => source !== "overlay";
const ConfirmingModal = (props: ModalProps) => (
<GlobalModal {...props} onCloseAttempt={onCloseAttempt} />
);