-
Notifications
You must be signed in to change notification settings - Fork 278
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add centralized dialog management (#2489)
BREAKING CHANGE: - removes the following variables from `MessageContext`: isReactionEnabled, onReactionListClick, showDetailedReactions, reactionSelectorRef - removes prop `messageWrapperRef` from `MessageOptions` and `MessageActions` props.
- Loading branch information
1 parent
9fa4806
commit 8235d45
Showing
56 changed files
with
1,768 additions
and
1,228 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
--- | ||
id: dialog-management | ||
title: 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`: | ||
|
||
```tsx | ||
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. | ||
|
||
```tsx | ||
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`. | ||
|
||
```tsx | ||
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`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.