---
source_url: https://www.pubnub.com/docs/chat/community-supported/android/message-menu
title: Message menu for PubNub Chat Components for Android
updated_at: 2026-05-22T11:04:00.847Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Message menu for PubNub Chat Components for Android

`MessageMenu` allows you to perform actions on sent messages by long-tapping them. It allows you, for example, to copy a message to the clipboard.

![Message Menu](https://www.pubnub.com/assets/images/android-message-menu-2af1166e2bbc52b9eafd8eec72363b5e.png)

`MessageMenu` uses the concept of [Bottom Sheets](https://material.io/develop/android/components/bottom-sheet-dialog-fragment) from Material Design. By default, the `Copy message` option in `MessageMenu` is enabled, but you can easily [disable](https://www.pubnub.com/docs/chat/community-supported/android/message-menu#disable-message-options) or [override](https://www.pubnub.com/docs/chat/community-supported/android/message-menu#override-message-options) it. `MessageMenu` appears on `BottomMenu` which pops up when you long-tap a message. A single message option available on `MessageMenu` consists of an icon and a text field that provides the name of the option.

## BottomMenu

`MessageMenu` is defined in PubNub Chat Components for Android as part of the `BottomMenu` composable function:

```kotlin
@Composable
fun BottomMenu(
    message: MessageUi.Data?,
    onAction: (MenuAction) -> Unit,
    onDismiss: () -> Unit,
    modifier: Modifier = Modifier,
    visible: Boolean = true,
    states: List<MenuItemState> = message?.let { MenuDefaults.items(message) } ?: emptyList(),
    headerContent: @Composable ColumnScope.() -> Unit = {},
    bodyContent: @Composable ColumnScope.() -> Unit = {
        MessageMenu(items = states, onClick = { onAction(it) })
    },
)
```

| Parameter | Description |
| --- | --- |
| `message` | Reference to the selected message, needed for all action types |
| `onAction` | Global `onClick` handler with `MenuAction` passed |
| `onDismiss` | Action to call after closing or clicking outside of `MessageMenu` |
| `modifier` | Way in which `MessageMenu` is drawn |
| `visible` | Visibility state |
| `states` | List of menu items |
| `headerContent` | Rendering function for the header, empty by default, used for drawing message reactions |
| `bodyContent` | Rendering function for the body, used for `MessageMenu` by default |

`BottomMenu` describes the bottom drawer that pops up on the screen when you long-tap a sent message. The layout of `BottomMenu` itself is split into `headerContent` and `bodyContent`, both of which are modifiable. By default, `headerContent` is empty and must be used to pass [message reactions](https://www.pubnub.com/docs/chat/community-supported/android/message-reactions) while `bodyContent` contains the `MessageMenu` component which specifies options available in `BottomMenu`:

```kotlin
@Composable
fun MessageMenu(
    items: List<MenuItemState>,
    onClick: (MenuAction) -> Unit,
    modifier: Modifier = Modifier,
    content: @Composable ColumnScope.(MenuItemState) -> Unit = { state ->
        MenuItem(
            state = state,
            onClick = onClick,
        )
    }
)
```

Check out a sample usage:

```kotlin
@Composable
fun MessageMenuExample() {
    val items = listOf(
        MenuItemState(
            title = R.string.menu_copy,
            iconPainter = rememberVectorPainter(image = Icons.Rounded.ContentCopy),
            action = Copy(dummyMessageData()),
        ),
        MenuItemState(
            title = R.string.menu_delete,
            iconPainter = rememberVectorPainter(image = Icons.Rounded.Delete),
            action = Delete(dummyMessageData()),
        ),
    )
    MenuItemTheme(DefaultMenuItemTheme) {
        MessageMenu(items = items, onClick = {})
    }
}
```

The `MessageMenu` composable function consists of:

* [items](#items)
* [onClick](#onclick)
* [modifier](#modifier)
* [content](#content)

### Items

`items` stands for the list of menu items referred to in the `MenuItemState` class. This call contains a string resource reference to the `title` of the menu option, `iconPainter` for drawing an icon (you can use either local or remote files), and the type of `action` on which the option is triggered (set to `onClick` by default).

```kotlin
data class MenuItemState(
    @StringRes val title: Int,
    val iconPainter: Painter,
    val action: MenuAction,
)
```

Default values for those parameters are stored in `MenuDefaults` that contains both the default `MessageMenu` options and [message reactions](https://www.pubnub.com/docs/chat/community-supported/android/message-reactions):

```kotlin
object MenuDefaults {
    @Composable
    fun items(message: MessageUi.Data) = listOf(
        MenuItemState(
            title = R.string.menu_copy,
            iconPainter = rememberVectorPainter(image = Icons.Rounded.ContentCopy),
            action = Copy(message),
        ),
    )
```

### onClick

`onClick` stands for the callback handler for selecting an action. It calls `MenuAction` which is a sealed class for defining multiple actions.

```kotlin
sealed class MenuAction(val message: MessageUi.Data)

class Copy(message: MessageUi.Data) : MenuAction(message)
```

### Modifier

`modifier` is an obligatory Compose parameter that defines how the component is drawn. We can use it to define the animation for `BottomMenu`, its position, or its size.

### Content

`content` is a composable function used for rendering a single item (`MenuItem`).

Check out a sample usage:

```kotlin
@Composable
fun MenuItemExample() {
    val message: MessageUi.Data = dummyMessageData()
    MenuItemTheme(DefaultMenuItemTheme) {
        MenuItem(
            MenuItemState(
                title = R.string.menu_copy,
                iconPainter = rememberVectorPainter(image = Icons.Rounded.ContentCopy),
                action = Copy(message),
            )
        )
    }
}
```

## Disable message options

`MessageMenu` with the `Copy message` option is enabled by default. To disable it, replace the `bodyContent` parameter with an empty function:

```kotlin
BottomMenu(
  onAction = { action ->
    onAction(action)
  },
  onDismiss = onDismiss,
  visible = visible && message != null,
  modifier = modifier,
  // Add the below line
  bodyContent = {},
)
```

## Override message options

You can define your own message options to be displayed in `MessageMenu` or replace the existing option with a different one. To add additional options:

1. Define a new MessageMenu option, such as Delete: 1val menuItems = listOf(2 MenuItemState(3 title = R.string.menu_copy,4 iconPainter = rememberVectorPainter(image = Icons.Rounded.ContentCopy),5 action = Copy(message),6 ),7 MenuItemState(8 title = R.string.menu_delete,9 iconPainter = rememberVectorPainter(image = Icons.Rounded.Delete),10 action = Delete(message),11 )12)
2. Pass menuItems in the states parameter to BottomMenu in your app code: 1BottomMenu(2 …3 states = menuItems,4 …5)
3. Consume the new option by overriding the onAction parameter and adding the additional Delete class: 1onAction = { action ->2 when (action) {3 is Copy -> {4 action.message.text?.let { content ->5 messageViewModel.copy(AnnotatedString(content))6 }7 }8 is Delete -> handleDelete(action.customData, action.message)9 is React -> reactionViewModel.reactionSelected(action)10 else -> {}11 }12}

## Theming

As already mentioned, a single `MessageMenu` option (like `Copy message`) is defined by the `MenuItem` composable function that applies the theming outlined in `MenuItemTheme`.

```kotlin
class MenuItemTheme(
    modifier: Modifier = Modifier,
    text: TextTheme,
    icon: IconTheme,
    horizontalArrangement: Arrangement.Horizontal,
    verticalAlignment: Alignment.Vertical,
)
```

Its default implementation looks as follows:

```kotlin
@Composable
fun MenuItem(
    state: MenuItemState,
    onClick: ((MenuAction) -> Unit)? = null,
    theme: MenuItemTheme = LocalMenuItemTheme.current,
) {
    Row(
        modifier = Modifier
            .clickable(
                onClick = { onClick?.invoke(state.action) },
                interactionSource = remember { MutableInteractionSource() },
                indication = rememberRipple(),
            )
            .then(theme.modifier),
        horizontalArrangement = theme.horizontalArrangement,
        verticalAlignment = theme.verticalAlignment,
    ) {
        Icon(
            modifier = theme.icon.modifier,
            painter = state.iconPainter,
            contentDescription = stringResource(id = state.title),
            tint = theme.icon.tint,
        )

        ThemedText(
            text = stringResource(id = state.title),
            theme = theme.text,
            modifier = theme.modifier,
        )
    }
}
```

## Customize parameters

`MenuItemTheme` allows you to customize these parameters for `MessageMenu`:

* Background color of the whole list and a single option
* Text color of an option title
* Icon tint

### Background color of the list

To change the background color of the whole option list to a different one, pass the `modifier` parameter with a selected background color like `Red`:

```kotlin
BottomMenu(
  onAction = { action ->
    onAction(action)
    onDismiss()
  },
  onDismiss = onDismiss,
  visible = visible && message != null,
  // Add the below line
  modifier = Modifier.background(Color.Red),
  ...
)
```

Since in the default implementation there's no padding set to `modifier`, add extra padding to show the difference better:

```kotlin
modifier = Modifier
                    .background(Color.Red)
                    .padding(12.dp),
```

### Background color of an option

To change the background color of a single option, override the `background` parameter to a selected color like `DarkGray`:

```kotlin
val theme = ThemeDefaults.menuItem(modifier = Modifier.fillMaxWidth().background(Color.DarkGray))
MenuItemTheme(theme) {
    BottomMenu(...)
}
```

### Color of the option title

To change the color of an option title to a different one, override the `menuItemTitle` parameter to a selected color like `Red`:

```kotlin
val theme = ThemeDefaults.menuItem(text = TextThemeDefaults.menuItemTitle(color = Color.Red))
MenuItemTheme(theme) {
    BottomMenu(...)
}
```

### Icon tint

To change the color tint of an icon to a different one, override the `menuIcon` parameter to a selected color like `Red`:

```kotlin
val theme = ThemeDefaults.menuItem(icon = IconThemeDefaults.menuIcon(tint = Color.Red))
MenuItemTheme(theme) {
    BottomMenu(...)
}
```