Saltar a contenido

ADR 018: Routing de pantallas y jerarquía de títulos del panel

Estado

Aceptado — 2026-07

Relacionado con ADR 003 y ADR 012.

Contexto

El shell shadcn mostraba títulos duplicados (header del panel, ModuleScreen, DashboardRenderer, cards de widgets) y rutas ambiguas: una URL como /panel/resources/create podía resolverse contra path: ":id" con id=create, mostrando un infolist vacío en lugar de un formulario.

Los manifests manuales y el orden de screens[] no bastaban para garantizar el comportamiento correcto.

Decisión

1. Resolución de pantallas por especificidad

En @cortex/panel-core:

  • scoreScreenPath(path) — prioriza segmentos literales sobre parámetros (:id).
  • matchModuleScreen(manifest, relativePath) — elige la pantalla coincidente con mayor score.
  • relativeModulePath(pathname, moduleUrl) — obtiene el segmento relativo bajo un módulo.

ModuleScreen y PanelShell deben usar estos helpers; no reimplementar matching por orden de array.

2. Jerarquía de títulos

Capa Regla
PanelShell Un h1 por pantalla = screens[].title resuelto
ModuleScreen h2 solo si theme.shellOwnsPageTitle === false
DashboardRenderer h3 solo si layout.hideTitle === false
Widgets CardTitle solo si config.title está definido

3. Flags de tema (PanelTheme)

Flag Default en shadcn Descripción
shellOwnsPageTitle true El shell muestra el título de pantalla
showPanelSubtitle true Muestra panel.title como subtítulo del header

4. Defaults en ResourceBuilder

Los dashboards generados para list/create/edit/view usan emit_dashboard(..., hide_title=True).

Si TableBuilder no define título, se propaga el título del recurso al widget data-table.

El manifest emitido ordena pantallas: list → create → edit → view.

Consecuencias

  • Manifests manuales con acción CREATE deben declarar path: "create" explícitamente.
  • Plugins que migran a ResourceBuilder obtienen routing y títulos correctos sin cambios en React.
  • Skins distintos de shadcn pueden dejar shellOwnsPageTitle en false para comportamiento legacy.
  • Tests unitarios en routingParams.test.ts y test_ui_form_builder.py fijan el contrato.

Referencias