- Suposición predeterminada: lógica de negocio compartida, chrome nativo de plataforma donde las convenciones del SO difieren (back, sheets, permisos).
- Cada decisión clasifica opciones - elige Mejor a menos que el cumplimiento, cronograma, o marca lo ordene de otro modo.
- Registra la clasificación elegida, fecha, y disensión en un ADR breve o comentario de ticket - vincula capturas de pantalla de iOS + Android.
- Revisa cuando agregues flujos llenos de gestos, Material You theming, o Android 15 predictive back.
Escenario: Multi-paso checkout dentro de un stack; los usuarios esperan ir atrás sin perder el estado del carrito.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Back nativo de plataforma | iOS swipe-from-edge + header back; Android hardware/gesture back vía Expo Router stack |
| 2do | Custom header back con lógica compartida | Un handler onBack; iconos de plataforma del design system |
| 3ro | Botón floating universal de atrás | FAB en la esquina inferior izquierda - aceptable solo en juegos o medios inmersivos |
Opción incorrecta: Deshabilitar el back del sistema en Android para forzar un botón de texto "Back" centrado - los usuarios abandonan la aplicación cuando el gesture back sale de la app inesperadamente.
Por qué lo mejor es lo mejor: Los usuarios tienen memoria muscular de la navegación del SO. Router router.back() conectado a header y Android BackHandler preserva el estado sin luchar contra la plataforma.
Escenario: Formulario de signup largo; el CTA primario debe ser obvio en ambas plataformas.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Sticky footer CTA (compartido) | Botón ancho completo sobre safe area; keyboard avoidance probado en ambos SO |
| 2do | iOS top-right text action + Android FAB | Divergencia documentada para aplicaciones de usuarios avanzados |
| 3ro | Submit inline después del último campo solo | Aceptable para flujos de 2 campos |
Opción incorrecta: iOS-only top-right "Done" sin Android equivalente escondido en menú overflow - los usuarios de Android nunca encuentran submit.
Por qué lo mejor es lo mejor: Sticky footer sobrevive keyboard y dynamic type; una matriz de QA de layout. El posicionamiento específico de plataforma duplica costos de diseño y prueba por ganancia UX marginal.
Escenario: Programar cita; selecciona fecha + hora con validación.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Pickers de plataforma | @react-native-community/datetimepicker - spinner en iOS, calendar/dialog en Android |
| 2do | Custom picker bottom sheet unificado | Aplicaciones de programación críticas para la marca con presupuesto de motion |
| 3ro | Calendario inline estilo web siempre visible | Solo en layouts de tablet |
Opción incorrecta: Forzar el estilo del wheel picker de iOS en Android - se siente extranjero y falla expectativas de TalkBack/VoiceOver.
Por qué lo mejor es lo mejor: Los pickers nativos se entregan rápido, respetan locale, y pasan escrutinio de accesibilidad de la tienda. Los pickers personalizados necesitan spikes - Trabajando con Diseño y Movimiento.
Escenario: El usuario comparte un enlace de referral o exporta un PDF desde una pantalla de detalle.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | expo-sharing + system share sheet | Objetivos nativos del SO (Messages, Drive, etc.) |
| 2do | Custom in-app share targets | Cuando analytics requieren seguimiento de canal por tap |
| 3ro | Copiar enlace solo | MVP aceptable; expande antes de campañas de crecimiento |
Opción incorrecta: Reconstruir toda el share sheet del SO en RN - pesadilla de mantenimiento; nunca coincide con apps instaladas.
Por qué lo mejor es lo mejor: System sheets se actualizan con el SO - nuevos objetivos aparecen sin entregas de app. La UI personalizada es diferenciación de producto, no predeterminada.
Escenario: La app tiene 4-5 destinos de nivel superior; PM quiere "igual que web sidebar."
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Bottom tabs (teléfono) | Expo Router (tabs) - alcanzable por pulgar; convenciones de Material/iOS tab bar |
| 2do | Drawer en Android + tabs en iOS | Documenta divergencia; raro a menos que aplicaciones admin empresariales |
| 3ro | Navegación hamburger-only | Aceptable para 6+ destinos con IA clara |
Opción incorrecta: Sidebar izquierdo permanente en portrait de teléfono - desperdicia espacio horizontal; lucha contra el uso con una mano.
Por qué lo mejor es lo mejor: La IA móvil centra bottom tabs; tablet puede usar split view después. El mental model de web sidebar no se transfiere a 390px width.
Escenario: Confirmar eliminación destructiva; necesitas atención del usuario sin perder contexto.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Platform alert / action sheet | Alert.alert simple; @expo/react-native-action-sheet para 3+ acciones |
| 2do | Bottom sheet (compartido) | @gorhom/bottom-sheet - coincide con modern iOS sheet + Android bottom dialog |
| 3ro | Modal centrado estilo web | Solo desktop tablet |
Opción incorrecta: Modal de bloqueo de pantalla completa sin gesto de descartar en Android - viola expectativas de Material back.
Por qué lo mejor es lo mejor: Las confirmaciones destructivas mapean limpiamente a diálogos de plataforma. Los sheets se escalan a contenido rico; los modales centrados se sienten importados de web en teléfonos.
Escenario: Actualización de feed list; la marca tiene animación de carga personalizada.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Platform refresh control | RefreshControl con token de color tint de marca |
| 2do | Custom Lottie header | Aplicaciones marketing-heavy; presupuesto Reanimated + scroll sync |
| 3ro | Manual refresh button solo | Listas offline-first donde el gesto de pull conflictúa con row swipe |
Opción incorrecta: Deshabilitar pull-to-refresh en iOS solo porque la animación personalizada era Android-only - los usuarios reportan "roto" en reseñas de App Store.
Por qué lo mejor es lo mejor: RefreshControl es una prop; tint alinea marca sin physics de scroll personalizados. El refresh personalizado necesita Resolución de Conflictos de Gesto.
Escenario: La marca usa fuente personalizada; el texto del body debe sentirse nativo.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Custom brand font + system fallback stack | Carga con expo-font; SF Pro / Roboto fallback para CJK y glifos faltantes |
| 2do | Platform system font para body, brand para display | Reduce bundle; ritmo ligeramente diferente entre plataformas |
| 3ro | Archivos de fuente web idénticos en ambas plataformas | Aceptable cuando marketing ordena paridad de píxeles |
Opción incorrecta: Asumir que archivos de Google Fonts web se renderizan idénticamente en iOS sin probar diacríticos y tabular nums.
Por qué lo mejor es lo mejor: La legibilidad móvil y el tamaño del bundle importan. La tipografía tokenizada de Design Systems Basics documenta qué roles usan marca vs sistema.
Escenario: Acceso a cámara para foto de perfil; la tienda requiere strings de propósito claros.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Pantalla de educación in-app → system prompt | Misma copia ambas plataformas; Info.plist + AndroidManifest strings localizados |
| 2do | iOS pre-prompt solo (Android va directo a system) | Aceptable - Android no tiene patrón oficial de pre-prompt |
| 3ro | Custom fake "permission" UI que no sea system dialog | Engañoso; riesgo de rechazo de tienda |
Opción incorrecta: Texto de ratificación de permisos diferente por plataforma sin revisión legal - falla de cumplimiento en contratos empresariales.
Por qué lo mejor es lo mejor: Un flujo de educación; el diálogo nativo aún está controlado por el SO. Documenta la ruta "don't ask again" de Android en macros de soporte.
Escenario: Éxito de pago, error de formulario, toggle favorito - la spec de diseño incluye haptic feedback.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | iOS expo-haptics + Android short vibration fallback | Mapea eventos semánticos: éxito → notification success; error → error pattern |
| 2do | iOS haptics solo; Android silencioso | Divergencia documentada para delight de baja prioridad |
| 3ro | Vibración larga idéntica en ambas plataformas | Se siente agresivo en iPhone; evita |
Opción incorrecta: Llamar haptics en cada list scroll tick - drenaje de batería y quejas de App Store "feedback excesivo".
Por qué lo mejor es lo mejor: El mapeo semántico preserva intención sin pretender que el hardware es idéntico. La amplitud de vibración de Android varía por OEM - mantén patrones cortos.
Escenario: La app soporta dark mode; Android Material You extrae colores de wallpaper.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Shared semantic tokens + platform theme provider | useColorScheme + Theming & Brand Flavors |
| 2do | Paleta hex idéntica en ambos modos | Sin dynamic color en Android 12+ |
| 3ro | Light mode solo | Aceptable corto plazo; documenta deuda |
Opción incorrecta: Hard-coded #FFFFFF backgrounds - Android dark mode e iOS smart invert rompen layouts.
Por qué lo mejor es lo mejor: Los tokens semánticos surface, textPrimary absorben el tema de plataforma sin redibujar cada pantalla en Figma.
Escenario: Marketing quiere opt-in de push al primer lanzamiento; engineering prefiere contextual prompt.
| Clasificación | Opción | Enfoque |
|---|
| Mejor | Contextual prompt después del primer momento de valor | por ejemplo, después del primer pedido - opt-in más alto, misma API ambas plataformas |
| 2do | iOS provisional / Android notification channels | APIs específicas de plataforma con doc de timing de producto compartida |
| 3ro | Modal de día de lanzamiento | Solo si cumplimiento ordena; espera opt-in más bajo |
Opción incorrecta: iOS system prompt en cold start antes de login - Apple Human Interface Guidelines desalienta; usuarios tocan Don't Allow permanentemente.
Por qué lo mejor es lo mejor: El timing es política de producto; la implementación usa expo-notifications una vez. La divergencia es cuándo, no si, preguntar.
¿Deben verse iOS y Android idénticos?
No - deben sentirse coherentes. IA compartida, tokens, y copy; navegación nativa y componentes del sistema pueden diferir. Documenta deltas intencionales en ADRs.
¿Quién aprueba la divergencia de plataforma?
PM + design lead + engineering lead. QA recibe una parity matrix listando pantallas que difieren - no una captura de pantalla única dorada.
¿Cómo prevenimos drift accidental?
PR template requiere capturas de pantalla de iOS + Android para cambios UI. CI preview builds en ambas plataformas. Drift no intencional es un bug; intencional es documentado.
¿Qué hay de layouts de tablet y foldable?
Trata como decisiones separadas - phone parity primero. Los foldables pueden seguir Android Material adaptive guidelines mientras iPad usa split navigation.
¿Expo Router fuerza paridad?
La estructura de archivo del Router es compartida; opciones de presentación (presentation: "modal") pueden divergir por plataforma con Platform.select - aún así documenta la elección.
Stack versions: Esta página fue escrita para React 19.2.3, React Native 0.86.0, y Expo SDK 57 (expo ~57.0.4).