# Patrones de UI > **Propósito:** explicar cómo implementar pantallas concretas. Este documento, junto con [Arquitectura frontend](./frontend-architecture.md) y [UI system](./ui-system.md), forma la fuente de verdad (SSOT) de frontend/UI. Los componentes aquí citados se definen en `ui-system.md`; este documento explica cómo componerlos. ## 1. Listados ```tsx } /> {refreshError} ``` - El CTA de creación permanece durante loading, empty y errores de refresh; puede desaparecer ante error inicial bloqueante. - Búsqueda, filtros y controles viven en `DataTable.topContent`. - TanStack Query conserva los datos remotos y la paginación server-side. - Búsqueda, filtros, sorting y paginación reflejan su estado relevante en `searchParams` y reinician página cuando corresponda. - No se calculan contadores globales a partir de una página parcial. - El click de fila recibe la fila; la página/controller usa explícitamente `row.id`. - Una vista de composición de dominio puede encapsular el shell si permanece pura. El controller de página concentra URL, filtros, consulta, estados y navegación. La Page define columnas y conecta callbacks; no reproduce reglas de dominio. ## 2. Create / Update ```tsx } footer={} > {notice} {fields} ``` Footer y aside son opcionales. `content` es adecuado para formularios focalizados; `full` para editores documentales amplios. Create y Update deben compartir geometría cuando solo cambian defaults, submit o navegación. Loading y error bloqueante usan también `RdxPageFrame` y `RdxPageContainer`; no reconstruyen el viewport. ## 3. Detail Un detalle normal usa `RdxPageFrame`, `RdxEditorHeader` cuando es fullscreen y el container apropiado. Un detalle documental especializado puede usar: ```text RdxPageFrame content overflow-hidden ├── document pane → scroll interno └── inspector → scroll interno ``` Solo se usa esta excepción cuando los panes necesitan permanecer visibles simultáneamente. No se crea un layout genérico de detalle si no existe repetición real. ## 4. Settings Settings posee un layout funcional bajo un único frame: ```text RdxPageFrame └── SettingsLayout ├── header ├── navigation └── Outlet ``` Las páginas hijas no añaden otro `RdxPageFrame` cuando el padre ya controla shell y scroll. El layout de Settings se conserva porque aporta navegación y composición funcional. ## 5. Dialogs Usar `Dialog` para una tarea breve y focalizada que debe volver al contexto actual. Usar `AlertDialog` para confirmaciones, especialmente destructivas. Una edición prolongada o documental necesita una ruta propia. Orden recomendado: ```text DialogContent ├── DialogHeader: título y descripción ├── campo de identidad, si existe ├── secciones agrupadas por intención └── DialogFooter: cancelar y enviar ``` - La cabecera y el footer se separan visualmente del formulario. - Los bloques usan `section` y `aria-labelledby` cuando tienen título. - Campos equivalentes pueden usar dos columnas desde `sm`; en móvil se apilan. - El botón submit puede apuntar al formulario mediante `form` si el footer está fuera de `
`. - Durante submit se deshabilitan controles y acciones de cierre que puedan interrumpir la operación. - El controller posee defaults, validación, mutation, reset, feedback y navegación posterior. - Todo texto visible usa i18n en `es` y `en`. ## 6. Acciones de fila `RdxRowActions` recibe acciones ya resueltas: - los listados usan `RdxRowActions` para mantener una presentación uniforme; - las frecuentes van en `primaryActions` como botones de icono con tooltip; no se usan botones de texto en la columna de acciones; - las secundarias y destructivas van en `overflowActions`, accesibles desde el menú de más acciones; - orden, `disabled`, `disabledReason`, permisos y callbacks pertenecen al consumidor; - una acción deshabilitada puede seguir visible para explicar por qué no está disponible. No se trasladan entidades, navegación, dialogs ni permisos a `rdx-ui`. ## 7. Loading, error y empty | Estado | Patrón | | --- | --- | | Loading inicial de tabla | `DataTable loading` dentro del shell estable | | Loading de editor | skeleton con el mismo frame/container que success | | Error inicial bloqueante | `PageErrorState` dentro de frame y container | | Error de refresh | `ErrorAlert` inline; mantiene datos y controles | | Empty | mensaje/estado vacío en el stack del contenido | No se crean sistemas alternativos de errores o skeletons cuando los componentes existentes cubren el caso. ## 8. Formularios - React Hook Form y `FormProvider` pertenecen al consumidor. - `RdxFormGrid` organiza únicamente campos. - Errores de campo permanecen junto al control; errores de operación usan `ErrorAlert`. - Dirty state, bloqueo de navegación y submit pertenecen al controller/provider correspondiente. - La acción principal comunica loading y evita doble submit. - Una única superficie editable es preferible a cards anidadas. ## 9. Main + aside El aside es opcional y contiene metadata, resumen o contexto secundario. En desktop acompaña al main y en pantallas menores se apila debajo. No usar el aside para equilibrar visualmente columnas, trasladar totales o fragmentar arbitrariamente el flujo del formulario. Tablas y line editors mantienen su layout especializado dentro del main. ## 10. Responsive - Validar móvil, tablet y desktop. - Evitar widths fijos en campos y controles localizados. - Mantener acciones utilizables cuando se apilan. - Confirmar `min-w-0`, truncado intencional y ausencia de overflow horizontal. - En layouts especializados, comprobar pane sizes y scroll independiente. ## 11. Accesibilidad - Controles nativos o primitives accesibles; nunca `div` clicables. - Labels asociadas mediante `htmlFor`/`id`. - Icon buttons con `aria-label` y tooltips cuando corresponda. - Activación por teclado en filas y acciones. - Foco visible, orden DOM lógico y errores anunciables. - El color no sustituye texto, icono o estado semántico. ## 12. Testing Usar tests de comportamiento con el runner vigente del workspace y Testing Library cuando existe interacción DOM. No probar detalles internos del controller ni clases visuales incidentales. Cobertura mínima según patrón: - listado: CTA, search, filtros, paginación, estados y navegación de fila; - editor: header, contenido, acciones, dirty/submit y loading/error; - dialog: título, campos, condicionales, cancelar/enviar y mutation; - UI pública: contrato observable, accesibilidad y responsabilidades estructurales. Las traducciones productivas deben probarse sin sustituirlas por un diccionario que oculte claves ausentes. ## 13. Checklist - [ ] La ruta usa el shell real declarado en `handle.layout`. - [ ] Existe un único `RdxPageFrame` propietario del scroll. - [ ] Header editorial o fullscreen elegido por responsabilidad. - [ ] Width y padding pertenecen a `RdxPageContainer`. - [ ] El aside es funcional y opcional. - [ ] No hay viewport o scroll principal manual en la Page. - [ ] Loading, error, empty y success conservan estructura coherente. - [ ] Acciones, permisos y navegación permanecen en el consumidor. - [ ] Responsive, teclado, foco, i18n y light/dark están validados. - [ ] Implementación, documentación, UI Kit y tests siguen sincronizados.