SwiftUI components for building native iOS interfaces with @expo/ui.
This library is currently in beta and subject to breaking changes. It is not available in the Expo Go app — use development builds to try it out.
The SwiftUI components in @expo/ui/swift-ui
allow you to build fully native iOS interfaces using SwiftUI from React Native.
Learn about the basics of @expo/ui/swift-ui
Installation
-
npx expo install @expo/ui
If you are installing this in an existing React Native app, make sure to install expo
in your project.
Components
BottomSheet
import { BottomSheet, Host, Text } from '@expo/ui/swift-ui'; import { useWindowDimensions } from 'react-native'; const { width } = useWindowDimensions(); <Host style={{ position: 'absolute', width }}> <BottomSheet isOpened={isOpened} onIsOpenedChange={e => setIsOpened(e)}> <Text>Hello, world!</Text> </BottomSheet> </Host>
See also: official SwiftUI documentation
Button
The borderless variant is not available on Apple TV.
import { Button, Host } from '@expo/ui/swift-ui'; <Host style={{ flex: 1 }}> <Button variant="default" onPress={() => { setEditingProfile(true); }}> Edit profile </Button> </Host>
See also: official SwiftUI documentation
CircularProgress
import { CircularProgress, Host } from '@expo/ui/swift-ui'; <Host style={{ width: 300 }}> <CircularProgress progress={0.5} color="blue" /> </Host>
See also: official SwiftUI documentation
ColorPicker
This component is not available on Apple TV.
import { ColorPicker, Host } from '@expo/ui/swift-ui'; <Host style={{ width: 400, height: 200 }}> <ColorPicker label="Select a color" selection={color} onValueChanged={setColor} /> </Host>
See also: official SwiftUI documentation
ContextMenu
Note: Also known as DropdownMenu.
import { ContextMenu, Host } from '@expo/ui/swift-ui'; <Host style={{ width: 150, height: 50 }}> <ContextMenu> <ContextMenu.Items> <Button systemImage="person.crop.circle.badge.xmark" onPress={() => console.log('Pressed1')}> Hello </Button> <Button variant="bordered" systemImage="heart" onPress={() => console.log('Pressed2')}> Love it </Button> <Picker label="Doggos" options={['very', 'veery', 'veeery', 'much']} variant="menu" selectedIndex={selectedIndex} onOptionSelected={({ nativeEvent: { index } }) => setSelectedIndex(index)} /> </ContextMenu.Items> <ContextMenu.Trigger> <Button variant="bordered"> Show Menu </Button> </ContextMenu.Trigger> </ContextMenu> </Host>
See also: official SwiftUI documentation
DateTimePicker (date)
This component is not available on Apple TV.
import { DateTimePicker, Host } from '@expo/ui/swift-ui'; <Host matchContents> <DateTimePicker onDateSelected={date => { setSelectedDate(date); }} displayedComponents='date' initialDate={selectedDate.toISOString()} variant='wheel' /> </Host>
See also: official SwiftUI documentation
DateTimePicker (time)
This component is not available on Apple TV.
import { DateTimePicker, Host } from '@expo/ui/swift-ui'; <Host matchContents> <DateTimePicker onDateSelected={date => { setSelectedDate(date); }} displayedComponents='hourAndMinute' initialDate={selectedDate.toISOString()} variant='wheel' /> </Host>
See also: official SwiftUI documentation
Gauge
This component is not available on Apple TV.
import { Gauge, Host } from "@expo/ui/swift-ui"; <Host matchContents> <Gauge max={{ value: 1, label: '1' }} min={{ value: 0, label: '0' }} current={{ value: 0.5 }} color={[ PlatformColor('systemRed'), PlatformColor('systemOrange'), PlatformColor('systemYellow'), PlatformColor('systemGreen'), ]} type="circularCapacity" /> </Host>
See also: official SwiftUI documentation
Host
A component that allows you to put the other @expo/ui/swift-ui
components in React Native. It acts like <svg>
for DOM, <Canvas>
for react-native-skia
, which underlying uses UIHostingController
to render the SwiftUI views in UIKit.
Since the Host
component is a React Native View
, you can pass the style
prop to it or matchContents
prop to make the Host
component match the contents' size.
import { Button, Host } from '@expo/ui/swift-ui'; function Example() { return ( <Host matchContents> <Button onPress={() => { console.log('Pressed'); }}> Click </Button> </Host> ); }
import { Button, Host, VStack, Text } from '@expo/ui/swift-ui'; function Example() { return ( <Host style={{ flex: 1 }}> <VStack spacing={8}> <Text>Hello, world!</Text> <Button onPress={() => { console.log('Pressed'); }}> Click </Button> </VStack> </Host> ); }
LinearProgress
import { LinearProgress, Host } from '@expo/ui/swift-ui'; <Host style={{ width: 300 }}> <LinearProgress progress={0.5} color="red" /> </Host>
See also: official SwiftUI documentation
List
import { Host, List } from '@expo/ui/swift-ui'; <Host style={{ flex: 1 }}> <List scrollEnabled={false} editModeEnabled={editModeEnabled} onSelectionChange={(items) => alert(`indexes of selected items: ${items.join(', ')}`)} moveEnabled={moveEnabled} onMoveItem={(from, to) => alert(`moved item at index ${from} to index ${to}`)} onDeleteItem={(item) => alert(`deleted item at index: ${item}`)} listStyle='automatic' deleteEnabled={deleteEnabled} selectEnabled={selectEnabled}> {data.map((item, index) => ( <LabelPrimitive key={index} title={item.text} systemImage={item.systemImage} color={color} /> ))} </List> </Host>
See also: official SwiftUI documentation
Picker (segmented)
import { Host, Picker } from '@expo/ui/swift-ui'; <Host matchContents> <Picker options={['$', '$$', '$$$', '$$$$']} selectedIndex={selectedIndex} onOptionSelected={({ nativeEvent: { index } }) => { setSelectedIndex(index); }} variant="segmented" /> </Host>
See also: official SwiftUI documentation
Picker (wheel)
The wheel variant is not available on Apple TV.
import { Host, Picker } from '@expo/ui/swift-ui'; <Host style={{ height: 100 }}> <Picker options={['$', '$$', '$$$', '$$$$']} selectedIndex={selectedIndex} onOptionSelected={({ nativeEvent: { index } }) => { setSelectedIndex(index); }} variant="wheel" /> </Host>
See also: official SwiftUI documentation
Slider
This component is not available on Apple TV.
import { Host, Slider } from '@expo/ui/swift-ui'; <Host style={{ minHeight: 60 }}> <Slider value={value} onValueChange={(value) => { setValue(value); }} /> </Host>
See also: official SwiftUI documentation
Switch (toggle)
Note: Also known as Toggle.
import { Host, Switch } from '@expo/ui/swift-ui'; <Host matchContents> <Switch checked={checked} onValueChange={checked => { setChecked(checked); }} color="#ff0000" label="Play music" variant="switch" /> </Host>
See also: official SwiftUI documentation
Switch (checkbox)
import { Host, Switch } from '@expo/ui/swift-ui'; <Host matchContents> <Switch checked={checked} onValueChange={checked => { setChecked(checked); }} label="Play music" variant="checkbox" /> </Host>
See also: official SwiftUI documentation
TextField
import { Host, TextField } from '@expo/ui/swift-ui'; <Host matchContents> <TextField autocorrection={false} defaultValue="A single line text input" onChangeText={setValue} /> </Host>
See also: official SwiftUI documentation
More
Expo UI is still in active development. We continue to add more functionality and may change the API. Some examples in the docs may not be up to date. If you want to see the latest changes, check the examples.
API
Full documentation is not yet available. Use TypeScript types to explore the API.
// Import from the SwiftUI package import { BottomSheet } from '@expo/ui/swift-ui';