Skip to main content
Version: v5

SelectedReactionsMenu

The SelectedReactionsMenu is a component that displays a list of message reactions with the users who left them. If a message already contains reactions, the user can tap on the section with reactions to show the component.

This is a stateless component which you can easily add to your UI if you're building a custom Messages screen. The component shows the following UI:

  • Reaction options: The top part which shows a list of reactions the user can use to react to the message.
  • User reactions: The main part which shows a list of users with their reactions left for the message.

Let's see how to use the component.

Usage

If you're using the MessagesScreen component, the SelectedReactionsMenu component is already set up for you. To use the SelectedReactionsMenu component in your custom screens, simply add it to your UI, like so:

// The rest of your UI
if (selectedMessageState is SelectedMessageReactionsState) {
val selectedMessage = selectedMessageState.message
SelectedReactionsMenu(
modifier = Modifier.align(Alignment.BottomCenter),
// The currently logged-in user
currentUser = user,
// The capabilities the user has in a given channel
ownCapabilities = selectedMessageState.ownCapabilities,
// The message whose reactions you selected
message = selectedMessage,
onMessageAction = { action ->
// Handle message action
},
onShowMoreReactionsSelected = {
// Handle show more reactions button click
},
onDismiss = {
// Handle dismiss
}
)
}

As you can see, showing the menu is very simple. If the selectedMessageState is an instance of SelectedMessageReactionsState, you pass in the currently logged in user, as well as the selected message. The reactions you show are taken from the ChatTheme component and everything else required to show the component is taken care of internally.

The aforementioned code produces the following UI:

Default SelectedReactionsMenu component

The component shows the available reactions from the ChatTheme on the top, followed by a list of message reactions.

To dismiss the component just tap outside of the dialog or press the system back button.

Handling Actions

Here are the actions exposed by the SelectedReactionsMenu component:

@Composable
fun SelectedReactionsMenu(
..., // State
onMessageAction: (MessageAction) -> Unit,
onShowMoreReactionsSelected: () -> Unit,
onDismiss: () -> Unit = {},
)
  • onMessageAction: Handler used when the user performs an action such as leaving a reaction.
  • onShowMoreReactionsSelected: Handler that propagates clicks on the show more reactions button.
  • onDismiss: Handler used when the menu is dismissed by clicking outside of the dialog area or by pressing the system back button.

To handle these actions, you can override them like so:

if (selectedMessageState is SelectedMessageReactionsState) {
SelectedReactionsMenu(
..., // State
onMessageAction = { action ->
composerViewModel.performMessageAction(action)
listViewModel.performMessageAction(action)
},
onShowMoreReactionsSelected = {
listViewModel.selectExtendedReactions(selectedMessage)
},
onDismiss = { listViewModel.removeOverlay() }
)
}

In the snippet above, you propagate the action to the composerViewModel and listViewModel, for them to store the latest action. This will update the UI accordingly.

Alternatively, you call listViewModel.removeOverlay() to remove the overlay from the screen in onDismiss(). It's important to note that onMessageAction() calls removeOverlay() internally to hide the overlay.

Next, let's see how to customize the overlay.

Customization

You can customize the reactions you show:

@Composable
fun SelectedReactionsMenu(
..., // State
modifier: Modifier = Modifier,
shape: Shape = ChatTheme.shapes.bottomSheet,
overlayColor: Color = ChatTheme.colors.overlay,
reactionTypes: Map<String, ReactionIcon> = ChatTheme.reactionIconFactory.createReactionIcons(),
@DrawableRes showMoreReactionsIcon: Int = R.drawable.stream_compose_ic_more,
... // Actions and Slot APIs
)
  • modifier: Modifier for the dialog component.
  • overlayColor: Allows you to customize the color of the overlay.
  • shape: Allows you to customize the shape of the dialog.
  • reactionTypes: Allows you to customize reactions shown in the overlay. By default it uses ChatTheme.reactionIconFactory which is exposed by the ChatTheme component.
  • showMoreReactionsIcon: Allows you to customize the show more reactions icon. By default, the icon will appear when ChatTheme.reactionIconFactory provides more than five reactions.

The best way to customize reactions is by overriding ChatTheme.reactionIconFactory with your own implementation of ReactionIconFactory so that all of your components wrapped inside of ChatTheme draw from the same source.

By default SelectedReactionsMenu looks like a bottom sheet, however you can customize it to look like a completely different component, such as a dialog, a drawer or whatever helps you retain the look and feel of your app.

if (selectedMessageState is SelectedMessageReactionsState) {
// Use a Modifier to customize the appearance
SelectedReactionsMenu(
..., // State
// Use a Modifier to customize the appearance
modifier = Modifier
.align(Alignment.Center)
.padding(horizontal = 20.dp)
.wrapContentSize(),
// Assign a different shape to the Composable element
shape = ChatTheme.shapes.attachment,
currentUser = user,
onMessageAction = { action ->
// Handle message action
},
onDismiss = {
// Handle dismiss
},
...
)
}

The code above will produce the following UI:

Custom SelectedReactionsMenu component

SelectedReactionsMenu provides you with Composable slots that are ready for more extensive customizations.

@Composable
fun SelectedReactionsMenu(
...,
headerContent: @Composable ColumnScope.() -> Unit = {
// Header content
},
centerContent: @Composable ColumnScope.() -> Unit = {
// Center content
}
)
  • headerContent: Allows you to customize the content shown at the top of the menu. By default it shows reaction options.
  • centerContent: Allows you to customize the content shown at the center of the menu. By default it shows user reactions.

You can easily override either slot:

if (selectedMessageState is SelectedMessageReactionsState) {
SelectedReactionsMenu(
...,
// Custom header content
headerContent = {
Text(
modifier = Modifier
.padding(16.dp)
.background(
shape = ChatTheme.shapes.avatar,
color = ChatTheme.colors.infoAccent
)
.padding(horizontal = 8.dp),
style = ChatTheme.typography.body,
color = ChatTheme.colors.textHighEmphasis,
text = "User Reactions"
)
}
)
}

The example above shows how to replace the header content with a custom Text.

The result looks like this:

Custom SelectedReactionsMenu component with a custom header content

Did you find this page helpful?