stream-chat-react
stream-chat-react copied to clipboard
feat: new MessageActions component
The Problem(s)
MessageActions/MessageOptions/MessageActionsBox are a poorly designed set of components which we were trying to patch over the time with things like CustomMessageActionsList but with each new patchy addition, the component set got heavier and worse to navigate in when it came to customization.
messageActionsprop onMessageListandVirtualizedMessageListcomponents allow for key/handler customization:
Solution like this falls face first when integrators need to access{ "Custom Action": () => doThing() }MessageContextor use translations for different languages (the key is used as button text).- Solution to patch those shortcomings was to introduce
CustomMessageActionsListwhich allows to render custom buttons within actions dropdown but... when buttons are rendered conditionally, the "..." is still rendered and upon clicking on it, it opens up an empty actions dropdown. This solution also does not allow to adjust "quick actions" (like reply or react).
Steps Taken
- pre-define default set of actions with buttons as components with own logic and click handlers, separate into "quick" and "dropdown" types
- define default filter which takes care of user capabilities and whether the actions are allowed within reply type of a message (and some other stuff based on message type or status)
- allow integrators to override the default set and to override the default filter function, alow reusing defaults too
access action set -> filter action set based on filter function criteria -> separate into quick and dropdown -> render
From Integrator's POV
import { Channel, MessageActions_UNSTABLE } from 'stream-chat-react';
const {
MessageActions,
defaultMessageActionSet,
DefaultDropdownActionButton,
} = MessageActions_UNSTABLE;
const CustomMessageActions = () => {
const customFilter = () => {
/*...*/
};
return (
<MessageActions
// though not recommended, it's completely possible to disable default filter...
disableBaseMessageActionSetFilter
messageActionSet={[
...defaultMessageActionSet,
{
type: 'myCustomTypeDropdown',
placement: 'dropdown',
// we can enforce non-null return type (at least through TS)
Component: () => <DefaultDropdownActionButton>🚀 Custom</DefaultDropdownActionButton>,
},
{
type: 'myCustomTypeQuick',
placement: 'quick',
Component: () => <button>a</button>,
},
// ...and apply custom filter here with access to CustomMessageActions scope (contexts + other hooks)
].filter(customFilter)}
/>
);
};
<Channel MessageOptions={CustomMessageActions}>...</Channel>;
Next Steps
- [ ] review and beta release
- [ ] allow overriding certain components within default
MessageActions_UNSTABLE - [ ] tests