React Native Paper
Componentes de Material Design y temas para UX orientada a Android.
Busca en todas las páginas de la documentación
Componentes de Material Design y temas para UX orientada a Android.
React Native Paper implementa Material Design 3 para React Native: botones, campos de texto, diálogos, chips y superficies con roles de accesibilidad integrados y retroalimentación de ripple. En Expo SDK 57, combina PaperProvider con temas MD3 y opcionalmente adapta React Navigation para que encabezados y pestañas coincidan con tu paleta.
Tarjeta de receta de referencia rápida - lista para copiar y pegar.
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: "Bandeja de entrada" }} />
</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="¡Hola!" subtitle="Material 3 en Expo" />
<Card.Content>
<Text variant="bodyMedium">Compone formularios y acciones a partir de primitivos de Paper.</Text>
</Card.Content>
<Card.Actions>
<Button mode="text">Descartar</Button>
<Button mode="contained">Continuar</Button>
</Card.Actions>
</Card>
<TextInput mode="outlined" label="Correo electrónico" placeholder="tu@ejemplo.com" />
</View>
);
}Cuándo usar esto:
adaptNavigationTheme.Button, FAB y Searchbar de Paper envían patrones listos para producción.Flujo de inicio de sesión con temas MD3, proveedor de iconos, retroalimentación de snackbar y modo oscuro.
// 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("Ingresa un correo electrónico válido");
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">Inicia sesión</Text>
<TextInput
mode="outlined"
label="Correo electrónico"
value={email}
onChangeText={setEmail}
keyboardType="email-address"
autoCapitalize="none"
error={!!error}
accessibilityLabel="Dirección de correo electrónico"
/>
<HelperText type="error" visible={!!error}>
{error}
</HelperText>
<Button mode="contained" onPress={handleSubmit} accessibilityLabel="Inicia sesión">
Inicia sesión
</Button>
</View>
<Snackbar visible={snack} onDismiss={() => setSnack(false)} duration={3000}>
Sesión iniciada como {email}
</Snackbar>
</KeyboardAvoidingView>
);
}Lo que esto demuestra:
PaperProvider suministra tema MD3 a todos los componentes de Paper - colores, roundness, fuentes, ripple.adaptNavigationTheme alinea los colores del encabezado/pestaña de React Navigation con los roles primary y surface de Paper.Text variant="headlineMedium" usa la escala de tipografía MD3 - no fontSize sin procesar.HelperText + prop error en TextInput - patrón de validación accesible.Snackbar para retroalimentación transitoria sin infraestructura de toast personalizada.primary, onPrimary, primaryContainer, surface, onSurface, outline, etc. Los componentes de Paper consumen roles, no hex arbitrarios.PaperProvider - React context para tema, iconos (settings.icon) y configuración de ripple.useTheme() de Paper devuelve el MD3Theme activo dentro de cualquier componente hijo.mode - Button mode="contained|outlined|text|elevated", Card mode="elevated|outlined|contained".MaterialCommunityIcons de react-native-vector-icons por defecto; anula mediante settings.icon en el proveedor.import { MD3LightTheme } from "react-native-paper";
const theme = {
...MD3LightTheme,
colors: {
...MD3LightTheme.colors,
primary: "#2563eb", // acciones de marca
onPrimary: "#ffffff", // texto en botones primarios
surface: "#ffffff", // tarjetas, hojas
onSurface: "#1c1b1f", // texto del cuerpo en surface
background: "#f8fafc", // fondo de pantalla
},
roundness: 10, // línea de base de radio de esquina global
};Mapea tus tokens semánticos de Design Systems Basics a roles MD3 - no inventes nombres 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,
});Los encabezados de navegación toman primary y card de Paper - evita azules desajustados entre la barra de aplicación y los botones.
import type { MD3Theme } from "react-native-paper";
export const lightTheme: MD3Theme = { ... };variant de Text es una unión de nombres de tipografía MD3 - autocompletado en IDE.Falta PaperProvider - Los componentes se renderizan con tema predeterminado; colores personalizados ignorados. Solución: Envuelve en la raíz, dentro de SafeAreaProvider.
Hex codificado en pantallas - Rompe el modo oscuro. Solución: Usa useTheme().colors.primary o componentes Paper que leen el tema automáticamente.
Usuarios de iOS esperando Cupertino - Paper se ve Material en ambas plataformas. Solución: Usa Paper para apps Android-primary; considera @expo/ui o primitivos personalizados para chrome iOS nativo.
TextInput detrás del teclado - Los campos destacados necesitan KeyboardAvoidingView en iOS. Solución: Envuelve pantallas de formulario; prueba en iPhones pequeños.
Ripple en iOS - Paper simula retroalimentación; no es exactamente Material Android. Solución: Acepta diferencias de plataforma o personaliza android_ripple mediante tema.
Mezclar Paper y RN Text sin estilo - El ritmo tipográfico se desvía. Solución: Usa Paper Text con variant dentro de pantallas Paper.
| Alternativa | Usa cuando | No uses cuando |
|---|---|---|
| React Native Paper | MD3, Android-first, formularios y diálogos | Marca completamente personalizada no-Material |
| Tamagui / NativeWind | Lenguaje de diseño personalizado | Quieres widgets MD3 preconstruidos |
| @expo/ui | Controles nativos SwiftUI/Compose | Elevación y ripple específicos de Material |
| react-native-elements | Proyectos heredados ya en RNE | Apps MD3 greenfield - prefiere Paper |
Sí. npx expo install react-native-paper react-native-safe-area-context. No se requiere plugin de configuración nativa para uso estándar.
Fuera de navegación pero dentro del área segura - típicamente envolviendo NavigationContainer en App.tsx o diseño de raíz. Un proveedor por app.
Anula colors.primary (y onPrimary) en spreads de MD3LightTheme / MD3DarkTheme. Mantén ratios de contraste para accesibilidad - consulta Accessibility Basics.
Pasa configureFonts({ config: { fontFamily: "Inter-Regular" } }) al tema después de cargar fuentes con expo-font. Consulta Typography Scale & Font Loading.
Construye darkTheme desde MD3DarkTheme, selecciona con useColorScheme, pasa a PaperProvider. Sincroniza StatusBar y navegación mediante adaptNavigationTheme.
Paper envía componentes MD3 con opinión. Tamagui envía primitivos de token que estilizas. Elige Paper cuando los patrones Material son el producto; Tamagui cuando la marca es personalizada.
Paper establece roles en muchos primitivos, pero aún debes proporcionar accessibilityLabel en botones solo de icono y prueba con VoiceOver/TalkBack. Consulta accessibilityLabel & accessibilityRole.
Versiones de stack: Esta página fue escrita para React 19.2.3, React Native 0.86.0, y Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última actualización: 16 jul 2026