import { GlobalModal } from "stream-chat-react";
const Component = () => <Channel Modal={GlobalModal}></Channel>;Modal
The SDK exports two modal components:
Modal(legacy)GlobalModal(introduced with stream-chat-react@13.6.0)
Best Practices
- Prefer
GlobalModalto avoid clipping in complex layouts. - Keep modal content lightweight to prevent scroll jank.
- Use
onCloseAttemptto enforce confirmation flows when needed. - Ensure
openstate is controlled by a single source of truth. - Verify keyboard and overlay close behavior for accessibility.
Modals use position: fixed. The legacy Modal renders deep in the tree (for example under Message), which in Safari can cause clipping if a parent uses position: relative. To avoid this, use GlobalModal, which renders at the top of the SDK tree.
By default, the SDK uses Modal. Opt in to GlobalModal by passing it to the Channel Modal prop:
Modal props
Both modals accept the same props.
children
The children prop is used to render the modal content.
import { useCallback, useState } from "react";
const Component = ({ image }) => {
const [modalIsOpen, setModalIsOpen] = useState(false);
const closeModal = useCallback(() => {
setModalIsOpen(false);
}, []);
return (
<>
<button onClick={() => setModalIsOpen(true)}>Open gallery</button>
<Modal
className="str-chat__image-modal"
onClose={closeModal}
open={modalIsOpen}
>
<ModalGallery images={[image]} index={0} />
</Modal>
</>
);
};open
Flag to determine whether the modal and its content is rendered.
| Type | Default |
|---|---|
boolean | false |
className
Class attached to the modal overlay div with default class str-chat__modal.
| Type |
|---|
string |
onClose
onClose should update open to hide the modal (typically set to false).
| Type |
|---|
(event: ModalCloseEvent) => void |
Where ModalCloseEvent is defined as follows:
export type ModalCloseEvent =
| KeyboardEvent
| React.KeyboardEvent
| React.MouseEvent<HTMLButtonElement | HTMLDivElement>;onCloseAttempt
Optional handler to intercept closing logic. Return false to prevent onClose. onCloseAttempt recognizes:
overlay- click on overlaybutton- click on close buttonescape- pressingEscapekey
By default, modals are closed upon interacting with all the above sources.
import type { ModalCloseSource, ModalProps } from "stream-chat-react";
import { Channel, GlobalModal } from "stream-chat-react";
// click on overlay will not result in closing the modal
const onCloseAttempt: (source: ModalCloseSource) => boolean = (source) =>
source !== "overlay";
const GlobalModalWrapper = (props: ModalProps) => {
return <GlobalModal {...props} onCloseAttempt={onCloseAttempt} />;
};
const Component = () => (
<Channel Modal={GlobalModalWrapper}>{/* children*/}</Channel>
);| Type |
|---|
(source: ModalCloseSource, event: ModalCloseEvent) => boolean |