reactnatively
DynamicIsland
An animated Dynamic Island component for iPhone 14 Pro and later. Smoothly transitions between compact, expanded, and minimal states to surface Live Activity content at the top of the screen.
⚠
DynamicIsland renders only on iOS 16+ devices with a Dynamic Island cutout. On unsupported devices the component renders
null. Use DynamicIsland.isSupported to gate rendering where needed.Import
typescript
import { DynamicIsland } from 'reactnatively';Now playing indicator
NowPlayingIsland.tsx
1import { useState } from 'react';2import { View, Image, StyleSheet } from 'react-native';3import { Ionicons } from '@expo/vector-icons';4import { DynamicIsland, Text, IconButton } from 'reactnatively';56export function NowPlayingIsland({ track, isPlaying, onPlayPause }) {7 const [state, setState] = useState<'compact' | 'expanded'>('compact');89 return (10 <DynamicIsland11 state={state}12 onPress={() => setState(state === 'compact' ? 'expanded' : 'compact')}13 compactContent={14 <View style={styles.compact}>15 <Ionicons name="musical-note" size={14} color="#fff" />16 <Text variant="xs" weight="semibold" numberOfLines={1} style={styles.compactTitle}>17 {track.title}18 </Text>19 <Ionicons20 name={isPlaying ? 'pause' : 'play'}21 size={14}22 color="#fff"23 />24 </View>25 }26 expandedContent={27 <View style={styles.expanded}>28 <Image source={{ uri: track.albumArt }} style={styles.art} />29 <View style={styles.info}>30 <Text variant="sm" weight="bold">{track.title}</Text>31 <Text variant="xs" color="rgba(255,255,255,0.5)">{track.artist}</Text>32 </View>33 <View style={styles.controls}>34 <IconButton35 icon={<Ionicons name="play-skip-back" size={18} color="#fff" />}36 accessibilityLabel="Previous"37 variant="ghost"38 size="sm"39 />40 <IconButton41 icon={<Ionicons name={isPlaying ? 'pause' : 'play'} size={20} color="#fff" />}42 accessibilityLabel={isPlaying ? 'Pause' : 'Play'}43 variant="ghost"44 size="md"45 onPress={onPlayPause}46 />47 <IconButton48 icon={<Ionicons name="play-skip-forward" size={18} color="#fff" />}49 accessibilityLabel="Next"50 variant="ghost"51 size="sm"52 />53 </View>54 </View>55 }56 />57 );58}5960const styles = StyleSheet.create({61 compact: { flexDirection: 'row', alignItems: 'center', gap: 6, paddingHorizontal: 8 },62 compactTitle: { maxWidth: 100 },63 expanded: { flexDirection: 'row', alignItems: 'center', gap: 12, padding: 12 },64 art: { width: 48, height: 48, borderRadius: 8 },65 info: { flex: 1 },66 controls: { flexDirection: 'row', alignItems: 'center', gap: 4 },67});Incoming call
CallIsland.tsx
1import { View, StyleSheet } from 'react-native';2import { Ionicons } from '@expo/vector-icons';3import { DynamicIsland, Avatar, Text, IconButton } from 'reactnatively';45export function CallIsland({ caller, onAccept, onDecline }) {6 return (7 <DynamicIsland8 defaultState="expanded"9 expandedContent={10 <View style={styles.row}>11 <Avatar src={{ uri: caller.avatar }} size="sm" online="online" />12 <View style={styles.info}>13 <Text variant="xs" color="rgba(255,255,255,0.5)">Incoming call</Text>14 <Text variant="sm" weight="semibold">{caller.name}</Text>15 </View>16 <View style={styles.actions}>17 <IconButton18 icon={<Ionicons name="call" size={18} color="#fff" />}19 accessibilityLabel="Accept call"20 variant="solid"21 color="success"22 size="sm"23 borderRadius={20}24 onPress={onAccept}25 />26 <IconButton27 icon={<Ionicons name="call" size={18} color="#fff" />}28 accessibilityLabel="Decline call"29 variant="solid"30 color="error"31 size="sm"32 borderRadius={20}33 onPress={onDecline}34 />35 </View>36 </View>37 }38 />39 );40}4142const styles = StyleSheet.create({43 row: { flexDirection: 'row', alignItems: 'center', gap: 10, padding: 10 },44 info: { flex: 1 },45 actions: { flexDirection: 'row', gap: 8 },46});Props
| Prop | Type | Default | Description |
|---|---|---|---|
| state | 'compact' | 'expanded' | 'minimal' | undefined | Controlled display state. |
| defaultState | 'compact' | 'expanded' | 'minimal' | "compact" | Initial state for uncontrolled usage. |
| onStateChange | (state) => void | undefined | Called when state transitions. |
| compactContent | ReactNode | undefined | Content rendered in compact state (pill shape). |
| expandedContent | ReactNode | undefined | Content rendered in expanded state (large island). |
| minimalContent | ReactNode | undefined | Content rendered in minimal state (dot). |
| onPress | () => void | undefined | Called when the island is tapped. |
| style | StyleProp<ViewStyle> | undefined | Style applied to the outer container. |