Skip to main content
Version: v12

Dialog Management

This article presents the API the integrators can use to toggle display dialogs in their UIs. The default components that are displayed as dialogs are:

  • ReactionSelector - allows users to post reactions / emojis to a message
  • MessageActionsBox - allows user to select from a list of permitted message actions

The dialog management following this guide is enabled within MessageList and VirtualizedMessageList.

Setup dialog display

There are two actors in the play. The first one is the component that requests the dialog to be closed or open and the other is the component that renders the dialog. We will start with demonstrating how to properly render a component in a dialog.

Rendering a dialog

Component we want to be rendered as a floating dialog should be wrapped inside DialogAnchor:

import React, { ElementRef, useRef } from 'react';
import { DialogAnchor } from 'stream-chat-react';

import { ComponentToDisplayOnDialog } from './ComponentToDisplayOnDialog';
import { generateUniqueId } from './generateUniqueId';

const Container = () => {
// DialogAnchor needs a reference to the element that will toggle the open state. Based on this reference the dialog positioning is calculated
const buttonRef = useRef<ElementRef<'button'>>(null);
// providing the dialog is necessary for the dialog to be retrieved from anywhere in the DialogManagerProviderContext
const dialogId = generateUniqueId();

return (
<>
<DialogAnchor id={dialogId} placement='top' referenceElement={buttonRef.current} trapFocus>
<ComponentToDisplayOnDialog />
</DialogAnchor>
</>
);
};

Controlling a dialog's display

The dialog display is controlled via Dialog API. You can access the API via useDialog() hook.

import React, { ElementRef, useRef } from 'react';
import { DialogAnchor, useDialog, useDialogIsOpen } from 'stream-chat-react';

import { ComponentToDisplayOnDialog } from './ComponentToDisplayOnDialog';
import { generateUniqueId } from './generateUniqueId';

const Container = () => {
const buttonRef = useRef<ElementRef<'button'>>(null);
const dialogId = generateUniqueId();
// access the dialog controller which provides the dialog API
const dialog = useDialog({ id: dialogId });
// subscribe to dialog open state changes
const dialogIsOpen = useDialogIsOpen(dialogId);

return (
<>
<DialogAnchor id={dialogId} placement='top' referenceElement={buttonRef.current} trapFocus>
<ComponentToDisplayOnDialog />
</DialogAnchor>
<button aria-expanded={dialogIsOpen} onClick={dialog.toggleSingle} ref={buttonRef}>
Toggle
</button>
</>
);
};

Dialog API

Dialog can be controlled via Dialog object retrieved using useDialog() hook. The hook returns an object with the following API:

  • dialog.open() - opens the dialog
  • dialog.close() - closes the dialog
  • dialog.toggle() - toggles the dialog open state. Accepts boolean argument closeAll. If enabled closes any other dialog that would be open.
  • dialog.remove() - removes the dialog object reference from the state (primarily for cleanup purposes)

Every Dialog object carries its own id and isOpen flag.

Dialog utility hooks

There are the following utility hooks that can be used to subscribe to state changes or access a given dialog:

  • useDialogIsOpen(id: string) - allows to observe the open state of a particular Dialog instance
  • useDialog({ id }: GetOrCreateDialogParams) - retrieves a dialog object that exposes API to manage it
  • useOpenedDialogCount() - allows to observe changes in the open dialog count

Custom dialog management context

Those who would like to render dialogs outside the MessageList and VirtualizedMessageList, will need to create a dialog management context using DialogManagerProvider.

import { DialogManagerProvider } from 'stream-chat-react';

const Container = () => {
return <DialogManagerProvider id='custom-dialog-manager-id'></DialogManagerProvider>;
};

Now the children of DialogAnchor will be anchored to the parent DialogManagerProvider.

Did you find this page helpful?