Dynamic Island banner
Reusable in-app notification banner primitive (expo-dynamic-island).
expo-dynamic-island is a neutral, reusable Dynamic Island–style transient
in-app notification banner for Expo apps (iOS, Android, Web): a provider with
a Skia goo morph, swipe-to-dismiss gesture, sticky notifications, and a custom
render override.
It is an external reusable primitive, not a vendored foundation skill — see
External skills. Route banner work to it through
$expo-development-foundation (Tree 3, UI stack), composed with
expo-native-ui / expo-a11y as matched and closed with expo-verify.
When to use
- Transient in-app card (download complete, upload progress, background work).
- OS-level push or local scheduled delivery → use the
expo-notificationsskill instead; permission timing alone →expo-permissions.
Install
Install the Expo SDK 57 peers, then wrap the root layout with the provider
(GestureHandlerRootView → SafeAreaProvider → DynamicNotifications):
npx expo install @shopify/react-native-skia react-native-reanimated react-native-worklets react-native-gesture-handler react-native-safe-area-context expo-blur expo-image expo-symbols
import { DynamicNotifications } from "expo-dynamic-island";
export default function RootLayout() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<SafeAreaProvider>
<DynamicNotifications>
<Stack screenOptions={{ headerShown: false }} />
</DynamicNotifications>
</SafeAreaProvider>
</GestureHandlerRootView>
);
}
Trigger from any component inside the provider:
const { trigger, dismiss } = useDynamicNotifications();
trigger({ title: "Download complete", message: "Your file is ready" });
API essentials
trigger(notification):title(required),message?,avatar?(image URI),symbol?(SF symbol name),accent?,duration?,onPress?,render?.duration={null}(provider or per notification) keeps the banner sticky untildismiss()is called.render(notification)replaces the default card content entirely.onDismiss(notification)on the provider observes dismissals.- Theming via
cardColor,islandColor,accent,shadowColor.
Accessibility and platform notes
- The card exposes an alert role with a title/message label; the default body is a single announcement.
- With OS reduced motion on, the banner appears and dismisses without spring travel.
- On Android and Web,
expo-symbolsglyphs fall back to no glyph — never rely on a symbol alone for critical meaning; preferavatar, text, orrender. - Title and message stay single-line truncated; custom
rendercontent is consumer-owned for Dynamic Type.
Verification
npx tsc --noEmitin the package.npx expo-doctorin the consumer app.- Expo Go smoke: banner appears on trigger, auto-hides after
duration, sticky hides only viadismiss(), tap firesonPress,renderreplaces card content, screen reader announces the alert.
Source
External reusable package expo-dynamic-island. The agent
contract is SKILL.md at the package root; copy-paste consumer snippets live
under example/. Ask the user for its checkout location rather than inventing one.
Stop rules
- No EAS builds, submissions, or deployments by inference.
- No secrets in code, config, or examples.