Icon
A platform-native icon — SF Symbol on iOS, Material Symbol on Android.
For the complete documentation index, see llms.txt. Use this file to discover all available pages.
A platform-native icon. On Android, it renders a Material Symbol XML vector drawable supplied through @expo/material-symbols (other XML vector drawable assets aren't officially supported). On iOS, it renders an SF Symbol
Note:
Icondoes not render on web.
Installation
- npx expo install @expo/uiIf you are installing this in an existing React Native app, make sure to install expo in your project.
Usage
Cross-platform icon with Icon.select
Icon.select picks the right asset for the current platform. Pair it with @expo/ui/babel-plugin (auto-loaded by babel-preset-expo) so Metro can tree-shake the unused side per platform.
import { Host, Icon } from '@expo/ui'; export default function IconSelectExample() { return ( <Host matchContents> <Icon name={Icon.select({ ios: 'star.fill', android: import('@expo/material-symbols/star.xml'), })} size={32} color="orange" /> </Host> ); }
Hoisted Icon.select
Hoist the Icon.select call when reusing the same icon across multiple call sites.
import { Host, Row, Icon } from '@expo/ui'; const STAR = Icon.select({ ios: 'star.fill', android: import('@expo/material-symbols/star.xml'), }); export default function HoistedIconExample() { return ( <Host matchContents> <Row spacing={4}> <Icon name={STAR} size={20} color="gold" /> <Icon name={STAR} size={20} color="gold" /> <Icon name={STAR} size={20} color="gold" /> </Row> </Host> ); }
Platform-specific files
Inside an .android.tsx file, import the XML asset directly. Inside an .ios.tsx file, pass the SF Symbol name as a string.
import StarIcon from '@expo/material-symbols/star.xml'; import { Host, Icon } from '@expo/ui'; export default function StarRow() { return ( <Host matchContents> <Icon name={StarIcon} size={24} /> </Host> ); }
import { Host, Icon } from '@expo/ui'; export default function StarRow() { return ( <Host matchContents> <Icon name="star.fill" size={24} /> </Host> ); }
API
import { Icon } from '@expo/ui';
Component
Type: React.Element<IconProps>
A platform-native icon. Renders an XML vector drawable (typically from
@expo/material-symbols) on Android and an SF Symbol on iOS.
Example
const STAR = Icon.select({ ios: 'star.fill', android: import('@expo/material-symbols/star.xml'), }); <Icon name={STAR} size={24} color="orange" />
Example
<Icon name={Icon.select({ ios: 'star.fill', android: import('@expo/material-symbols/star.xml'), })} size={24} />
Example
Both sides ship to both platforms. Prefer Icon.select when bundle size
matters.
<Icon name={{ ios: 'star.fill', android: require('@expo/material-symbols/star.xml'), }} size={24} />
Example
import StarIcon from '@expo/material-symbols/star.xml'; <Icon name={StarIcon} size={24} />
Example
<Icon name="star.fill" size={24} />
Props for the Icon component.
stringAccessibility label for screen readers. On Android, maps to
contentDescription. iOS accessibility is not yet wired up.
booleanWhether the component is disabled. Disabled components do not respond to user interaction.
ModifierConfig[]Platform-specific modifier escape hatch. Pass an array of modifier configs
from @expo/ui/swift-ui/modifiers or @expo/ui/jetpack-compose/modifiers.
IconNameIcon source. Android expects an XML vector drawable asset (typically from
@expo/material-symbols); iOS expects an SF Symbol string.
Use Icon.select for a cross-platform definition.
() => voidCalled when the component is removed from screen.
numberIcon size in dp (Android) / points (iOS). When omitted, the icon uses its intrinsic size.
Pick<ViewStyle, 'padding' | 'paddingHorizontal' | 'paddingVertical' | 'paddingTop' | 'paddingBottom' | 'paddingLeft' | 'paddingRight' | 'backgroundColor' | 'borderRadius' | 'borderWidth' | 'borderColor' | 'opacity' | 'width' | 'height'>Platform-agnostic style properties. These are translated to SwiftUI modifiers on iOS and Jetpack Compose modifiers on Android.
Component Methods
| Parameter | Type |
|---|---|
| spec | IconSelectSpec |
Picks the icon source for the current platform — android on Android,
ios on iOS.
Pair with @expo/ui/babel-plugin to strip the unused side per platform.
SFSymbols7_0 | ImageSourcePropTypeExample
const STAR = Icon.select({ ios: 'star.fill', android: import('@expo/material-symbols/star.xml'), }); <Icon name={STAR} size={24} />
Interfaces
Argument shape accepted by Icon.select.
The android slot accepts either a synchronous require() result or a
dynamic import('*.xml') expression. The latter is preferred because
TypeScript validates the literal path through the package's exports map,
catching typos at compile time. The accompanying Babel plugin
(@expo/ui/babel-plugin, auto-loaded by babel-preset-expo) rewrites the
import() to a require() so Metro can still tree-shake the unused side.
| Property | Type | Description |
|---|---|---|
| android | ImageSourcePropType | Promise<{
default: ImageSourcePropType
}> | - |
| ios | SFSymbols7_0 | - |
Types
A platform-specific icon definition.
Pass a primitive (require()'d XML asset on Android, string SF Symbol on
iOS) or use Icon.select for a cross-platform definition.
The plain object form ({ ios, android }) is also accepted but does not
tree-shake — the Android bundle still includes the iOS asset and vice versa.
Prefer Icon.select so the babel-preset-expo plugin can rewrite the call
into a Platform.OS ternary that Metro DCE can fold per platform.
Type: SFSymbol or ImageSourcePropType or object shaped as below:
| Property | Type | Description |
|---|---|---|
| android | ImageSourcePropType | - |
| ios | SFSymbol | - |