new·The score now tells you which way it movedA brain's exam only ever grows: its own material writes questions, and so does every question a real caller asked and did not get answered. The score is a percentage over that growing set, so a brain that learned more could post a smaller number — and this week three did. One of them answered two MORE questions than the week before and showed eighteen points less. Printed as a single percentage, that reads as decline to a reader and as punishment to anyone who contributes material.all news →
mozg.beta
Sign in

Expo · Router · all subjects

stack-navigator

37 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Stack navigator creates foundational navigation

A stack navigator is the foundational way of navigating between routes in an app. On Android, a stacked route animates on top of the current screen. On iOS, a stacked route animates from the right. Expo Router provides a Stack navigation component that creates a navigation stack and allows you to add new routes in your app.

Basic Stack setup with file-based routing

To create a basic Stack navigator using file-based routing, create a _layout.tsx file in your app directory and import and render the Stack component. Example: import { Stack } from 'expo-router'; export default function Layout() { return <Stack />; }

Stack.Screen component for static route configuration

You can use the <Stack.Screen name={routeName} /> component in the layout component to statically configure a route's options. This allows you to set options for individual routes like headerStyle, headerTintColor, and headerTitleStyle.

Statically configure header bar for all Stack routes

Configure the header bar for all routes in a Stack navigator by using the screenOptions prop on the Stack component. This is useful for setting a common header style across all routes. Example options include headerStyle, headerTintColor, and headerTitleStyle.

Dynamic screen options with Stack.Screen in route component

To configure a route's options dynamically, use the Stack.Screen component within the route component itself (e.g., in details.tsx). You can set options like title based on route params by calling router.setParams() to update the displayed title.

Composition components API for screen configuration (SDK 55+)

Starting in SDK 55, you can configure screen options using composition components in addition to the options-based API. Use <Stack.Title>, <Stack.Header>, and <Stack.Toolbar> components directly in route components to configure screen appearance dynamically.

Add buttons to Stack header with headerLeft and headerRight

You can add buttons to the header using the headerLeft and headerRight options or the <Stack.Toolbar> component. These options accept a React component that renders in the header. For example, headerRight can render a Button component.

Custom push behavior with getId function

By default, the Stack navigator removes duplicate screens when pushing a route already in the stack. You can override this by providing a custom getId() function to <Stack.Screen>. Returning a new ID every time (e.g., String(Date.now())) will cause every page to push as a new screen.

Router dismiss action removes screens from stack

The router.dismiss(count) action dismisses the last screen in the closest stack. You can optionally pass a positive number to dismiss up to that specified number of screens. Dismiss targets the closest stack and not the current navigator, so with nested navigators it takes you back multiple screens.

Router dismissTo action goes to specific route

The router.dismissTo(href) action (added in Expo Router 4.0.8) dismisses screens until the specified Href is reached. If the Href is absent in the history, a push action is performed instead. For example, with history /one, /two, /three, calling router.dismissTo('/one') goes back twice.

Router dismissAll action returns to first screen

The router.dismissAll() action returns to the first screen in the closest stack, similar to the popToTop stack action. This allows jumping from any screen directly to the first screen and dismissing any screens in between.

Router canDismiss checks if dismissal is possible

The router.canDismiss() method returns true if the router is within a stack with more than one screen in the stack's history. Use this to check if it is possible to dismiss the current screen before calling router.dismiss().

iOS 26 Liquid Glass headers enabled by default

Starting from iOS 26, navigation headers adopt the system's Liquid Glass effect by default and cannot be disabled per screen. You must opt out using global configuration.

Disable iOS Liquid Glass with UIDesignRequiresCompatibility

To opt out of iOS 26+ Liquid Glass headers, create a development build and set the UIDesignRequiresCompatibility property to true in app.json under ios.infoPlist. This is a temporary workaround that will be removed in iOS 27.

Use expo-router/js-stack for full header control

To avoid iOS 26+ Liquid Glass effect and gain full control over header UI, use the JavaScript-driven stack from expo-router/js-stack instead of the native stack. This comes at the cost of performance benefits from the optimized iOS navigation views. Import: import { Stack as JsStack } from 'expo-router/js-stack';

Fix large title not collapsing with ScrollView

