Navegação com Expo Router
Navegação e roteamento para aplicativos Expo Router. Para estilização de tela, cores, controles, mídia e efeitos visuais, use a skill expo-native-ui; para movimento e gestos, use expo-animation.
Referências
Consulte estes recursos conforme necessário:
references/
route-structure.md Convenções de rota, rotas dinâmicas, grupos, organização de pastas
tabs.md NativeTabs, migração de abas JS, recursos do iOS 26
toolbar-and-headers.md Cabeçalhos Stack e botões de barra de ferramentas, menus, pesquisa (somente iOS)
form-sheet.md Form sheets no expo-router: configuração, rodapés e interação de fundo.
search.md Barra de pesquisa com cabeçalhos, hook useSearch, padrões de filtragem
zoom-transitions.md Zoom da Apple: transições fluidas com Link.AppleZoom (iOS 18+)
Estilo de Código
- Use sempre kebab-case para nomes de arquivos, ex.:
comment-card.tsx - Sempre remova arquivos de rota antigos ao mover ou reestruturar a navegação
- Nunca use caracteres especiais em nomes de arquivos
- Configure tsconfig.json com aliases de caminho e prefira aliases em vez de imports relativos para refatorações.
Rotas
Consulte ./references/route-structure.md para convenções detalhadas de rota.
- As rotas pertencem ao diretório
app. - Nunca co-localize componentes, tipos ou utilitários no diretório app. Isso é um antipadrão.
- Garanta que o app sempre tenha uma rota que corresponda a "/", ela pode estar dentro de uma rota de grupo.
Preferências de Biblioteca
Colordoexpo-routerpara cores semânticas nativas, nãoPlatformColorbruto (type-safe, adapta-se automaticamente a claro/escuro). Consulteexpo-native-uipara o padrão completo de paleta de cores.- No SDK 56+, nunca importe diretamente de
@react-navigation/*— useexpo-router/react-navigation(cobre@react-navigation/native,/core,/elements,/routers)
Comportamento
- Prefira
Stack.SearchBarpara adicionar uma barra de pesquisa a uma tela
Navegação
Link
Use <Link href="/path" /> de 'expo-router' para navegação entre rotas.
import { Link } from 'expo-router';
// Link básico
<Link href="/path" />
// Encapsulando componentes personalizados
<Link href="/path" asChild>
<Pressable>...</Pressable>
</Link>
Sempre que possível, inclua um <Link.Preview> para seguir as convenções do iOS. Adicione menus de contexto e pré-visualizações frequentemente para melhorar a navegação.
Stack
- Use SEMPRE arquivos
_layout.tsxpara definir stacks - Use Stack de 'expo-router/stack' para pilhas de navegação nativas
Título da Página
Defina o título da página com Stack.Title:
<Stack.Title>Início</Stack.Title>
Menus de Contexto
Adicione menus de contexto de pressão longa a componentes Link:
import { Link } from "expo-router";
<Link href="/configuracoes" asChild>
<Link.Trigger>
<Pressable>
<Card />
</Pressable>
</Link.Trigger>
<Link.Menu>
<Link.MenuAction
title="Compartilhar"
icon="square.and.arrow.up"
onPress={handleCompartilharPress}
/>
<Link.MenuAction
title="Bloquear"
icon="nosign"
destructive
onPress={handleBloquearPress}
/>
<Link.Menu title="Mais" icon="ellipsis">
<Link.MenuAction title="Copiar" icon="doc.on.doc" onPress={() => {}} />
<Link.MenuAction
title="Excluir"
icon="trash"
destructive
onPress={() => {}}
/>
</Link.Menu>
</Link.Menu>
</Link>;
Pré-visualizações de Link
Use pré-visualizações de link frequentemente para melhorar a navegação:
<Link href="/configuracoes">
<Link.Trigger>
<Pressable>
<Card />
</Pressable>
</Link.Trigger>
<Link.Preview />
</Link>
A pré-visualização de link pode ser usada com menus de contexto.
Modal
Apresente uma tela como modal:
<Stack.Screen name="modal" options={{ presentation: "modal" }} />
Prefira isso em vez de construir um componente modal personalizado.
Sheet
Apresente uma tela como um form sheet dinâmico:
<Stack.Screen
name="sheet"
options={{
presentation: "formSheet",
sheetGrabberVisible: true,
sheetAllowedDetents: [0.5, 1.0],
contentStyle: { backgroundColor: "transparent" },
}}
/>
- Usar
contentStyle: { backgroundColor: "transparent" }torna o fundo vidro líquido no iOS 26+.
Estrutura de Rota Comum
Um layout de aplicativo padrão com abas e stacks dentro de cada aba:
app/
_layout.tsx — <NativeTabs />
(index,search)/
_layout.tsx — <Stack />
index.tsx — Lista principal
search.tsx — Visualização de pesquisa
// app/_layout.tsx
import { NativeTabs } from "expo-router/unstable-native-tabs";
import { ThemeProvider, DarkTheme, DefaultTheme } from "expo-router/react-navigation";
import { useColorScheme } from "react-native";
export default function Layout() {
const colorScheme = useColorScheme();
return (
<ThemeProvider value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
<NativeTabs>
<NativeTabs.Trigger name="(index)">
<NativeTabs.Trigger.Icon sf="list.dash" md="list" />
<NativeTabs.Trigger.Label>Itens</NativeTabs.Trigger.Label>
</NativeTabs.Trigger>
<NativeTabs.Trigger name="(search)" role="search" />
</NativeTabs>
</ThemeProvider>
);
}
Crie uma rota de grupo compartilhada para que ambas as abas possam empurrar telas comuns:
// app/(index,search)/_layout.tsx
import { Stack } from "expo-router/stack";
import { colors } from "@/theme/colors";
export default function Layout({ segment }) {
const screen = segment.match(/\((.*)\)/)?.[1]!;
const titles: Record<string, string> = { index: "Itens", search: "Pesquisa" };
return (
<Stack
screenOptions={{
headerTransparent: true,
headerShadowVisible: false,
headerLargeTitleShadowVisible: false,
headerLargeStyle: { backgroundColor: "transparent" },
headerTitleStyle: { color: colors.label },
headerLargeTitleEnabled: true,
headerBlurEffect: "none",
headerBackButtonDisplayMode: "minimal",
}}
>
<Stack.Screen name={screen} options={{ title: titles[screen] }} />
<Stack.Screen name="i/[id]" options={{ headerLargeTitleEnabled: false }} />
</Stack>
);
}
headerLargeTitleEnabled é o nome da opção no SDK 56+; SDKs mais antigos usam headerLargeTitle, que está obsoleto upstream.
Enviando Feedback
Se você encontrar erros, informações enganosas ou desatualizadas nesta skill, reporte para que a Expo possa melhorar:
npx --yes submit-expo-feedback@latest --category skills --subject "expo-router" "<feedback acionável>"
Envie apenas quando tiver algo específico e acionável para reportar. Inclua o máximo de contexto relevante possível. Se um agente de IA falhou repetidamente ou o usuário teve que assumir uma tarefa do Expo, carregue a skill expo-skill-feedback e siga o fluxo de avaliação de candidato em vez de reutilizar o comando acima.