React Native Paper
Componentes Material Design e temas para UX com foco em Android.
Busque em todas as páginas da documentação
Componentes Material Design e temas para UX com foco em Android.
React Native Paper implementa Material Design 3 para React Native: botões, campos de texto, diálogos, chips e superfícies com papéis de acessibilidade e feedback de ripple integrados. No Expo SDK 57, combine PaperProvider com temas MD3 e, opcionalmente, adapte o React Navigation para que cabeçalhos e abas correspondam à sua paleta.
Cartão de receita de referência rápida - pronto para copiar e colar.
npx create-expo-app@latest MyPaperApp --template blank-typescript
cd MyPaperApp
npx expo install react-native-paper react-native-safe-area-context
npm install @react-navigation/native// theme/paper.ts
import {
MD3DarkTheme,
MD3LightTheme,
adaptNavigationTheme,
configureFonts,
} from "react-native-paper";
import {
DarkTheme as NavDarkTheme,
DefaultTheme as NavDefaultTheme,
} from "@react-navigation/native";
const fontConfig = configureFonts({ config: { fontFamily: "System" } });
export const lightTheme = {
...MD3LightTheme,
fonts: fontConfig,
colors: {
...MD3LightTheme.colors,
primary: "#2563eb",
secondary: "#7c3aed",
},
roundness: 10,
};
export const darkTheme = {
...MD3DarkTheme,
fonts: fontConfig,
colors: {
...MD3DarkTheme.colors,
primary: "#60a5fa",
secondary: "#a78bfa",
},
roundness: 10,
};
export const { LightTheme: NavLight, DarkTheme: NavDark } = adaptNavigationTheme({
reactNavigationLight: NavDefaultTheme,
reactNavigationDark: NavDarkTheme,
materialLight: lightTheme,
materialDark: darkTheme,
});// App.tsx
import { useColorScheme } from "react-native";
import { PaperProvider } from "react-native-paper";
import { NavigationContainer } from "@react-navigation/native";
import { createNativeStackNavigator } from "@react-navigation/native-stack";
import { HomeScreen } from "./screens/HomeScreen";
import { darkTheme, lightTheme, NavDark, NavLight } from "./theme/paper";
const Stack = createNativeStackNavigator();
export default function App() {
const scheme = useColorScheme() ?? "light";
const paperTheme = scheme === "dark" ? darkTheme : lightTheme;
const navTheme = scheme === "dark" ? NavDark : NavLight;
return (
<PaperProvider theme={paperTheme}>
<NavigationContainer theme={navTheme}>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen} options={{ title: "Inbox" }} />
</Stack.Navigator>
</NavigationContainer>
</PaperProvider>
);
}// screens/HomeScreen.tsx
import { View } from "react-native";
import { Button, Card, Text, TextInput } from "react-native-paper";
export function HomeScreen() {
return (
<View style={{ flex: 1, padding: 16, gap: 12 }}>
<Card mode="elevated">
<Card.Title title="Welcome" subtitle="Material 3 on Expo" />
<Card.Content>
<Text variant="bodyMedium">Compose forms and actions from Paper primitives.</Text>
</Card.Content>
<Card.Actions>
<Button mode="text">Dismiss</Button>
<Button mode="contained">Continue</Button>
</Card.Actions>
</Card>
<TextInput mode="outlined" label="Email" placeholder="you@example.com" />
</View>
);
}Quando usar isto:
adaptNavigationTheme.Button, FAB e Searchbar do Paper já oferecem padrões prontos para produção.Fluxo de login com tema MD3, provedor de ícones, feedback de snackbar e modo escuro.
// providers/AppProviders.tsx
import { useMemo } from "react";
import { useColorScheme } from "react-native";
import { PaperProvider, MD3Theme } from "react-native-paper";
import { NavigationContainer, Theme } from "@react-navigation/native";
import { darkTheme, lightTheme, NavDark, NavLight } from "../theme/paper";
export function AppProviders({
children,
navigationRef,
}: {
children: React.ReactNode;
navigationRef?: React.RefObject<object>;
}) {
const scheme = useColorScheme() ?? "light";
const paperTheme = useMemo<MD3Theme>(
() => (scheme === "dark" ? darkTheme : lightTheme),
[scheme],
);
const navTheme = useMemo<Theme>(
() => (scheme === "dark" ? NavDark : NavLight),
[scheme],
);
return (
<PaperProvider theme={paperTheme}>
<NavigationContainer ref={navigationRef} theme={navTheme}>
{children}
</NavigationContainer>
</PaperProvider>
);
}// screens/LoginScreen.tsx
import { useState } from "react";
import { KeyboardAvoidingView, Platform, View } from "react-native";
import { Button, HelperText, Snackbar, Text, TextInput } from "react-native-paper";
export function LoginScreen() {
const [email, setEmail] = useState("");
const [error, setError] = useState<string | null>(null);
const [snack, setSnack] = useState(false);
function handleSubmit() {
if (!email.includes("@")) {
setError("Enter a valid email");
return;
}
setError(null);
setSnack(true);
}
return (
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === "ios" ? "padding" : undefined}
>
<View style={{ flex: 1, padding: 24, justifyContent: "center", gap: 12 }}>
<Text variant="headlineMedium">Sign in</Text>
<TextInput
mode="outlined"
label="Email"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
error={!!error}
accessibilityLabel="Email address"
/>
<HelperText type="error" visible={!!error}>
{error}
</HelperText>
<Button mode="contained" onPress={handleSubmit} accessibilityLabel="Sign in">
Sign in
</Button>
</View>
<Snackbar visible={snack} onDismiss={() => setSnack(false)} duration={3000}>
Signed in as {email}
</Snackbar>
</KeyboardAvoidingView>
);
}O que isto demonstra:
PaperProvider fornece o tema MD3 para todos os componentes Paper - cores, arredondamento, fontes, ripple.adaptNavigationTheme alinha as cores do cabeçalho/aba do React Navigation com os papéis primary e surface do Paper.Text variant="headlineMedium" usa a escala de tipografia MD3 - não fontSize bruto.HelperText + prop error no TextInput - padrão de validação acessível.Snackbar para feedback transitório sem infraestrutura de toast personalizada.primary, onPrimary, primaryContainer, surface, onSurface, outline, etc. Componentes Paper consomem papéis, não hexadecimais arbitrários.PaperProvider - Contexto React para tema, ícones (settings.icon) e configuração de ripple.useTheme() do Paper retorna o MD3Theme ativo dentro de qualquer componente filho.mode - Button mode="contained|outlined|text|elevated", Card mode="elevated|outlined|contained".react-native-vector-icons MaterialCommunityIcons por padrão; substitua via settings.icon no provedor.import { MD3LightTheme } from "react-native-paper";
const theme = {
...MD3LightTheme,
colors: {
...MD3LightTheme.colors,
primary: "#2563eb", // ações da marca
onPrimary: "#ffffff", // texto em botões primários
surface: "#ffffff", // cards, sheets
onSurface: "#1c1b1f", // texto principal na superfície
background: "#f8fafc", // fundo da tela
},
roundness: 10, // linha de base do raio do canto global
};Mapeie seus tokens semânticos de Noções Básicas de Sistemas de Design para os papéis MD3 - não invente nomes paralelos.
import { adaptNavigationTheme } from "react-native-paper";
import { DefaultTheme, DarkTheme } from "@react-navigation/native";
const { LightTheme, DarkTheme: NavDark } = adaptNavigationTheme({
reactNavigationLight: DefaultTheme,
reactNavigationDark: DarkTheme,
materialLight: lightTheme,
materialDark: darkTheme,
});Os cabeçalhos de navegação captam primary e card do Paper - evita azuis incompatíveis entre a barra de aplicativos e os botões.
import type { MD3Theme } from "react-native-paper";
export const lightTheme: MD3Theme = { ... };Text variant é uma união de nomes de tipografia MD3 - autocompletar no IDE.PaperProvider ausente - Componentes renderizam com tema padrão; cores personalizadas ignoradas. Correção: Envolva na raiz, dentro de SafeAreaProvider.
Hexadecimais codificados em telas - Quebra o modo escuro. Correção: Use useTheme().colors.primary ou componentes Paper que leem o tema automaticamente.
Usuários de iOS esperando Cupertino - Paper lê Material em ambas as plataformas. Correção: Use Paper para apps com foco em Android; considere @expo/ui ou primitivas personalizadas para chrome nativo do iOS.
TextInput atrás do teclado - Campos contornados precisam de KeyboardAvoidingView no iOS. Correção: Envolva telas de formulário; teste em iPhones pequenos.
Ripple no iOS - Paper simula feedback; não é idêntico ao Material Android. Correção: Aceite as diferenças da plataforma ou personalize android_ripple via tema.
Mistura de Paper e Text RN sem estilo - O ritmo da tipografia se desvia. Correção: Use Paper Text com variant dentro de telas Paper.
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| React Native Paper | MD3, foco em Android, formulários e diálogos | Marca totalmente personalizada não-Material |
| Tamagui / NativeWind | Linguagem de design personalizada | Você quer widgets MD3 pré-construídos |
| @expo/ui | Controles nativos SwiftUI/Compose | Elevação e ripple específicos do Material |
| react-native-elements | Projetos legados já em RNE | Apps Greenfield MD3 - prefira Paper |
Sim. npx expo install react-native-paper react-native-safe-area-context. Nenhum plugin nativo é necessário para uso padrão.
Fora da navegação, mas dentro da área segura - tipicamente envolvendo NavigationContainer em App.tsx ou layout raiz. Um provedor por app.
Substitua colors.primary (e onPrimary) nos spreads de MD3LightTheme / MD3DarkTheme. Mantenha as proporções de contraste para acessibilidade - veja Noções Básicas de Acessibilidade.
Passe configureFonts({ config: { fontFamily: "Inter-Regular" } }) para o tema após carregar fontes com expo-font. Veja Escala de Tipografia e Carregamento de Fontes.
Construa darkTheme a partir de MD3DarkTheme, selecione com useColorScheme, passe para PaperProvider. Sincronize StatusBar e navegação via adaptNavigationTheme.
Paper envia componentes MD3 opinativos. Tamagui envia primitivas de tokens que você estiliza. Escolha Paper quando os padrões Material forem o produto; Tamagui quando a marca for personalizada.
Paper define papéis em muitos primitivos, mas você ainda deve fornecer accessibilityLabel em botões apenas com ícones e testar com VoiceOver/TalkBack. Veja accessibilityLabel & accessibilityRole.
Versões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026