When using headerLargeTitle: true with ScrollView or FlatList, the large title may not collapse on scroll if the scrollable view is not the direct first child. To fix this, ensure ScrollView or FlatList is the first child. If you need a wrapper, set collapsable={false} on it.

Stack.Title component for composition API

In SDK 55+, use <Stack.Title> component to configure the screen title dynamically. It accepts children for the title content and an optional 'large' prop to enable large title mode.

Stack.Header component for composition API

In SDK 55+, use <Stack.Header> component to configure header styling in route components. It accepts style props and other header configuration.

Stack.Toolbar component for header buttons

In SDK 55+, use <Stack.Toolbar> component to add buttons to the header. It accepts a placement prop (left or right) and asChild prop to render custom components.

Web modal configuration in Stack.Screen

Modals in Expo Router are configured using the Stack.Screen component with specific options. The modal screen must be added to the layout file of your app's Stack. Modals are opened using router.push() with the modal screen path.

Stack.Screen modal presentation option values

The presentation option accepts four values: 'modal', 'formSheet', 'transparentModal', or 'containedTransparentModal'. On screens with width more than 768px, all styles display as a centered overlay (lightbox). On screens with width less than 768px, formSheet is used to display as a bottom sheet. transparentModal displays as an overlay without a completely obscured background and does not apply detents or sheet grabber properties. containedTransparentModal is similar to transparentModal and is useful when building custom modals.

sheetAllowedDetents option for web modals

The sheetAllowedDetents option accepts either an array of numbers between 0.0 and 1.0 representing snap positions as percentages, or the string 'fitToContents' for automatic fitting. This option only applies to screens with less than 768px width and defines the height at which a modal can rest when displayed as a bottom sheet.

Compact modal example

For smaller interactions, create a compact modal with Stack.Screen options: presentation: 'modal', webModalStyle: { width: 400, height: 'auto', minHeight: 200, border: '1px solid #e5e7eb', overlayBackground: 'rgba(0, 0, 0, 0.3)' }, sheetCornerRadius: 12, sheetAllowedDetents: 'fitToContents'.

Transparent modal with custom overlay example

To implement a custom modal with animations and overlay, set presentation: 'transparentModal', animation: 'fade', and headerShown: false in Stack.Screen options. Use Animated.View with FadeIn entering animation for the overlay and SlideInDown for the modal content. Set backgroundColor: '#00000040' for semi-transparent overlay and use Link href={'/'} with Pressable to dismiss the modal when pressing outside.

Basic web modal setup example

Example of basic web modal setup in _layout.tsx: ```tsx import { Stack } from 'expo-router'; export const unstable_settings = { anchor: 'index', }; export default function Layout() { return ( <Stack> <Stack.Screen name="index" /> <Stack.Screen name="modal" options={{ presentation: 'modal', sheetAllowedDetents: [0.5, 1], }} /> </Stack> ); } ``` Then use router.push('/modal') in your index route to open the modal.

Web modals only apply webModalStyle on desktop

The webModalStyle properties only apply to web platforms on desktop. On mobile devices, the modal will automatically adapt to use sheet-like behavior for touch interaction.

Web modal options reference table

Stack.Screen options for web modals: | Option | Type | Description | |--------|------|-------------| | presentation | 'modal', 'formSheet', 'transparentModal', 'containedTransparentModal' | Modal presentation style. On screens >768px width, all styles display as centered overlay. On screens <768px, formSheet displays as bottom sheet. transparentModal and containedTransparentModal display as overlay without obscured background. | | sheetAllowedDetents | number[], 'fitToContents' | Snap positions as percentages (0.0-1.0) or automatic fitting. Only applies to screens <768px width. | | sheetGrabberVisible | boolean | Shows/hides drag handle at top of sheet. Only on iOS; not supported on Android and web. | | sheetCornerRadius | number | Corner radius of the sheet in pixels. | | webModalStyle | WebModalStyle | Special prop for web-specific styling options. |

webModalStyle properties reference

