¿Qué hace Sistema de Diseño de Bottom Sheet?
Propósito
El Sistema de Diseño de Bottom Sheet proporciona un marco de diseño estandarizado y móvil-first para paneles deslizables hacia arriba (bottom sheets), hojas de acción y cajones modales en interfaces web y aplicaciones web progresivas (PWAs). Los dispositivos móviles modernos con relaciones de aspecto grandes dificultan alcanzar superposiciones en la parte superior o modales centrados con una sola mano. Los bottom sheets anclan tareas interactivas, menús contextuales, controles de filtro y subvistas detalladas en la parte inferior de la pantalla, dentro del alcance natural del pulgar del usuario.
Diseñar un sistema de bottom sheet efectivo requiere establecer alturas de encaje (reducido/colapsado, parcial/media altura, altura completa), asideros de arrastre táctiles (agarraderas), oscurecimiento de fondo (scrim/backdrop), mecanismos de bloqueo del scroll del cuerpo, márgenes de área segura del viewport (env(safe-area-inset-bottom)) y una transformación responsive fluida en escritorio (convirtiendo bottom sheets en modales centrados o popovers en viewports más anchos).
Casos de Uso
- Selectores de Opciones de Producto Móvil: Presentar selectores de talla, color, cantidad y cadencia de suscripción en páginas de detalle de producto de comercio electrónico sin salir de la PDP.
- Controles de Filtro y Ordenación Móviles: Proporcionar opciones de filtrado multifacético para páginas de catálogo de comercio electrónico o vistas de búsqueda de SaaS con barras de acción persistentes de "Aplicar Filtros" en la parte inferior.
- Hojas de Acción Contextuales: Activar acciones rápidas de 1 toque (Compartir, Marcar, Agregar a Lista, Reportar) en feeds sociales, tarjetas multimedia o tablas de datos.
- Tarjetas de Detalle de Ubicación y Mapas: Mostrar detalles expandibles de puntos de interés o cronologías de seguimiento de entrega que se deslizan sobre vistas de mapa (altura de encaje reducida a expandida completa).
- Subflujos de Trabajo Móviles de Varios Pasos: Completar tareas rápidas en línea como selección de método de pago en checkout, selección de dirección o envío rápido de comentarios.
Cuándo NO Usar
- Enrutamiento de Navegación Global: Para la navegación principal de la aplicación entre secciones principales, usar
bottom-navigation-systemosite-navigation-system. - Alertas de Confirmación Destructivas: Para acciones críticas e irreversibles (por ejemplo, "Eliminar Cuenta"), usar un modal de diálogo centrado
overlay-and-dialog-system(role="alertdialog") que exija confirmación explícita. - Contenido Plegable en Página: Para alternar contenido expandible en línea dentro del flujo de la página, usar
accordion-ui-systemotab-ui-system. - Diseños de Escritorio de Pantalla Ancha (>1024px): No mostrar bottom sheets de ancho completo en pantallas de escritorio. Adaptar la interfaz de usuario a diálogos modales centrados (
overlay-and-dialog-system), cajones laterales (dashboard-layout-system) o popovers anclados (tooltip-and-hint-system).
Entradas
- Tipo de Tarea y Profundidad: Naturaleza del contenido (lista de acciones rápidas de 1 toque vs. formulario de varios campos vs. lista de detalles desplazable).
- Configuración de Encaje: Elección de alturas de encaje (Encaje Único: 100% altura completa; Encaje Doble: 50% mitad y 100% completa; Encaje Triple: 20% reducido, 50% mitad, 90% completo).
- Contexto del Disparador: Elemento o acción del usuario que inicia el panel (toque en botón, pulsación larga, gesto de deslizamiento o enlace profundo).
- Tokens de Diseño: Colores de fondo de superficie, radio de borde, dimensiones del asidero de arrastre, sombras de elevación, opacidad del fondo y escala tipográfica.
- Estrategia de Adaptación de Escritorio: Transición de diseño elegida para viewports ≥1024px (Convertir a Modal Centrado, Convertir a Popover Anclado o Convertir a Cajón Lateral Deslizante).
Salidas
- Especificación de Anatomía del Bottom Sheet: Plano de diseño que define la Barra de Asidero de Arrastre, el Encabezado (Título + Botón de Cierre), el Cuerpo Desplazable, el Pie de Página Fijo (Barra CTA) y el Relleno de Área Segura.
- Matriz de Altura de Encaje y Token de Gesto: Variables CSS y definiciones de umbral de encaje (
--sheet-detent-peek,--sheet-detent-half,--sheet-detent-full) con reglas de descarte por velocidad de arrastre. - Especificación de Fondo y Elevación: Tokens de opacidad del fondo, configuración de filtro de desenfoque del fondo, jerarquía de z-index y reglas de bloqueo del scroll del cuerpo (
overflow: hiddenen el body). - Mapeo ARIA para Teclado y Lector de Pantalla:
role="dialog",aria-modal="true",aria-labelledby, especificación de trampa de foco y definiciones del controlador de teclaEscape. - Plano de Adaptación Responsive de Escritorio: Puntos de interrupción de media query que transforman bottom sheets móviles en diálogos modales centrados o popovers para tablet y escritorio.
Flujo de Trabajo
1. Categorizar el Tipo de Panel y la Estructura de Encaje
Seleccionar el modo de encaje apropiado según el volumen de contenido y la frecuencia de interacción:
- Hoja de Acción No Modal (Encaje Reducido/Ajuste al Contenido): Se autoajusta para contenido corto (2–5 acciones de menú). Las alturas suelen oscilar entre 180px y 320px. Se descarta al seleccionar una acción o al tocar el fondo.
- Panel de Media Altura/Encaje Doble (50% y 90% del Viewport): Se utiliza para tareas de densidad media como selección de variantes de producto o clasificación. Se abre al 50% de altura (
50vh); al arrastrar hacia arriba, encaja al 90% de altura (90vh). - Panel de Altura Completa/Expandido (90%–100% del Viewport): Se utiliza para flujos de trabajo móviles complejos como filtros multifacéticos o pasos de checkout. Proporciona un encabezado y pie de página fijos con un cuerpo interno desplazable.
2. Definir la Anatomía Visual y la Jerarquía Espacial
Construir el panel utilizando cinco capas anatómicas distintas:
- Fondo (Scrim): Superposición fija que cubre todo el viewport (
background: rgba(0, 0, 0, 0.5); backdrop-filter: blur(4px); z-index: 1000;). - Contenedor del Panel: Panel fijo anclado al borde inferior de la pantalla (
position: fixed; bottom: 0; left: 0; right: 0; border-radius: 16px 16px 0 0; background: var(--surface-bg); z-index: 1001;). - Barra de Asidero de Arrastre (Affordance): Píldora visual centrada en la parte superior (
width: 36px; height: 5px; border-radius: 999px; background: var(--border-neutral); margin: 8px auto; cursor: grab;). - Capa de Encabezado: Contiene el título del panel (
h2), subtítulo opcional y botón de cierre explícito (<button aria-label="Cerrar panel">✕</button>). - Capa de Cuerpo Desplazable: Contenedor de contenido interno configurado con
overflow-y: auto; -webkit-overflow-scrolling: touch;. - Capa de Pie de Página Fijo CTA: Barra de acción anclada en la parte inferior con botones primario/secundario y relleno de área segura (
padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px))).
3. Establecer Gestos, Encaje y Mecanismos de Descarte
Configurar interacciones táctiles suaves para retroalimentación de gestos físicos:
- Interacción de Asidero de Arrastre: Arrastrar hacia abajo sobre el asidero o el encabezado mueve el panel hacia abajo suavemente usando
transform: translateY(). - Umbrales de Encaje:
- Si se arrastra hacia abajo más allá del 30% de la altura actual o se desliza hacia abajo con una velocidad > 0.5px/ms, activar el cierre completo.
- Si se arrastra entre el 30% y el 70% en modo de encaje doble, encajar en el encaje más cercano (50% o 90%).
- Colisión de Bloqueo de Scroll: Al arrastrar dentro de la capa de cuerpo desplazable, solo iniciar el arrastre para descartar el panel si la posición de scroll del cuerpo está en
scrollTop === 0y el usuario desliza hacia abajo. - Bloqueo de Scroll del Cuerpo: Cuando el panel modal inferior está abierto, aplicar
overflow: hiddenaldocument.bodypara evitar fugas de scroll de la página de fondo.
4. Implementar Áreas Seguras del Viewport y Contraste de Superficie
Asegurar la integración visual completa con recortes de pantalla de hardware móvil y modos claro/oscuro:
- Manejo de Área Segura: Aplicar siempre
padding-bottom: env(safe-area-inset-bottom, 16px)al contenedor del panel o al pie de página fijo para que el contenido/los botones no queden cubiertos por los indicadores de inicio de iOS. - Límite de Altura Máxima: Limitar los paneles de altura completa a
max-height: calc(100vh - 48px)omax-height: calc(100dvh - 48px)para dejar una porción visible de 48px del contexto de la página principal oscurecida en la parte superior. - Elevación de Superficie: Usar tokens de sombra de elevación profunda (
box-shadow: 0 -4px 24px rgba(0, 0, 0, 0.15)) para crear separación del contenido de la página de fondo.
5. Configurar Accesibilidad y Navegación por Teclado
Asegurar el cumplimiento total de los estándares WCAG 2.1 / 2.2 AA:
- Roles ARIA: El contenedor debe usar
role="dialog"orole="region"(para paneles reducidos no modales),aria-modal="true"yaria-labelledby="sheet-title-id". - Gestión de Foco:
- Al abrir, mover programáticamente el foco al primer elemento enfocable dentro del panel o al botón de cierre.
- Implementar una trampa de foco que impida que
TaboShift+Tabsalgan del panel hacia el fondo inerte. - Al cerrar, restaurar el foco al elemento disparador que abrió el panel.
- Controles de Teclado: Al presionar
Escape, el panel debe cerrarse inmediatamente. - Anuncios del Lector de Pantalla: Los cambios de contenido dinámico dentro del panel deben usar regiones
aria-live="polite".
6. Diseñar la Adaptación Responsive de Escritorio
Los bottom sheets se ven poco pulidos cuando se estiran a lo ancho completo en monitores de escritorio (≥1024px). Implementar reglas explícitas de transformación responsive:
- Modo Modal de Escritorio (Predeterminado): En viewports ≥1024px, transformar el bottom sheet en un diálogo modal centrado (
width: 100%; max-width: 540px; border-radius: 16px; margin: auto; position: fixed; top: 50%; left: 50%; transform: translate(-50%, -50%);). - Modo Popover de Escritorio (Menús Contextuales): Para hojas de acción rápidas, transformar el panel en un popover anclado posicionado adyacente al botón disparador.
- Modo Cajón Lateral de Escritorio (Formularios/Filtros Complejos): Para filtros multifacéticos profundos o flujos de varios pasos, transformar en un cajón lateral deslizante alineado a la derecha (
width: 400px; height: 100vh; top: 0; right: 0; border-radius: 16px 0 0 16px;).
Reglas de Decisión
Matriz de Selección de Encaje
| Tipo de Panel | Configuración de Encaje | Volumen de Contenido | Caso de Uso Ideal |
|---|---|---|---|
| Hoja de Acción | Ajuste al contenido (Encaje Único) | 2–6 enlaces/ítems de acción | Compartir rápido, menú contextual, cambio de opción simple. |
| Panel de Selección | Encaje Doble (50vh inicial, 90vh expandido) | 5–15 ítems desplazables | Selector de talla/color de producto, selector de dirección, método de pago. |
| Cajón Interactivo | Encaje Triple (120px reducido, 50vh, 90vh) | Datos espaciales/de mapa complejos | Tarjetas de mapa de seguimiento de entrega, paradas de tránsito en vivo, detalles de viaje compartido. |
| Panel de Flujo Completo | Encaje Único (90vh - 100vh fijo) | Formulario / filtros de varias secciones | Multifiltros de catálogo, paso de checkout móvil, flujo de trabajo de encuesta. |
Elección de Transformación de Escritorio
- Usar Modal Centrado: Cuando el panel contiene formularios estructurados, selectores de variantes u opciones de checkout.
- Usar Popover Anclado: Cuando el panel contiene acciones contextuales cortas (Compartir, Editar, Eliminar).
- Usar Cajón Lateral: Cuando el panel contiene controles de filtro o paneles de edición en tableros y tablas de datos.
Restricciones
- Accesibilidad (WCAG 2.1 / 2.2 AA):
- Debe proporcionar una trampa de foco explícita cuando
aria-modal="true"esté activo. - Los objetivos táctiles para todos los elementos internos y botones de cierre deben medir al menos 44x44px (WCAG 2.5.8 / 2.5.5).
- El contenido de fondo detrás de los paneles modales inferiores debe marcarse como
inertu ocultarse de la tecnología de asistencia.
- Debe proporcionar una trampa de foco explícita cuando
- Tamaño Táctil y de Gestos:
- El objetivo de impacto del asidero de arrastre debe ampliarse con relleno invisible (
min-height: 24px,min-width: 60px) incluso si el asidero visual es de 36x5px.
- El objetivo de impacto del asidero de arrastre debe ampliarse con relleno invisible (
- Unidades Dinámicas del Viewport:
- Usar
dvh(altura de viewport dinámica) donde sea compatible (height: 90dvh), con respaldo avhpara adaptarse a las expansiones y contracciones dinámicas de la barra de direcciones móvil.
- Usar
Patrones de Falla Comunes
- La Falta de Relleno de Área Segura: Omitir
env(safe-area-inset-bottom), lo que hace que los botones de acción del pie de página principal se superpongan con las barras de gestos de iOS. - Paneles de Escritorio de Ancho Completo Estirados: Permitir que un bottom sheet móvil se expanda a 1920px de ancho en monitores de escritorio.
- Bloqueo por Secuestro de Scroll: No separar el desplazamiento del contenido de los gestos de arrastre para descartar el panel, lo que provoca que el panel se colapse cuando el usuario intenta desplazarse hacia abajo a través del texto.
- Falta del Controlador de Escape del Teclado: Omitir el listener del evento de tecla
Escape, atrapando a los usuarios de teclado de escritorio dentro de la superposición del panel modal. - Fuga de Foco al Fondo: Dejar que los elementos de la página de fondo sean accesibles mediante la tecla
Tabmientras un panel modal inferior está abierto.
Criterios de Validación
- El diseño del panel incluye affordance de arrastre visual explícito, encabezado con título, cuerpo desplazable y pie de página fijo.
- El margen de área segura (
padding-bottom: env(safe-area-inset-bottom)) está implementado en el pie de página fijo y en el contenedor del panel. - La zona de impacto del asidero de arrastre cumple con una altura mínima de 44px para accesibilidad táctil.
- El panel usa
role="dialog",aria-modal="true",aria-labelledbyy atrapa el foco mientras está activo. - Presionar
Escapeo tocar el fondo cierra el panel modal y restaura el foco al botón disparador. - El desplazamiento del cuerpo de fondo está bloqueado (
overflow: hidden) cuando el panel modal está abierto. - Los viewports ≥1024px transforman limpiamente el bottom sheet en un diálogo modal centrado, popover o cajón lateral.