261 lines
8.3 KiB
Markdown
261 lines
8.3 KiB
Markdown
# Page Layouts Rdx
|
|
|
|
## Estado
|
|
|
|
Este documento describe los patrones conceptuales de página aprobados para adopción progresiva.
|
|
|
|
El documento canónico de contexto global es:
|
|
|
|
- [visual-system-design.md](./visual-system-design.md)
|
|
|
|
## Listado
|
|
|
|
```txt
|
|
RdxPageContainer
|
|
└── RdxPageStack
|
|
├── RdxPageHeader
|
|
├── notices opcionales
|
|
└── contenido del listado
|
|
```
|
|
|
|
Reglas:
|
|
|
|
- anchura por defecto `full`;
|
|
- acciones principales en cabecera;
|
|
- acciones de fila frecuentes visibles y acciones destructivas en overflow mediante `RdxRowActions`;
|
|
- panel contextual solo cuando aporte contexto real;
|
|
- la composición del listado no debe acoplarse a React Query, routing ni dominio.
|
|
|
|
Ejemplo de integración real validado en `proformas/list` y `customers/list`:
|
|
|
|
```tsx
|
|
<RdxPageContainer width="full">
|
|
<RdxPageStack spacing="default">
|
|
<RdxPageHeader
|
|
title={title}
|
|
description={description}
|
|
actions={<RdxPageActions primary={primaryAction} />}
|
|
/>
|
|
|
|
{notice}
|
|
|
|
{content}
|
|
</RdxPageStack>
|
|
|
|
{dialogs}
|
|
</RdxPageContainer>
|
|
```
|
|
|
|
Aclaraciones:
|
|
|
|
- `RdxPageContainer` resuelve el padding exterior y la anchura de página;
|
|
- `RdxPageStack` resuelve el ritmo vertical principal entre cabecera, aviso y contenido;
|
|
- `RdxPageHeader` no conoce navegación ni callbacks de React Router;
|
|
- la tabla, los filtros, los panels, los dialogs y los controllers permanecen fuera de las foundations;
|
|
- `RdxRowActions` puede vivir dentro de las columnas de tabla, pero recibe acciones ya decididas por el consumidor;
|
|
- en ambos pilotos el panel contextual sigue viviendo en composición local mediante `ResizablePanelGroup`;
|
|
- no documentar todavía `RdxListPageLayout` ni `RdxResponsivePageGrid` mientras el resize y la apertura del aside dependan del caso de uso.
|
|
|
|
### Evidencia de pilotos de listado
|
|
|
|
```txt
|
|
DECISIÓN_CONFIRMADA
|
|
Container + Stack + Header + Actions cubren la capa exterior del listado.
|
|
|
|
DECISIÓN_PROVISIONAL
|
|
La Page puede extraer una vista pura si mejora el test y reduce wiring.
|
|
|
|
NO_ABSTRAER_TODAVÍA
|
|
main + aside redimensionable
|
|
shell específico del panel contextual
|
|
toolbars
|
|
```
|
|
|
|
## Listado con panel contextual
|
|
|
|
```txt
|
|
ResizablePanelGroup
|
|
├── main
|
|
└── RightPanel
|
|
└── RdxContextPanel
|
|
```
|
|
|
|
Reglas:
|
|
|
|
- `ResizablePanelGroup` gestiona la geometría, el resize y la persistencia local del split;
|
|
- `RightPanel` gestiona la superficie lateral, la altura y el overflow base;
|
|
- `RdxContextPanel` gestiona cabecera, cierre, body y footer visual del panel;
|
|
- el contenido interno del panel sigue siendo específico del dominio;
|
|
- no documentar todavía un layout genérico de listado a partir de este patrón.
|
|
|
|
## Editor simple
|
|
|
|
```txt
|
|
scroll container
|
|
└── RdxEditorPageLayout complexity="simple"
|
|
└── form stack
|
|
├── RdxEditorSection
|
|
├── RdxEditorSection
|
|
└── ...
|
|
```
|
|
|
|
Reglas:
|
|
|
|
- las rutas cuya tarea principal sea crear, editar o configurar mediante un formulario focalizado deben entrar por el shell `app-fullscreen`;
|
|
- listados, dashboards, detalle y navegación de settings mantienen `app-sidebar` salvo necesidad funcional explícita;
|
|
- `RdxEditorPageLayout` resuelve padding interior, ancho centrado y `min-w-0`;
|
|
- el editor simple puede apoyarse en una única superficie contenedora para diferenciar la página del área editable, sin volver a cards por sección;
|
|
- `RdxEditorSection` expresa jerarquía por defecto con spacing y divisor inferior;
|
|
- `RdxFormGrid` mantiene la retícula del formulario sin conocer RHF ni dominio;
|
|
- priorizar lectura y velocidad de escaneo;
|
|
- usar secciones planas con espacio o divisores;
|
|
- reservar sticky footer solo cuando el scroll lo justifique.
|
|
|
|
Ejemplo validado en `customers/update`, `customers/create` y `/account`:
|
|
|
|
```tsx
|
|
<AppFullscreenLayout>
|
|
<PageFormHeader backLabel={backLabel} onBack={onBack} title={title} />
|
|
<div className="flex-1 overflow-y-auto">
|
|
<RdxEditorPageLayout complexity="simple">
|
|
<div className="flex min-w-0 flex-col gap-6">
|
|
{notice}
|
|
|
|
<form className="flex min-w-0 flex-col gap-6">
|
|
<RdxEditorSection title={title} description={description}>
|
|
<RdxFormGrid>{fields}</RdxFormGrid>
|
|
</RdxEditorSection>
|
|
</form>
|
|
</div>
|
|
</RdxEditorPageLayout>
|
|
</div>
|
|
</AppFullscreenLayout>
|
|
```
|
|
|
|
Deuda registrada:
|
|
|
|
- `PageFormHeader` sigue siendo full-width mientras el contenido del editor queda centrado en `max-w-5xl`;
|
|
- no modificar todavía el header legacy sin validación visual manual real.
|
|
|
|
Evidencia adicional de create/update:
|
|
|
|
```txt
|
|
DECISIÓN_CONFIRMADA
|
|
ambos flujos reutilizan el mismo layout, superficie y secciones.
|
|
|
|
ESPECÍFICO
|
|
defaults iniciales
|
|
wiring de submit
|
|
feedback de error
|
|
navegación de retorno concreta
|
|
```
|
|
|
|
Candidatos explícitos para auditoría posterior:
|
|
|
|
- `customers/create`
|
|
- `customers/update`
|
|
- `/account`
|
|
- `proformas/update`
|
|
|
|
## Editor complejo
|
|
|
|
```txt
|
|
shell
|
|
├── PageFormHeader
|
|
├── scroll container
|
|
│ └── RdxEditorPageLayout complexity="complex"
|
|
│ ├── main
|
|
│ │ └── única superficie editable
|
|
│ │ ├── RdxEditorSection
|
|
│ │ ├── RdxEditorSection
|
|
│ │ ├── bloque de líneas con layout propio
|
|
│ │ └── ...
|
|
│ └── aside
|
|
│ └── controles secundarios o contexto de apoyo
|
|
└── RdxEditorStickyFooter
|
|
├── summary/context region
|
|
└── action region
|
|
```
|
|
|
|
Reglas:
|
|
|
|
- `RdxEditorPageLayout` resuelve padding exterior, `min-w-0` y la geometría `main + aside`;
|
|
- el `main` debe alojar los campos editables y sus bloques funcionales;
|
|
- el `aside` debe reservarse para metadata, configuración o contexto de apoyo ya existente en la pantalla;
|
|
- el `aside` del editor complejo usa una geometría aproximada `minmax(0, 1fr) 22rem` en desktop y se apila debajo del `main` cuando no hay ancho suficiente;
|
|
- no mover campos editables al `aside` solo por estética si eso empeora el flujo;
|
|
- no mover los totales al `aside`;
|
|
- los bloques con layout interno propio, como una tabla de líneas, no deben forzarse dentro de `RdxFormGrid`;
|
|
- `RdxEditorStickyFooter` resuelve una única superficie sticky con una región contextual flexible y una región de acciones;
|
|
- los totales siguen perteneciendo al dominio de Proformas aunque se rendericen dentro de la región contextual del footer;
|
|
- `PageFormHeader` puede seguir existiendo, pero no debe duplicar `Guardar` y `Cancelar` cuando el footer sticky ya los contiene.
|
|
|
|
Ejemplo validado en `proformas/update`:
|
|
|
|
```tsx
|
|
<div className="fixed inset-0 flex flex-col overflow-hidden">
|
|
<PageFormHeader />
|
|
|
|
<div className="flex min-h-0 flex-1 flex-col bg-muted/20">
|
|
<div className="min-h-0 flex-1 overflow-y-auto">
|
|
{notice}
|
|
|
|
<RdxEditorPageLayout
|
|
complexity="complex"
|
|
aside={aside}
|
|
>
|
|
<div className="rounded-2xl border border-border bg-background px-4 py-4 shadow-xs md:px-6 md:py-6">
|
|
<form className="flex min-w-0 flex-col gap-6">
|
|
<RdxEditorSection title={documentTitle}>
|
|
<RdxFormGrid>{documentFields}</RdxFormGrid>
|
|
</RdxEditorSection>
|
|
|
|
{lineEditor}
|
|
</form>
|
|
</div>
|
|
</RdxEditorPageLayout>
|
|
</div>
|
|
|
|
<RdxEditorStickyFooter
|
|
leading={<TotalsSummary />}
|
|
secondary={cancelButton}
|
|
primary={saveButton}
|
|
status={status}
|
|
/>
|
|
</div>
|
|
</div>
|
|
```
|
|
|
|
Evidencia del piloto:
|
|
|
|
```txt
|
|
DECISIÓN_CONFIRMADA
|
|
main contiene la única superficie editable
|
|
aside contiene bloques secundarios ya existentes del editor
|
|
la sticky zone inferior pasa a una única superficie visual
|
|
los totales permanecen como dominio de Proformas dentro de la región contextual
|
|
las acciones principales comparten el mismo footer sin una segunda franja
|
|
RdxFormGrid se mantiene solo para campos
|
|
|
|
DECISIÓN_PROVISIONAL
|
|
visual exacta del header legacy frente al ancho full del editor complejo
|
|
|
|
NO_ABSTRAER_TODAVÍA
|
|
layout específico del bloque de líneas
|
|
layout específico del footer de totales
|
|
```
|
|
|
|
## Detalle
|
|
|
|
```txt
|
|
width="wide" o "full"
|
|
main + aside opcional
|
|
aside para metadata, actividad, resumen o acciones
|
|
```
|
|
|
|
Reglas:
|
|
|
|
- mantener patrón consistente de label/value;
|
|
- usar aside solo cuando el contenido realmente gane claridad;
|
|
- no implementar todavía `RdxDetailPageLayout` en esta fase.
|