# 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 error inicial bloqueante conserva el mismo shell:
```tsx
```
- 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.
- Los listados no reconstruyen con HTML local las responsabilidades de Frame, Container o Content. Search, filtros, tabs, tabla y paginación son contenido funcional de `RdxPageContent`; el scroll interno de una tabla o grid es legítimo y no sustituye el scroll de página.
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.
Los listados administrativos que editan en diálogo mantienen el formulario en el controller. La Page monta diálogos presentacionales con `FormProvider`; estos reciben `form`, estado pendiente y callbacks, pero no clientes HTTP ni mutations. `document-series` en Settings > Billing es la referencia para una edición general más operaciones administrativas separadas (contador, default y estado).
## 2. Create / Update
Estructura canónica: providers → RdxPageFrame (header/content/footer) → un único RdxPageContainer → un único RdxPageContent; los dialogs son hermanos del frame.
```tsx
}
footer={}
>
{pageError ? : null}
```
Los errores inline no definen su propio spacing estructural. Participan del spacing estándar de RdxPageContent igual que el resto de hijos principales.
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.
El error bloqueante conserva la misma jerarquía: RdxPageFrame → RdxPageContainer → RdxPageContent → PageErrorState.
## 3. Detail
Un detalle normal usa `RdxPageFrame`, `RdxEditorHeader` cuando es fullscreen y la jerarquía `RdxPageContainer → RdxPageContent`; errores, alertas, secciones semánticas y contenido funcional viven dentro de `RdxPageContent`.
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. Su scroll interno es parte del workspace documental, no el scroll estructural de la Page. 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 `