metis-desk/docs/patron-de-listados-compactos.md

344 lines
26 KiB
Markdown
Raw Normal View History

# Patrón de listados compactos — v2
Fecha: 22 de octubre de 2026. **Contrato de diseño vigente; primera implementación compartida adoptada en el dashboard de puesto.**
Complementa el [patrón de listados de entidades](patron-de-listados-de-entidades.md), que
continúa siendo normativo para exploración y gestión. [DESIGN.md](../DESIGN.md) gobierna
tokens, tipografía e identidad; el [patrón de diálogos](patron-de-dialogos.md) gobierna
las interacciones modales. Este documento no crea componentes, rutas, permisos ni APIs.
## 1. Objetivo y selección del patrón
Un **Listado compacto (Compact List)** permite reconocer, consultar y actuar sobre
elementos relacionados en una ficha, dashboard, tarjeta o panel contextual. Selecciona
los atributos útiles para esa relación y permite profundizar sin reproducir las
herramientas de una pantalla de exploración. No sustituye un formulario ni un picker.
Un **Listado de entidades (Entity Listing)** permite encontrar y gestionar registros
de una colección completa mediante las bandas y capacidades del estándar existente.
Activos, Personas, Recursos y Compañías en sus pantallas principales conservan ese patrón.
| Criterio | Listado de entidades | Listado compacto |
| --- | --- | --- |
| Tarea principal | Encontrar, filtrar, comparar muchos atributos y gestionar | Reconocer relaciones y ejecutar acciones contextuales |
| Ámbito | Colección completa dentro de su ámbito funcional | Relación o resumen de una entidad/contexto explícito |
| Encabezado | Cabecera de pantalla con título, subtítulo y acciones | Título de sección normalmente aportado por el contenedor |
| Composición | Cuatro bandas normativas | Cabecera opcional, filas y salida al conjunto completo cuando proceda |
| Búsqueda/filtros | Herramientas del patrón completo | Ausentes por defecto; búsqueda local solo con justificación |
| Columnas | Configurables, con identidad y acciones protegidas | Seleccionadas por el consumidor, sin configurador |
| Ordenación | Contrato actual de cabeceras y selector | Orden estable del contexto; ordenación local opcional |
| Rango y paginación | Rango superior/inferior, tamaño y paginación | Sin esos controles; ampliación o acceso completo según necesidad |
| Estado navegable | URL/History en consumidores habilitados por L03.1 | Estado local del resumen; conserva retorno al abrir destinos reales |
| Volumen | Preparado para exploración sostenida | Resumen o colección legible con estrategia explícita de acceso completo |
| Presentación | Tabla de entidades | Compact Table o Compact Item List |
| Estado técnico | EntityTable implementada | CompactTable, CompactList y CompactListItem implementados; adopción inicial en puestos |
Decidir en este orden:
1. Identificar la pregunta del usuario y la relación que necesita consultar. Si debe
explorar repetidamente el conjunto, aplicar listado de entidades aunque haya pocas filas.
2. Elegir atributos prioritarios y tareas: comparar columnas favorece Compact Table;
reconocer títulos con metadatos favorece Compact Item List.
3. Evaluar crecimiento esperado, frecuencia de uso, acciones y ancho del contenedor.
Definir cómo alcanzar todo el conjunto antes de limitar filas.
4. Si necesita filtros combinados, configuración de columnas, tamaño de página y
paginación recurrente, ofrecer una vista completa con el patrón de entidades.
La tarjeta puede conservar un resumen; no acumular esas capacidades en él.
Estar en una ficha no obliga a compactar una colección que requiere exploración compleja.
Tener 60 perfiles no obliga a cambiar de patrón: puede mantenerse un resumen compacto,
siempre que el conjunto completo resulte accesible y el alcance visible esté explicado.
Un selector continúa sujeto al patrón de diálogos/PickerList; no pierde búsqueda,
selección o paginación por parecerse visualmente a una lista corta.
## 2. Estructura y variantes
El contenedor aporta el ámbito y normalmente el encabezado: título accesible, contador
conocido opcional y acción contextual opcional. No repetir dentro de la colección el
título de `DetailPanel`. El cuerpo contiene filas, estados y acciones. Al final puede
aparecer «Mostrar más» o «Ver todos» con alcance explícito.
**Compact Table:** comparación de atributos homogéneos. Tabla HTML, nombre accesible,
cabeceras de columna y filas con identidad estable. Las cabeceras aportan significado;
no omitirlas en tablas comparativas ni usar una tabla para maquetar tarjetas.
| Perfil | Persona | Cuenta | Estado |
| --- | --- | --- | --- |
| Administración | Ángela Muñoz | angela.pruebas | Activo |
| Consultas | Íñigo Fernández | — | Activo |
**Compact Item List:** lectura lineal de elementos con título, metadatos y acciones.
Usar `ul`/`li`; `ol` solo si la secuencia tiene significado. Por ejemplo, portátil
principal con estado técnico y uso, monitor asociado, o aplicación con versión y estado.
Puede componer `dl` dentro de un elemento para pares etiqueta/valor. Un único elemento
conserva la misma semántica; no requiere una tarjeta nueva para cada fila.
Ambas variantes comparten reglas de datos, densidad y estados, pero mantienen semánticas
y estructuras independientes. No convertir automáticamente una tabla en lista al crecer
el número de filas.
## 3. Contrato visual
Valores orientativos derivados de las primitivas y tokens instalados. La primera receta
compartida se concreta en el contrato implementado al final de este documento.
Los equivalentes en px usan la escala actual; el contenido y la ampliación de texto
pueden aumentar las alturas. Consultar [las fuentes inspeccionadas](auditoria-patrones-de-listado-v2.md).
| Elemento | Receta orientativa | Criterio |
| --- | --- | --- |
| Contenido principal | Inter, `text-sm` (14 px), título `font-medium` | No reducir todo a 12 o 13 px para ganar densidad |
| Metadatos | `text-xs` (12 px), `text-muted-foreground` | Mantener legibilidad y contraste efectivo |
| Cabecera tabular | `text-sm font-medium`, altura orientativa `h-10` (40 px) | Etiquetas breves; no nuevo estilo de títulos globales |
| Celdas | `px-2 py-2` (8 px) | Menor padding vertical que `EntityTable` (`py-3`); sin alterar vendor |
| Fila simple | Altura natural, alrededor de 40 px de texto; 48 px con acción de 32 px y `py-2` | No fijar altura máxima; aceptar filas multilínea y zoom |
| Elemento de lista | `py-2`, separación título/metadatos `gap-1`; entre grupos `gap-2`/`gap-3` | Ritmo de 4/8/12 px según contenido |
| Acciones | `Button size="sm"` o `size="icon-sm"` (32 px) | Conservar foco y separación; ampliar superficie si el contexto táctil lo exige |
| Separadores | `border-border`, divisores horizontales discretos | Evitar cuadrícula completa, sombras y tarjeta anidada innecesaria |
| Superficie | Heredar `bg-card`/`text-card-foreground` o fondo del contenedor | Sin paleta alternativa ni tokens nuevos de éxito/advertencia |
Texto a la izquierda; números comparables a la derecha con `tabular-nums`; acciones al
final y alineadas a la derecha. La columna de identidad recibe el espacio flexible
(`min-w-0`); estado y acciones tienen ancho controlado por su contenido. Evitar anchos
mínimos heredados de inventario que hagan inutilizable una tarjeta estrecha. No añadir
un configurador para resolver un exceso de atributos: elegir los esenciales y ofrecer detalle.
Permitir saltos de línea en nombres largos y valores técnicos. Si se trunca, conservar
el valor completo en el árbol accesible y ofrecer lectura visual completa mediante
expansión, detalle o tooltip accesible también por foco. `title` o hover aislados no
bastan. No recortar cuentas diferentes hasta hacerlas indistinguibles.
Ausencias en datos: exclusivamente `—`, preservando cero y estados reales. Un error de
resolución de referencias debe explicarse al nivel de la fuente, sin convertirlo en
«sin relaciones». Estado textual además de color; conservar estados técnicos, uso y
revisión por separado. `EntityStatus.active` es binario: no representa por sí solo todos
los estados de configuración o disponibilidad.
## 4. Capacidades obligatorias y opcionales
Obligatorio: ámbito reconocible, identidad estable, información prioritaria, semántica
correcta, estados honestos, acciones accesibles y acceso completo a los elementos que
no se muestran. El contador es opcional; si existe, debe indicar si cuenta el conjunto,
los elementos visibles o las coincidencias. Omitir el total cuando se desconoce.
No componer por defecto barra de búsqueda, barra de filtros, configurador de columnas,
selector de tamaño, paginación, rangos duplicados ni menús de configuración. **Omitirlos
en la composición**, sin controles ocultos por CSS ni elementos invisibles enfocables.
| Capacidad opcional | Cuándo y condiciones |
| --- | --- |
| Ordenación local | Comparación útil y conjunto local completo; estable para empates, indicador `aria-sort` y botones de cabecera. No confundir ordenación con búsqueda. |
| Búsqueda local | Localización frecuente dentro de la relación; campos y alcance explícitos, limpieza y estado sin coincidencias. No filtrar una página como si fuera el conjunto entero. |
| Expansión de fila | Metadatos secundarios vinculados al elemento; botón con `aria-expanded`/`aria-controls`, contenido asociado y foco estable. |
| Mostrar más | Revelar una porción adicional de la misma colección; explicar cantidad visible si se conoce. Tras activar, no mover foco inesperadamente; al contraer evitar retirar el elemento enfocado. |
| Ver todos | Ruta real con ámbito conservado, o diálogo/panel existente que permita recorrer todo el conjunto. Distinguir navegar de revelar contenido. |
| Scroll interno | Proteger el presupuesto de una tarjeta de consulta repetida; límite de altura responsive, indicador de continuidad, acceso por teclado y foco sin recortes. Evitar scroll anidado innecesario. |
| Límite inicial | Solo con orden y criterio explícitos y una salida que alcance todos los registros. Nunca un `slice` silencioso. |
| Acciones por elemento | Operaciones reales y permitidas; principal visible, secundarias en menú accesible, sin duplicar la principal. No ocultarlas exclusivamente al hover. |
| Selección simple | Alimenta una acción o detalle concreto; radio o control equivalente semántico, nombre y estado visibles. Enlaces y botones internos mantienen su comportamiento. |
| Selección múltiple | Existe una operación colectiva real y se define su alcance y confirmación. Casillas primero, restricciones y selección parcial explícitas; considerar PickerList si se está eligiendo en un formulario. |
Cada consumidor documentará qué capacidad necesita y por qué. Un nuevo requisito de
exploración compleja debe resolverse en la vista completa antes de ampliar el resumen
con otra barra. Búsqueda y ordenación opcionales no implican persistencia global nueva.
## 5. Volumen y acceso completo
Escenarios de diseño, **no umbrales automáticos**:
| Escenario | Estrategia |
| --- | --- |
| 0 | Vacío real tras respuesta válida, explicación contextual y alta/vinculación si existe y está permitida. No mostrar tabla de controles sin propósito. |
| 1 | Mantener fila o elemento del mismo patrón; tabla si las etiquetas comparables siguen aportando significado. |
| 2–5 | Mostrar normalmente todo; sin herramientas de exploración añadidas por defecto. |
| 6–15 | Evaluar altura, anchura y frecuencia; mostrar todo si resulta legible o ampliar progresivamente con alcance explícito. |
| Decenas/cientos | Resumen inicial determinista y acceso completo mediante expansión, región desplazable o destino completo real. Para investigación sostenida, utilizar listado de entidades en ese destino. |
Si no existe una ruta que conserve la relación, no inventar un enlace ni enlazar «Ver
todos» a un listado sin ese filtro. Puede mostrarse todo con desplazamiento contenido o
proponerse una interacción local de ampliación para implementación posterior. La ausencia
de destino completo bloquea un recorte que haría inaccesibles registros, no obliga a
inventar contratos HTTP.
En datos remotos paginados indicar «elementos cargados» o «hay más» según el contrato.
«Cargar más» obtiene páginas reales y conserva orden/identidades; no es paginación local
oculta. Si se necesita cambiar página/tamaño o filtrar todo el servidor, llevar esa tarea
a la vista completa. No derivar total global de `items.length` de una página.
## 6. Estados y fuentes
| Situación | Presentación y recuperación |
| --- | --- |
| Carga inicial | Skeleton de geometría plausible, decorativo y sin nombres, acciones o totales inventados; mensaje de carga de la colección. |
| Actualización con datos previos | Conservar filas, selección, expansión y foco; aviso discreto. Si falla, explicar que se muestran últimos datos disponibles y ofrecer reintento dirigido. |
| Vacío real | Cero únicamente confirmado por respuesta válida del ámbito completo; CTA pertinente con permisos. |
| Sin coincidencias | Mantener criterio visible y acción de limpiar búsqueda; no afirmar ausencia de relaciones. |
| Error parcial | Mantener fuentes válidas; identificar la fallida, las limitaciones del resumen y su reintento. No mostrar un total definitivo incompleto. |
| Fuente no disponible | Mensaje contextual y recuperación si procede; no reutilizar vacío. Si no existe caché autorizada, no mostrar filas inventadas. |
| Información incompleta | Conservar registros válidos y `—` en datos ausentes; explicar referencia no resuelta o metadatos pendientes en su contexto. No equiparar ausencia y error. |
| Datos paginados | Identificar alcance cargado, total solo si es conocido y acceso al resto. |
| Ausencia de permisos | Respetar denegación real, retirar datos no autorizados y explicar acceso según contrato del módulo. No usar caché anterior como sustituto de autorización. |
`EntityListState` existente cubre loading/ready/refreshing/unavailable/stale. No cubre por
sí solo total desconocido, permisos, error de otra fuente o parcialidad de datos: esos
hechos pertenecen al adaptador consumidor. Reutilizar la unión cuando encaje y componer
la información adicional; este estándar no añade variantes a su API.
Ubicar feedback y reintento fuera de la región horizontal desplazable. Conservar un
destino de foco estable cuando desaparezca el botón de reintento. Usar anuncios
moderados por colección, sin una región live por celda ni toasts repetidos en refetch.
Los datos remotos siguen en TanStack Query; no duplicarlos en estado React.
## 7. Responsive y accesibilidad
Adaptar por capacidad real del **contenedor**, sin copiar presupuestos de Activos o
Recursos ni definir un breakpoint global. Mantener identidad, estado y acciones; los
atributos secundarios pueden ir al detalle o a una fila expandida con acceso explícito.
En lista, apilar título, metadatos y acciones conservando orden DOM. En tabla, preferir
salto de línea y columnas prioritarias; usar scroll horizontal contenido cuando la
comparación lo requiera. Si se diseña una alternativa móvil como lista, conservar
etiquetas y relaciones, una sola presentación accesible e identidad/foco estables.
- Tabla nativa con nombre mediante `caption`, `aria-label` o `aria-labelledby`, `th`
con `scope="col"` y cabecera de fila cuando resulte pertinente. Etiquetas accesibles
para columnas visuales de iconos/acciones, aunque usen `sr-only`.
- Lista nativa con nombre de sección; no simular tabla con `div` ni añadir `role="grid"`
sin implementar su modelo de interacción. No usar la semántica de tabla para composición.
- Enlace para destino real, botón para acciones, expansión y diálogos. Navegación del
cliente mediante `BrowserLink` desde el consumidor; la biblioteca genérica no conoce rutas.
- Acciones por teclado, etiquetas traducidas para iconos funcionales y decorativos
`aria-hidden`. Una fila clicable conserva controles internos y alternativa de teclado.
- Foco visible no recortado, sin dependencia de hover; retorno al origen tras modal y
conservación del registro al ampliar/cargar más. No introducir saltos de foco en refetch.
- Contraste efectivo según DESIGN.md: texto normal 4,5:1 y texto grande 3:1; comprobar
también controles, selección y foco según los criterios aplicables del proyecto.
- Contenido completo legible con teclado y tacto; zoom 200/400 %, nombres largos,
espacios y valores técnicos sin desbordamiento global. La compactación no justifica
reducir controles ni fijar alturas que recorten texto.
La futura implementación debe verificarse con el [procedimiento Playwright MCP](playwright-mcp.md),
datos sintéticos aislados y volumen de AGENTS.md, además de escenarios específicos
vacíos y pequeños. Las reglas aquí escritas no equivalen a una validación en navegador
ni a cumplimiento WCAG demostrado.
## 8. Arquitectura de componentes
**Compartir primitivas y comportamientos transversales; diferenciar composición y capacidades.**
No añadir un modo universal a `EntityTable` con flags para quitar barras.
| Pieza existente | Reutilización y límite |
| --- | --- |
| Table, TableHeader, TableBody, TableRow, TableHead, TableCell | Base semántica de Compact Table. Componer desde código propio; no editar vendor. |
| DetailPanel | Contenedor opcional con título/acciones/contador; `density="compact"` reduce espaciado, sin gestionar filas ni estados. Evitar doble tarjeta. |
| EntityStatus / Badge | Estado textual y visual cuando la semántica encaja; el booleano de EntityStatus no modela un estado complejo. |
| EntityRowActions / EntityAction | Acciones existentes, menú Base UI y restricciones. La navegación conserva un enlace real, no se transforma en callback de botón por usar primaryAction. |
| EntityListState / EntityListStatus | Disponibilidad, refetch, error y reintento cuando el contrato encaja; el consumidor conserva permisos y parcialidad. |
| EmptyState, Skeleton | Composición de estados; EmptyState tiene presentación de incorporación y no es obligatorio para todo vacío mínimo. |
| BrowserLink y contratos de retorno | El módulo aporta enlaces y contexto real; no acoplar rdx-ui a core o DTO. |
| EntityTableContent / useEntityTable | Acoplados a TanStack y al patrón completo; no reutilizarlos obligando a inicializar paginación/visibilidad que el compacto no necesita. |
| DashboardTable | Precedente local sobre Table; no es todavía API compartida ni receta normativa del compacto. |
Responsabilidades del patrón; la API mínima implementada se describe en §11. Las
capacidades opcionales anteriores no se consideran implementadas por aparecer aquí:
| Componente | Responsabilidad y entradas conceptuales |
| --- | --- |
| CompactTable | Tabla comparable: nombre accesible, colección readonly con identidad estable y definición mínima de columnas (ID, etiqueta y render). Alineación y prioridad explícitas cuando proceda. |
| CompactList | Lista semántica de elementos con identidad estable, nombre accesible y contenido compuesto por el consumidor. Sin motor de tabla. |
| CompactListItem | Título, metadatos y acciones mediante composición; independiente de entidades, consultas y traducciones. Extraer solo ante repetición real. |
Los nombres de ficheros siguen kebab-case y componentes PascalCase. La
implementación genérica pertenece a `@repo/rdx-ui`;
las adaptaciones de entidades viven en su operación conforme a la estructura web vigente.
No crear barrels vacíos, factories, contexto React o un motor de columnas universal de antemano.
Los renderizadores reciben datos presentacionales, textos traducidos y acciones del módulo,
sin endpoints, ORM ni DTO específicos. No exigir `EntityColumn` con capacidades de exploración
para describir una fila compacta. Selección, búsqueda o ampliación se añaden como composición
explícita cuando haya consumidores; no mediante una colección de flags `hide*`/`show*`.
La consulta se comparte por query keys existentes. Calcular filtrados, contadores y filas
durante render; solo criterio, selección y expansión necesitan estado local. Sin efectos
para copiar datos remotos, consultas por fila, memoización preventiva ni nuevas dependencias.
No persistir preferencias nuevas ni introducir paginación/virtualización sin necesidad medida.
## 9. Casos de referencia y ejemplos
La ficha de Puesto de trabajo es referencia funcional, **no la única especificación visual**.
La tabla conserva el diagnóstico anterior y la transformación adoptada en la primera
implementación, descrita en el informe de refinamiento:
| Colección | Actual inspeccionado | Propuesta |
| --- | --- | --- |
| Personas y perfiles | WorkstationProfiles usa EntityTable completa con búsqueda, contador, columnas, ordenación y paginación dentro de DetailPanel | Compact Table: perfil, persona, cuenta, estado y acción contextual; resumen de configuraciones solo si aporta a la tarea y cabe. Conservar alta, archivados, revisión, enlaces y estados independientes. |
| Equipamiento | WorkstationAssets usa EntityTable completa | Compact Item List: nombre y enlace, plantilla, condición de principal, estado técnico y uso separados; editar composición sigue siendo una acción explícita. |
| Software del principal | WorkstationSoftware ya presenta ul/li con scroll y gestión en diálogo | Normalizar como Compact Item List preservando versión, licencia, estado, revisión, errores por fuente y gestión existente. No sustituir su diálogo de gestión completa por resumen. |
| Configuraciones por perfil | WorkstationConfigurationFamily presenta listas por familia, selector de perfil y destinos de gestión | Colecciones contextuales con selección de perfil fuera de las filas; conservar familias, estados de configuración, cobertura documental y revisión, sin inferir permisos efectivos. |
Con 60 perfiles: indicar alcance (por ejemplo, activos y archivados separados), mantener
orden estable y permitir recorrerlos todos. Hasta disponer de una ampliación o destino
real que conserve la relación con el ordenador principal, no limitar el resumen sin salida.
Una ruta de perfiles de compañía sin ese filtro no equivale a «todos los perfiles del puesto».
| Correcto | Incorrecto |
| --- | --- |
| Tres activos con título, estado técnico, uso y enlaces en lista | EntityTable completa dentro de tarjeta solo para mostrar tres nombres |
| Resumen de perfiles con Mostrar más que permite alcanzar los 60 | Recortar a cinco sin explicar que faltan registros |
| Ver todos abre un destino real con el mismo ámbito | Enlace inventado o listado general presentado como si conservara la relación |
| Herramientas omitidas de la composición | Ocultar buscador y paginación de EntityTable con selectores CSS |
| Reintento de la familia fallida y datos válidos conservados | Fallo de metadatos convertido en «0 configuraciones» |
| Acción visible y menú operable con teclado | Acción disponible únicamente al pasar el ratón |
| Vista completa para filtrar muchas relaciones | Añadir sucesivamente todas las barras del inventario al resumen |
## 10. Compatibilidad y decisiones de implementación pendientes
Este patrón no altera los listados de entidades existentes, la excepción de pickers `layout="fill"`,
L03.1, contratos HTTP, i18n es/en, permisos ni políticas de actualización de consultas.
Mantener contexto de compañía y retorno al navegar; el resumen no hereda sort/página
del listado padre ni añade parámetros URL por defecto. Una interacción contextual con
contrato URL propio lo conserva. Modal de alta/edición sigue el patrón de diálogos.
Para futuras adopciones debe concretarse por consumidor:
- Prioridad y anchura efectiva de columnas, altura disponible y forma de ampliación.
La receta orientativa de densidad debe validarse con texto largo, tacto y zoom.
- Destino o interacción para consultar todos los perfiles del principal y tratamiento
de archivados; no asumir que existe un filtro de ruta aún no implementado.
- Evoluciones de la API mínima y extracción real de renderizadores/estados comunes.
Los nombres propuestos no comprometen una API universal.
- Búsqueda local si se necesita: V07 sigue pendiente. La normalización del selector de
columnas no aprueba automáticamente la de entidades; conservar la semántica vigente
hasta una entrega específica y documentar los campos buscables.
La [auditoría v2](auditoria-patrones-de-listado-v2.md) contiene candidatos adicionales,
evidencias estáticas, discrepancias y verificaciones realizadas en esta fase documental.
## 11. Primera implementación compartida
Adoptada en [el refinamiento del dashboard de puesto](workplace-dashboard-implementacion.md#refinamiento-visual-y-adopción-del-listado-compacto).
Primitivas de `@repo/rdx-ui/components/<nombre-en-kebab-case>`:
| API disponible | Contrato implementado |
| --- | --- |
| `CompactTable<T extends { id: string }>` | `title`, `items` readonly, `columns` readonly y `emptyMessage`; opcionales `className` sobre la tabla, `state`, `onRetry` y `retryLabel`. |
| `CompactColumn<T>` | `id`, `label`, `render(item)` y `align` opcional: start o end. Sin metadatos de búsqueda, visibilidad o paginación. |
| `CompactList` | `title` accesible y `children`; lista nativa con divisores y tipografía estándar. |
| `CompactListItem` | `title`, `metadata?`, `icon?`, `actions?`, `children?`; identidad flexible y acciones independientes. |
| `CollectionPreview<T>` | `items`, `limit`, `expandLabel`, `collapseLabel` y función hija que recibe los elementos visibles; amplía al conjunto completo cargado. |
`CompactTable` conserva mensajes de `EntityListState` mediante `EntityListStatus`, reintento
con foco estable fuera del scroll y valores ausentes mediante el mismo helper que
`EntityTable`. El consumidor aporta textos y no debe proporcionar un callback de reintento
sin su etiqueta. El padding implementado de celda es `px-2 py-1.5` (8/6 px), ajustado para
filas de texto y acciones legibles; la altura continúa siendo natural. No hay herramientas
ocultas, motor TanStack, consultas ni dependencia de Workstation.
`CollectionPreview` muestra inicialmente el límite elegido por la tarea (cinco en el
resumen de puesto) y ofrece Mostrar todos con cantidad y Mostrar menos, con
`aria-expanded`/`aria-controls`. No pagina, no filtra ni presume que los elementos cargados
sean un total remoto. Mantiene el botón y su foco al ampliar o contraer. Límite no entero
positivo implica mostrar todo, evitando recortes inaccesibles.
Ordenación local, búsqueda, selección y carga de páginas remotas siguen siendo capacidades
de diseño opcionales **no implementadas por estos componentes**. No se añadieron flags a
EntityTable. Las adopciones restantes de la auditoría v2 continúan pendientes.