This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.
Extending with Jetpack Compose
Edit page
Learn how to create custom Jetpack Compose components and modifiers that integrate with Expo UI.
This guide explains how to create custom Jetpack Compose components and modifiers that integrate seamlessly with Expo UI.
3 requirements
3 requirements
1.
@expo/ui installedSee Building Jetpack Compose apps with Expo UI for more information.
2.
Expo UI is not available in Expo Go. Create a development build of your app.
3.
Familiarity with Expo Modules API and Jetpack Compose.
Creating a custom component
Project setup
1
Create a local Expo module in your project:
2
Update your module's android/build.gradle to enable Jetpack Compose and depend on expo-ui. The lines marked below are added on top of the default scaffold:
Creating a Compose view
3
Create your Compose view. It has two parts:
- Props data class: annotated with
@OptimizedComposeProps, implementsComposeProps, and includes amodifiers: ModifierListfield for themodifiersprop. @Composablecontent function: an extension onFunctionalComposableScopeso it can callModifierRegistry.applyModifiers(...)and renderChildren(...).
4
Register the view in your module using ExpoUIView. This wires your @Composable content into the Expo modules view system and makes it available to JavaScript:
5
Create a wrapper component that connects modifiers with event handling. The createViewModifierEventListener utility enables event-based modifiers like clickable and onVisibilityChanged to work with your custom view:
Using your custom component
Your custom component now works with all @expo/ui built-in modifiers:
Creating custom modifiers
You can also create custom modifiers that work with any Expo UI component.
Modifiers are Compose's way to configure layouts for styling, sizing, behavior, and more. Learn more in Android's Compose modifiers documentation.
Native modifier implementation
1
Define your modifier's parameters as an @OptimizedRecord data class, and a function that returns a Modifier from those params:
compose is a Kotlin extension property on android.graphics.Color? defined in the expo.modules.ui package. Importing it with import expo.modules.ui.compose lets you call params.color.compose to convert the Android Color parsed from JS into the androidx.compose.ui.graphics.Color that Compose APIs (like BorderStroke) expect. It's the same helper Expo UI's built-in modifiers use.
2
Register your modifier with ModifierRegistry in your module definition. Use OnCreate to register and OnDestroy to unregister so the factory does not leak across module reloads:
The register lambda receives the raw map sent from JavaScript, the current ComposableScope (use it for scope-dependent modifiers like weight or align), the AppContext, and an event dispatcher. Most modifiers only need map and convert it via recordFromMap<T>(map).
JavaScript modifier function
3
Create a TypeScript function that builds the modifier config:
4
Export the modifier from your module:
Using custom modifiers
Your custom modifier works with any @expo/ui component:
Next steps
Congratulations! You've learned how to extend Expo UI with custom Jetpack Compose components and modifiers. Your custom components now integrate seamlessly with the built-in modifier system.
Here are some ideas for what to build next:
- Use the built-in Jetpack Compose components that come with Expo UI.
- Build custom modifiers for app-specific styling patterns.
- Wrap third-party Compose libraries for use in React Native.
- Share your components as an npm package for others to use.