# Guía de Responsividad - OpenCCB ## Principios Mobile-First ### Breakpoints (Tailwind CSS) ```css /* Mobile: Default (0-639px) */ /* sm: 640px+ */ /* md: 768px+ */ /* lg: 1024px+ */ /* xl: 1280px+ */ /* 2xl: 1536px+ */ ``` ### Jerarquía de Diseño 1. **Mobile (< 640px)**: Diseño de una sola columna, menú hamburguesa 2. **Tablet (640px - 1024px)**: 2 columnas, navegación visible 3. **Desktop (1024px+)**: Layout completo, todas las características --- ## Componentes Responsivos ### Layout Principal ```tsx // Mobile-first container
{/* Header responsivo */}
{/* Logo y navegación */}
{/* Contenido principal */}
{children}
``` ### Navegación **Mobile:** - Menú hamburguesa (ícono) - Sidebar deslizante desde la derecha - Overlay con backdrop blur - Items de navegación en columna **Desktop:** - Navegación horizontal visible - Dropdowns al hacer hover/click - Items en fila con espaciado ### Tarjetas de Cursos ```tsx // Grid responsivo
{courses.map(course => ( ))}
``` ### Tablas de Datos **Mobile:** - Scroll horizontal - O tarjetas apiladas en lugar de tabla **Desktop:** - Tabla completa visible ```tsx
{/* tabla */}
``` --- ## Tipografía Fluida ```tsx // Títulos responsivos

Título

// Texto de párrafo

Contenido

// Texto pequeño Metadata ``` --- ## Espaciado Responsivo ```tsx // Padding responsivo
{/* contenido */}
// Gap responsivo
{/* items */}
``` --- ## Componentes Específicos ### AppHeader (Experience) **Mobile (< 768px):** - Logo compacto - Íconos de notificación y tema - Botón de menú hamburguesa - Sidebar deslizante con: - Navegación completa - Selector de idioma - Toggle de tema - Perfil de usuario - Botón de logout **Desktop (≥ 768px):** - Logo completo - Navegación horizontal visible - Íconos de notificación, idioma, tema - Perfil de usuario visible - Botón de logout ### Navbar (Studio) **Mobile (< 768px):** - Logo compacto - Dropdowns colapsados - Toggle de tema - Selector de idioma - Botón de menú hamburguesa - Sidebar deslizante **Desktop (≥ 768px):** - Logo completo - Dropdowns visibles - Toggle de tema - Selector de idioma - Información de usuario visible ### Reproductor de Lecciones **Mobile:** - Video en ancho completo - Controles simplificados - Pestañas colapsadas (acordeón) - Navegación entre lecciones (botones) **Desktop:** - Video con tamaño fijo - Sidebar con navegación de lecciones - Pestañas visibles - Panel de transcripción/resumen --- ## Imágenes y Multimedia ```tsx // Imágenes responsivas {alt} // Video responsivo
``` --- ## Accesibilidad ### Navegación por Teclado - Todos los elementos interactivos deben ser focusables - Orden de tab lógico - Indicadores de focus visibles ### Screen Readers - Labels descriptivos en botones e íconos - `aria-label` en íconos sin texto - `aria-expanded` en elementos colapsables - `aria-modal` en diálogos ### Contraste - Relación de contraste mínima 4.5:1 - Texto grande: 3:1 mínimo --- ## Pruebas de Responsividad ### Dispositivos de Prueba **Chrome DevTools:** - iPhone SE (375x667) - iPhone 12 Pro (390x844) - iPad Air (820x1180) - iPad Pro (1024x1366) - Desktop (1920x1080) **Herramientas:** - Chrome DevTools Device Mode - Firefox Responsive Design Mode - BrowserStack (dispositivos reales) ### Checklist de Pruebas - [ ] Navegación funciona en mobile - [ ] Menús desplegables accesibles - [ ] Formularios usables en pantallas pequeñas - [ ] Tablas con scroll horizontal o versión mobile - [ ] Imágenes se escalan correctamente - [ ] Texto legible sin zoom - [ ] Botones táctiles (mínimo 44x44px) - [ ] Sin overflow horizontal no intencional - [ ] Layout no se rompe en tamaños extremos --- ## Patrones Comunes ### Mobile: Navegación Inferior ```tsx ``` ### Desktop: Sidebar Fija ```tsx ``` ### Tablas Responsivas ```tsx // Opción 1: Scroll horizontal
{/* tabla completa */}
// Opción 2: Tarjetas en mobile
{items.map(item => ( ))}
{/* tabla completa */}
``` --- ## Rendimiento ### Lazy Loading ```tsx // Imágenes {alt} // Componentes pesados const HeavyComponent = dynamic(() => import('./HeavyComponent'), { loading: () =>

Cargando...

, ssr: false, }) ``` ### Code Splitting ```tsx // Carga diferida por ruta const CourseDetail = dynamic(() => import('@/components/CourseDetail')) ``` --- ## Referencias - [Tailwind CSS Responsive Design](https://tailwindcss.com/docs/responsive-design) - [MDN Responsive Design](https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design) - [Web.dev Responsive Design](https://web.dev/responsive-web-design-basics/) --- **Última actualización**: 2026-03-20 **Versión**: 1.0