The webModalStyle object provides the following properties: | Property | Type | Description | Default | |----------|------|-------------|----------| | width | number, string | Override modal width (px or percentage). Only on web desktop. | 83vw | | height | number, string | Override modal height (px or percentage). Only on web desktop. | 79vh | | minHeight | number, string | Minimum height of desktop modal (px or percentage). | min(586px, 79vh) | | minWidth | number, string | Minimum width of desktop modal (px or percentage). | min(936px, 83vw) | | border | string | Override border of desktop modal (any valid CSS border value). | None | | overlayBackground | string | Override overlay background color (any valid CSS color or rgba/hsla value). | Semi-transparent black | | shadow | string | Override modal shadow filter (any valid CSS filter value). | Drop-shadow filter |

Web modal CSS custom properties

Expo Router uses CSS custom properties to style modals. Width and height variables: --expo-router-modal-width (83vw), --expo-router-modal-max-width (min(936px, 83vw)), --expo-router-modal-min-width (auto), --expo-router-modal-height (79vh), --expo-router-modal-min-height (min(586px, 79vh)). Border and overlay variables: --expo-router-modal-border (none), --expo-router-modal-border-radius (24px), --expo-router-modal-shadow (drop-shadow(0 10px 8px rgb(0 0 0 / 0.04)) drop-shadow(0 4px 3px rgb(0 0 0 / 0.1))), --expo-router-modal-overlay-background (rgba(0, 0, 0, 0.25)).

How webModalStyle maps to CSS variables

When you use webModalStyle to override sizing variables, Expo Router automatically sets the corresponding CSS variables. For example, webModalStyle with width: 800, height: 600, border: '2px solid blue', overlayBackground: 'rgba(0, 0, 0, 0.7)', shadow: 'drop-shadow(0 8px 16px rgba(0,0,0,0.2))' sets --expo-router-modal-width: 800px, --expo-router-modal-height: 600px, --expo-router-modal-border: 2px solid blue, --expo-router-modal-overlay-background: rgba(0, 0, 0, 0.7), --expo-router-modal-shadow: drop-shadow(0 8px 16px rgba(0,0,0,0.2)).

Anchors in web modals with nested stacks

An anchor serves as the base for a modal to ensure correct navigation behavior, especially when deep-linking to modal routes. Without anchoring, the screen behind the modal can be wiped away, leaving no navigation context. Configure an anchor by exporting unstable_settings from your stack's layout file with the anchor property set to the initial route name, for example: export const unstable_settings = { anchor: 'index' };

Global CSS customization for web modals

You can override modal styling globally using a global CSS file by setting custom --expo-router-* CSS variables. Example: :root { --expo-router-modal-width: 700px; --expo-router-modal-min-width: auto; --expo-router-modal-max-width: 95vw; --expo-router-modal-height: 640px; --expo-router-modal-min-height: 640px; --expo-router-modal-border: none; --expo-router-modal-border-radius: 16px; --expo-router-modal-shadow: drop-shadow(0 8px 16px rgba(0, 0, 0, 0.2)); --expo-router-modal-overlay-background: rgba(0, 0, 0, 0.5); }

Full screen web modal example

To create a full screen modal, use webModalStyle property in Stack.Screen options with width: '95vw', height: '95vh', and border: 'none'. On mobile devices, set sheetAllowedDetents to 'fitToContents' or a custom value to avoid showing a full screen modal on small screens.

Stack navigator in layout example

To implement a stack navigator in a layout file, import Stack from 'expo-router' and return a Stack component. Files in the directory are automatically treated as eligible routes in the stack. You can optionally define Stack.Screen components inside Stack to set screen options, where the name prop matches the route name. The back button in the header pops the current page off the stack.

Stack navigator with screen options example

You can define screen options in a stack by adding Stack.Screen components with a name prop matching the route name. You do not need to supply a component prop; Expo Router maps this automatically. Example: <Stack><Stack.Screen name="[productId]" options={{ headerShown: false }} /></Stack>

Avoid unnecessary nested stacks

Avoid nesting navigators unless truly needed. If you want to push a route from a subdirectory onto a parent stack, do not add an additional _layout.tsx in the subdirectory with a Stack navigator, as this creates unnecessary nesting. Instead, use the same navigator as the parent directory, or add directories that only affect the URL structure.

Default navigation mode is stack-based

Expo Router apps default to stack navigation, where navigating to a new route pushes a screen onto a stack, and backing out of that route pops it off the stack.

Give your agent this brain