Reference version

This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

SplitButtonLayout

A Jetpack Compose SplitButtonLayout component for a primary action next to a button that opens related actions.

Android
Included in Expo Go
Recommended version:
~58.0.25

Expo UI SplitButtonLayout matches the official Jetpack Compose SplitButtonLayout API. It places a leading button for the primary action next to a trailing button, which usually opens a menu of related actions. Both buttons take the same height.

Installation

Terminal
- npx expo install @expo/ui
- yarn expo install @expo/ui
- pnpm expo install @expo/ui
- bun expo install @expo/ui

If you are installing this in an existing React Native app, make sure to install expo in your project.

Usage

Split button with a menu

SplitButtonLayout has two slots: SplitButtonLayout.LeadingButton and SplitButtonLayout.TrailingButton. Put a SplitButtonLeadingButton in the leading slot. To open a menu from the trailing button, put a DropdownMenu in the trailing slot with a SplitButtonTrailingButton as the menu's trigger. The menu then opens below the button. Set checked on the trailing button while the menu is expanded. Material 3 changes the shape of a checked button to show that the menu is open.

SplitButtonWithMenu.tsx
import { DropdownMenu, DropdownMenuItem, Host, Icon, SplitButtonLayout, SplitButtonLeadingButton, SplitButtonTrailingButton, Text, } from '@expo/ui/jetpack-compose'; import { rotate } from '@expo/ui/jetpack-compose/modifiers'; import { useState } from 'react'; const DROP_DOWN_ICON = require('./assets/arrow_drop_down.xml'); export default function SplitButtonWithMenu() { const [expanded, setExpanded] = useState(false); return ( <Host matchContents> <SplitButtonLayout> <SplitButtonLayout.LeadingButton> <SplitButtonLeadingButton onClick={() => console.log('Send')}> <Text>Send</Text> </SplitButtonLeadingButton> </SplitButtonLayout.LeadingButton> <SplitButtonLayout.TrailingButton> <DropdownMenu expanded={expanded} onDismissRequest={() => setExpanded(false)}> <DropdownMenu.Trigger> <SplitButtonTrailingButton checked={expanded} onCheckedChange={setExpanded}> <Icon source={DROP_DOWN_ICON} contentDescription="Send options" modifiers={[rotate(expanded ? 180 : 0)]} /> </SplitButtonTrailingButton> </DropdownMenu.Trigger> <DropdownMenu.Items> <DropdownMenuItem onClick={() => setExpanded(false)}> <DropdownMenuItem.Text> <Text>Schedule send</Text> </DropdownMenuItem.Text> </DropdownMenuItem> </DropdownMenu.Items> </DropdownMenu> </SplitButtonLayout.TrailingButton> </SplitButtonLayout> </Host> ); }

The slots accept other content too. For example, wrap the trailing button in a TooltipBox to show a tooltip on long press.

Full-width split button

The layout measures the trailing button first and gives the leading button the remaining width. Apply fillMaxWidth() to both the layout and the leading button to make the split button span its container.

FullWidthSplitButton.tsx
import { Host, Icon, SplitButtonLayout, SplitButtonLeadingButton, SplitButtonTrailingButton, Text, } from '@expo/ui/jetpack-compose'; import { fillMaxWidth } from '@expo/ui/jetpack-compose/modifiers'; const DROP_DOWN_ICON = require('./assets/arrow_drop_down.xml'); export default function FullWidthSplitButton() { return ( <Host matchContents={{ vertical: true }} style={{ width: '100%' }}> <SplitButtonLayout modifiers={[fillMaxWidth()]}> <SplitButtonLayout.LeadingButton> <SplitButtonLeadingButton onClick={() => console.log('Merge')} modifiers={[fillMaxWidth()]}> <Text>Squash and merge</Text> </SplitButtonLeadingButton> </SplitButtonLayout.LeadingButton> <SplitButtonLayout.TrailingButton> <SplitButtonTrailingButton checked={false}> <Icon source={DROP_DOWN_ICON} contentDescription="Merge options" /> </SplitButtonTrailingButton> </SplitButtonLayout.TrailingButton> </SplitButtonLayout> </Host> ); }

API

import { SplitButtonLayout } from '@expo/ui/jetpack-compose';

Components

SplitButtonLayout

Android

Type: React.Element<SplitButtonLayoutProps>

A Material 3 split button layout: a leading button for the primary action and a trailing button, usually for a menu of related actions. Both buttons take the same height.

SplitButtonLayoutProps

children

Android
Type: ReactNode

The SplitButtonLayout.LeadingButton and SplitButtonLayout.TrailingButton slots.

modifiers

Android
Optional • Type: ModifierConfig[]

Modifiers for the component.

spacing

Android
Optional • Type: number • Default: SplitButtonDefaults.Spacing

The space between the leading and trailing buttons, in dp.

SplitButtonLeadingButton

Android

Type: React.Element<SplitButtonLeadingButtonProps>

The leading button of a split button, which runs the primary action. Goes in the SplitButtonLayout.LeadingButton slot. Wraps SplitButtonDefaults.LeadingButton.

SplitButtonLeadingButtonProps

children

Android
Type: ReactNode

Content to display inside the button.

colors

Android
Optional • Type: ButtonColors

Colors for the button. Unset colors use ButtonDefaults.buttonColors().

enabled

Android
Optional • Type: boolean • Default: true

Whether the button is enabled for user interaction.

modifiers

Android
Optional • Type: ModifierConfig[]

Modifiers for the component.

onClick

Android
Optional • Type: () => void

Callback that is called when the leading button is clicked.

SplitButtonTrailingButton

Android

Type: React.Element<SplitButtonTrailingButtonProps>

The trailing button of a split button, which usually opens a DropdownMenu of related actions. Goes in the SplitButtonLayout.TrailingButton slot. Wraps SplitButtonDefaults.TrailingButton.

SplitButtonTrailingButtonProps

checked

Android
Type: boolean

Whether the trailing button is checked. This usually matches the menu's expanded state.

children

Android
Type: ReactNode

Content to display inside the button, usually an icon.

colors

Android
Optional • Type: ButtonColors

Colors for the button. Unset colors use ButtonDefaults.buttonColors().

enabled

Android
Optional • Type: boolean • Default: true

Whether the button is enabled for user interaction.

modifiers

Android
Optional • Type: ModifierConfig[]

Modifiers for the component.

onCheckedChange

Android
Optional • Type: (checked: boolean) => void

Callback that is called with the new checked state when the button is clicked.

Types

ButtonColors

Android

Colors for button elements.

PropertyTypeDescription
containerColor(optional)ColorValue
-
contentColor(optional)ColorValue
-
disabledContainerColor(optional)ColorValue
-
disabledContentColor(optional)ColorValue
-