-
Notifications
You must be signed in to change notification settings - Fork 273
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8174682
commit 0cf5482
Showing
14 changed files
with
324 additions
and
8 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+169 KB
docusaurus/docs/React/assets/dashboard-channel-type-feature-configuration-ui.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
194 changes: 194 additions & 0 deletions
194
docusaurus/docs/React/components/message-components/poll.mdx
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,194 @@ | ||
--- | ||
id: poll | ||
title: Poll | ||
--- | ||
|
||
Messages can contain polls. Polls are by default created using `PollCreationDialog` that is invoked from [`AttachmentSelector`](../../message-input-components/attachment-selector). Messages that render polls are not editable. Polls can be only closed by the poll creator. The top-level component to render the message poll data is `Poll` and it renders a header followed by option list and poll actions section. | ||
|
||
![](../../assets/message-with-poll.png) | ||
|
||
## Poll UI customization | ||
|
||
The following part of the poll UI can be customized: | ||
|
||
- `QuotedPoll` - UI rendered if the poll is rendered in a quoted message | ||
- `PollContent` - component that renders the whole non-quoted poll UI | ||
- `PollHeader` - customizes the topmost part of the poll UI | ||
- `PollOptionSelector` - customizes the individual clickable option selectors | ||
- `PollActions` - customizes the bottom part of the poll UI that consists of buttons that invoke action dialogs | ||
|
||
### Poll header customization | ||
|
||
```tsx | ||
import { ReactNode } from 'react'; | ||
import { Channel } from 'stream-chat-react'; | ||
|
||
const PollHeader = () => <div>Custom Header</div>; | ||
|
||
const ChannelWrapper = ({ children }: { children: ReactNode }) => ( | ||
<Channel PollHeader={PollHeader}>{children}</Channel> | ||
); | ||
``` | ||
|
||
### Poll option selector customization | ||
|
||
If we wanted to customize only the option selector we can do it with custom `PollOptionSelector` component. | ||
|
||
```tsx | ||
import { ReactNode } from 'react'; | ||
import { Channel } from 'stream-chat-react'; | ||
|
||
const PollOptionSelector = () => <div>Custom Option Selector</div>; | ||
|
||
const ChannelWrapper = ({ children }: { children: ReactNode }) => ( | ||
<Channel PollOptionSelector={PollOptionSelector}>{children}</Channel> | ||
); | ||
``` | ||
|
||
### Poll actions customization | ||
|
||
The component `PollActions` controls the display of dialogs or modals that allow user to further interact with the poll data. There are the following poll actions supported by the component that invoke corresponding dialogs resp. modals: | ||
|
||
| Action button | Visible condition | Invokes | | ||
| ------------------------- | ----------------------------------------------------------------------------------------- | ----------------------- | | ||
| See all options | option count > 10 | `PollOptionsFullList` | | ||
| Suggest an option | poll is not closed and `poll.allow_user_suggested_options === true` | `SuggestPollOptionForm` | | ||
| Add or update own comment | poll is not closed and `poll.allow_answers === true` | `AddCommentForm` | | ||
| View comments | `channel.own_capabilities` array contains `'query-poll-votes'` & `poll.answers_count > 0` | `PollAnswerList` | | ||
| View results | always visible | `PollResults` | | ||
| End vote | owner of the poll | `EndPollDialog` | | ||
|
||
**Default PollOptionsFullList** | ||
|
||
![](../../assets/poll-option-full-list.png) | ||
|
||
**Default SuggestPollOptionForm** | ||
|
||
![](../../assets/suggest-poll-option-form.png) | ||
|
||
**Default AddCommentForm** | ||
|
||
![](../../assets/add-poll-comment-form.png) | ||
|
||
**Default PollAnswerList** | ||
|
||
![](../../assets/poll-comment-list.png) | ||
|
||
**Default PollResults** | ||
|
||
![](../../assets/poll-results.png) | ||
|
||
**Default EndPollDialog** | ||
|
||
![](../../assets/end-poll-dialog.png) | ||
|
||
Individual dialogs and thus the whole `PollActions` component can be overridden via `PollActions` component props as follows: | ||
|
||
```tsx | ||
import { ReactNode } from 'react'; | ||
import { Channel, PollActions } from 'stream-chat-react'; | ||
import { | ||
CustomAddCommentForm, | ||
CustomEndPollDialog, | ||
CustomPollAnswerList, | ||
CustomPollOptionsFullList, | ||
CustomPollResults, | ||
CustomSuggestPollOptionForm, | ||
} from './PollActions'; | ||
|
||
const CustomPollActions = () => ( | ||
<PollActions | ||
AddCommentForm={CustomAddCommentForm} | ||
EndPollDialog={CustomEndPollDialog} | ||
PollAnswerList={CustomPollAnswerList} | ||
PollOptionsFullList={CustomPollOptionsFullList} | ||
PollResults={CustomPollResults} | ||
SuggestPollOptionForm={CustomSuggestPollOptionForm} | ||
/> | ||
); | ||
|
||
const ChannelWrapper = ({ children }: { children: ReactNode }) => ( | ||
<Channel PollActions={CustomPollActions}>{children}</Channel> | ||
); | ||
``` | ||
|
||
### Poll contents layout customization | ||
|
||
This approach is useful when we want to change the organization of the poll UI. For the purpose we can provide custom `PollContent` component to `Channel`. | ||
|
||
```tsx | ||
import { ReactNode } from 'react'; | ||
import { Channel } from 'stream-chat-react'; | ||
import { CustomPollHeader, CustomPollOptionList } from './Poll'; | ||
|
||
const PollContents = () => ( | ||
<div> | ||
<CustomPollHeader /> | ||
<CustomPollOptionList /> | ||
</div> | ||
); | ||
|
||
const ChannelWrapper = ({ children }: { children: ReactNode }) => ( | ||
<Channel PollContents={PollContents}>{children}</Channel> | ||
); | ||
``` | ||
|
||
## Poll API and state | ||
|
||
In order to be fully capable to customize the poll UI, we need to learn how to utilize Poll API and later access the reactive poll state. | ||
|
||
First of all, the Poll API is exposed via a `Poll` instance. This instance is provided via React context to all the children of the `Poll` component that is rendered internally by `Message` component. The context can be consumed using `usePollContext` hook: | ||
|
||
```tsx | ||
import { usePollContext } from 'stream-chat-react'; | ||
|
||
const Component = () => { | ||
const { poll } = usePollContext(); | ||
}; | ||
``` | ||
|
||
The `Poll` instance exposes the following methods: | ||
|
||
- `query` - queries the data for a given poll (permission to query polls is required) | ||
- `update` - overwrites the poll data | ||
- `partialUpdate` - overwrites only the given poll data | ||
- `close` - marks the poll as closed (useful for custom `EndPollDialog`) | ||
- `delete` - deletes the poll | ||
- `createOption` - creates a new option for given poll (useful for custom `SuggestPollOptionForm`) | ||
- `updateOption` - updates an option | ||
- `deleteOption` - removes the option from a poll | ||
- `castVote` - casts a vote to a given option (useful for custom `PollOptionSelector`) | ||
- `removeVote` - removes a vote from a given option (useful for custom `PollOptionSelector`) | ||
- `addAnswer` - adds an answer (comment) | ||
- `removeAnswer` - removes an answer (comment) | ||
- `queryAnswers` - queries and paginates answers (useful for custom `PollAnswerList`) | ||
- `queryOptionVotes` - queries and paginates votes for a given option (useful for option detail) | ||
|
||
The poll state can be accessed inside the custom React components using the following pattern | ||
|
||
```tsx | ||
import { usePollContext, useStateStore } from 'stream-chat-react'; | ||
|
||
import type { PollState, PollVote } from 'stream-chat'; | ||
import type { StreamChatGenerics } from './types'; | ||
|
||
type PollStateSelectorReturnValue = { | ||
latest_votes_by_option: Record<string, PollVote<StreamChatGenerics>[]>; | ||
}; | ||
|
||
// 1. Define the selector function that receives the fresh value every time the observed property changes | ||
const pollStateSelector = ( | ||
nextValue: PollState<StreamChatGenerics>, | ||
): PollStateSelectorReturnValue => ({ latest_votes_by_option: nextValue.latest_votes_by_option }); | ||
|
||
const CustomComponent = () => { | ||
// 2. Retrieve the poll instance from the context | ||
const { poll } = usePollContext<StreamChatGenerics>(); | ||
// 3. Use the useStateStore hook to subscribe to updates in the poll state with selector picking out only properties we are interested in | ||
const { latest_votes_by_option } = useStateStore(poll.state, pollStateSelector); | ||
}; | ||
``` | ||
|
||
:::warning | ||
Do not try to access the `poll` data via `message` object available from `MessageContext`. This data is not updated and serve only as a seed, for the `poll` state. | ||
::: |
120 changes: 120 additions & 0 deletions
120
docusaurus/docs/React/components/message-input-components/attachment-selector.mdx
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,120 @@ | ||
--- | ||
id: attachment-selector | ||
title: Attachment Selector | ||
--- | ||
|
||
Messages can be enriched with attachments or polls by default. The `AttachmentSelector` component is a component that allows to select what information is to be attached to a message. The attachment objects are included in `message.attachments` property and represent various file uploads. The poll representation is available via `message.poll` property. | ||
|
||
## Enabling the default attachment selector features | ||
|
||
The configuration is possible via Stream dashboard. File uploads and poll creation can be controlled via | ||
|
||
1. role permissions | ||
|
||
![](../../assets/dashboard-roles-permissions-ui.png) | ||
|
||
2. channel type configuration | ||
|
||
![](../../assets/dashboard-channel-type-feature-configuration-ui.png) | ||
|
||
## File uploads | ||
|
||
Uploads are possible only if both Upload Attachment permission is granted to the user role and channel type Uploads configuration is enabled. | ||
|
||
## Poll creation | ||
|
||
:::note | ||
Polls feature is available in the React SDK as of version 12.5.0 | ||
::: | ||
|
||
Poll creation is enabled only if both Create Poll permission is granted to the user role and channel type Polls configuration is enabled. Poll creation is not possible withing threads. | ||
|
||
### Poll creation UI | ||
|
||
The component in charge of rendering [the poll creation UI is `PollCreationDialog`](https://github.com/GetStream/stream-chat-react/blob/master/src/components/Poll/PollCreationDialog/PollCreationDialog.tsx). The component is rendered in a modal and therefore accepts a prop `close`. | ||
|
||
![](../../assets/poll-creation-dialog.png) | ||
|
||
Custom `PollCreationDialog` can be provided via `Channel` prop `PollCreationDialog`: | ||
|
||
```tsx | ||
import { ReactNode } from 'react'; | ||
import { Channel } from 'stream-chat-react'; | ||
import type { PollCreationDialogProps } from 'stream-chat-react'; | ||
|
||
const CustomPollCreationDialog = ({ close }: PollCreationDialogProps) => ( | ||
<div onClick={close}>Custom Poll Creation Dialog</div> | ||
); | ||
|
||
const ChannelWrapper = ({ children }: { children: ReactNode }) => ( | ||
<Channel PollCreationDialog={CustomPollCreationDialog}>{children}</Channel> | ||
); | ||
``` | ||
|
||
Created poll is then rendered within a message list by [`Poll` component](../../message-components/poll). | ||
|
||
## Attachment selector customization | ||
|
||
### Custom attachment selector actions | ||
|
||
Items in the `AttachementSelector` menu can be customized via its `attachmentSelectorActionSet` prop: | ||
|
||
```tsx | ||
import { ReactNode } from 'react'; | ||
import { AttachmentSelector, Channel, defaultAttachmentSelectorActionSet } from 'stream-chat-react'; | ||
import type { | ||
AttachmentSelectorAction, | ||
AttachmentSelectorActionProps, | ||
AttachmentSelectorModalContentProps, | ||
} from 'stream-chat-react'; | ||
|
||
// Define the menu button | ||
const AddLocationAttachmentAction = ({ | ||
closeMenu, | ||
openModalForAction, | ||
}: AttachmentSelectorActionProps) => ( | ||
<button | ||
onClick={() => { | ||
openModalForAction('addLocation'); | ||
closeMenu(); | ||
}} | ||
> | ||
Location | ||
</button> | ||
); | ||
|
||
// Define the modal contents to be rendered if AddLocationAttachmentAction button is clicked | ||
const AddLocationModalContent = ({ close }: AttachmentSelectorModalContentProps) => { | ||
return <div onClick={close}>abc</div>; | ||
}; | ||
|
||
// the custom action will be at the top of the menu | ||
const attachmentSelectorActionSet: AttachmentSelectorAction[] = [ | ||
{ | ||
ActionButton: AddLocationAttachmentAction, | ||
ModalContent: AddLocationModalContent, | ||
type: 'addLocation', | ||
}, | ||
...defaultAttachmentSelectorActionSet, | ||
]; | ||
|
||
const CustomAttachmentSelector = () => ( | ||
<AttachmentSelector attachmentSelectorActionSet={attachmentSelectorActionSet} /> | ||
); | ||
|
||
const ChannelWrapper = ({ children }: { children: ReactNode }) => ( | ||
<Channel AttachmentSelector={CustomAttachmentSelector}>{children}</Channel> | ||
); | ||
``` | ||
|
||
### Custom modal portal destination | ||
|
||
By default, the modals invoked by clicking on AttachmentSelector menu buttons are anchored to the channel container `div` element. The destination element can be changed by providing `getModalPortalDestination` prop to `AttachmentSelector`. This would be function that would return a reference to the target element that would serve as a parent for the modal. | ||
|
||
```tsx | ||
const getModalPortalDestination = () => document.querySelector<HTMLDivElement>('#my-element-id'); | ||
|
||
const CustomAttachmentSelector = () => ( | ||
<AttachmentSelector getModalPortalDestination={getModalPortalDestination} /> | ||
); | ||
``` |
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