Files
project.linkedcorp.net/docs/UI-UX-WINDOWS.md
T
Milton Gonzalez 6b61e5cea7 fix(ui): ComboBox y Flyout se portan a document.body con position:fixed
El panel desplegable de ComboBox se posicionaba con position:absolute dentro
de su propio contenedor. Cualquier ancestro con overflow:hidden/auto (un
Expander colapsable, el body de un DetailPopup, una tarjeta con scroll propio)
lo recortaba, dejando la lista invisible o cortada a la mitad -reproducido en
Configuracion > Apariencia, dentro del Expander-.

Fix: igual tecnica que Flyout -createPortal a document.body, position:fixed
calculado desde getBoundingClientRect() del trigger-, con cierre en click
afuera y en scroll de cualquier ancestro (capture:true, el scroll no
burbujea). De paso Flyout pasa de position:absolute a position:fixed por el
mismo motivo (evita un bug latente de desalineacion si la pagina esta
scrolleada).

Regla documentada en project-md-templates/UI-UX-WINDOWS.md (Kit de
componentes + do's/don'ts) para que no se repita en este ni otros proyectos.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-05 21:50:09 -05:00

326 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# UI/UX — Identidad para aplicaciones de escritorio Windows (cómo construir pantallas)
> 🖥️ **Muestra viva:** `UI-UX-WINDOWS.html` (en esta misma carpeta) — ábrela en el navegador para
> VER todos los elementos (ventana con barra de título propia, panel de navegación, comandos,
> listado con clic derecho, maestro-detalle, diálogos, flyouts, configuración). **Es lo primero que
> se le muestra al usuario** al arrancar un proyecto de escritorio Windows para que apruebe o pida
> ajustes de la identidad antes de construir. Usa dos JS **locales** junto al HTML (sin CDN, offline):
> `lucide.min.js` (íconos) y `chart.umd.js` (gráficas Chart.js) — cópialos junto al HTML si se mueve.
> ⚠️ **Este documento es la referencia visual y de interacción** (look & feel, tokens, componentes,
> nomenclatura de regiones). **No asume una tecnología de implementación concreta**: sirve tanto para
> una app WinUI 3/.NET nativa como para una app Electron/Tauri, o cualquier otro stack de escritorio
> Windows. Cada proyecto decide su stack al copiar este documento; lo que **no cambia** es el
> comportamiento y la identidad descritos aquí — son los que hacen que la app "se sienta Windows".
Estilo de referencia: **Fluent Design / Windows 11** (Mica, esquinas redondeadas, tipografía Segoe UI
Variable, paleta de acento del sistema). Pensado **primero para mouse** (hover, clic derecho, arrastre),
sin dejar de ser accesible por teclado.
---
## 1. Identidad visual (tokens y tema)
Colores como **variables CSS RGB** (o el equivalente del framework elegido: `DynamicResource` en
WPF/WinUI, CSS vars en Electron/Tauri), para poder escribir `rgb(var(--accent)/.2)` y variantes con
transparencia. Tema **oscuro por defecto** + claro vía `data-theme="light"`.
| Token | Uso | Oscuro (ref.) | Claro (ref.) |
|---|---|---|---|
| `canvas` | fondo de ventana (equivalente a Mica) | `32 32 32` | `243 243 243` |
| `surface` | tarjetas, diálogos, flyouts | `43 43 43` | `255 255 255` |
| `panel` | panel de navegación, hover de filas | `51 51 51` | `249 249 249` |
| `field` | fondo de campos de entrada | `43 43 43` | `255 255 255` |
| `body` | texto principal | `255 255 255` | `32 32 32` |
| `muted` | texto secundario, labels, hints | `168 168 168` | `96 96 96` |
| `line` | bordes y divisores | `70 70 70` | `225 225 225` |
| `accent` | acción primaria — **el acento del sistema** | `0 120 212` | `0 103 192` |
| `success` / `warning` / `danger` | estados | `108 203 95` / `255 185 0` / `255 105 97` | `16 124 16` / `157 93 0` / `196 43 28` |
**Acento del sistema (do & don't):** Windows deja al usuario elegir un color de acento en la
configuración del sistema; la app debe **heredarlo** cuando el framework lo expone (WinUI 3 lo hace
automático vía `AccentColor`), o dar un selector propio con la paleta estándar si no hay acceso al
acento del SO. Paleta de referencia (la que usa la muestra viva): `blue #0078D4` (por defecto),
`purple #8764B8`, `green #10893E`, `red #C42B1C`, `orange #CA5010`, `teal #009984`.
**Tipografía:** **Segoe UI Variable** (Windows 11) como fuente del sistema — no requiere carga de
fuente web, ya está instalada en Windows: `font-family:'Segoe UI Variable Text','Segoe UI',system-ui,sans-serif`.
Los títulos grandes usan el corte *Display* de la misma familia (`Segoe UI Variable Display`).
Escala: `.72rem` metadatos/labels · `.8–.82rem` cuerpo/controles · `1.05–1.25rem` títulos de sección ·
`1.6rem+` valores KPI/Display. Pesos: 600–700 títulos y labels, 400 párrafos.
**Forma (radios de Fluent 2):** `--r-sm: 4px` en controles (botones, campos, checkboxes) y
`--r-lg: 8px` en superficies elevadas (tarjetas, diálogos, flyouts, menús, y la propia ventana).
No usar esquinas totalmente cuadradas ni "pill" (`999px`) salvo en `ToggleSwitch`, `badge` y `avatar`.
**Iconografía:** un solo set en toda la app. Dos opciones válidas:
- **Lucide** (la que usa la muestra viva, `lucide.min.js` local) — mismo estándar que ya usa el grupo
en sus apps web (`UI-UX-LINKEDCORP.md`), da continuidad visual entre plataformas y permite compartir
nombres de ícono entre el proyecto web y el de escritorio de un mismo cliente.
- **Segoe Fluent Icons** (fuente de glifos del propio Windows) — 100% nativo, cero peso adicional, pero
solo tiene sentido en una implementación WinUI/WPF nativa (no está disponible como webfont fuera de Windows).
- Los íconos **heredan el color del contexto** (activo = `accent`, texto = `body`/`muted`). No mezclar
ambos sets en la misma app.
---
## 2. Mensajes del sistema — jerarquía de avisos (REGLA DE ORO)
A diferencia de la web (donde todo pasa por un único `AppDialog`), una app de escritorio Windows tiene
**cuatro** mecanismos de aviso, cada uno con un propósito distinto. Elegir el correcto es parte de la
identidad:
| Mecanismo | Para qué | Bloquea | Ejemplo |
|---|---|---|---|
| **ContentDialog** (modal) | **toda decisión** del usuario (confirmar, elegir, error crítico) | Sí | "¿Eliminar el cliente CLI-002?" |
| **InfoBar** | estado o aviso **no bloqueante**, embebido en el contenido de la pantalla | No | "Sincronización activa", "Licencia por vencer" |
| **Toast/notificación** | evento de **fondo**, sin interacción esperada, autodesaparece | No | "Copia de seguridad completada" |
| **Flyout** | acción o info **contextual**, anclada a un control, se cierra al hacer clic fuera | No (light-dismiss) | menú de usuario, "¿seguro?" ligado a un botón puntual |
**Nunca** `MessageBox`/`alert`/`confirm` del sistema operativo ni del navegador si el shell es
web-based: siempre el `ContentDialog` propio, para mantener consistencia visual entre Windows y el resto
de plataformas del grupo.
Contrato del `ContentDialog` (equivalente al `openDialog` del template web):
```js
openDialog({
tone: 'info' | 'success' | 'warning' | 'error', // franja superior + color del ícono/título
title: 'Título claro',
message: 'Descripción en lenguaje del usuario',
actions: [ // opcional; sin actions -> botón "Cerrar"
{ label: 'Cancelar', variant: 'standard' },
{ label: 'Eliminar', variant: 'danger', onClick: async () => { ... }, keepOpen: false },
],
});
```
- Sin `actions` ⇒ botón "Cerrar" (`accent`) automático. `keepOpen: true` mantiene el diálogo abierto
tras el `onClick` (procesos largos).
- **Sets de botones estándar** (misma convención que la identidad web): Aceptar/Cancelar,
Sí/No, Eliminar(danger)/Cancelar, Guardar/Descartar. **Acción primaria a la derecha**, Cancelar/No a
la izquierda. Los botones de decisión **siempre muestran texto** (nunca solo ícono).
- El `ContentDialog` se centra sobre la **ventana de la app**, no sobre toda la pantalla del monitor.
---
## 3. Kit de componentes (resumen; ver el markup/CSS de referencia en `UI-UX-WINDOWS.html`)
- **Botones** — `accent` (relleno de color, acción primaria), `standard` (borde + fondo neutro),
`subtle` (transparente, solo hover), `danger` (borde/texto rojo). Alto `32px` (`sm` `26px`). Todo
botón compone **ícono (izq.) + texto**; en toolbars muy densas puede ir solo ícono con `tooltip`
obligatorio indicando la acción.
- **Campos** — `TextBox`, `NumberBox` (con spinner +/-), `ComboBox` propio (desplegable redondeado,
con buscador si la lista tiene **≥10 ítems**; nunca el `<select>`/combo nativo del SO — no se puede
redondear ni estilar), `Textarea`, `CheckBox`, `RadioButtons`, `ToggleSwitch` (interruptor), `Slider`.
**Regla dura de implementación (bug real, recurrente):** el panel desplegable de `ComboBox` (y de
cualquier control propio con un panel flotante — `DatePicker`, `Flyout`) **nunca** se posiciona con
`position: absolute` dentro de su propio contenedor. Un ancestro con `overflow: hidden` o `overflow:
auto` (un `Expander` colapsable, el body de un `DetailPopup`, una tarjeta con scroll propio) lo
recorta y la lista queda invisible o cortada a la mitad. Portar el panel a `document.body` con
`createPortal` y posicionarlo con `position: fixed` calculado desde `getBoundingClientRect()` del
trigger (misma técnica que `Flyout`) — así queda fuera del árbol/clipping del contenedor. Cerrar el
panel en scroll (`window.addEventListener('scroll', fn, true)`, con `capture:true` porque el scroll
de un ancestro no burbujea) y en click afuera.
- **DatePicker/TimePicker** — calendario propio en un **flyout** anclado al campo (navegación de mes,
día de hoy marcado, selección resaltada con `accent`); igual criterio que `ComboBox`: no usar el
selector nativo del SO por falta de control visual, y el mismo requisito de portal +
`position: fixed` de arriba (no recortarse dentro de un contenedor con overflow).
- **ListView/DataGrid** — tabla con encabezados **ordenables** (clic ordena asc/desc), columna de
**selección múltiple** (checkbox), fila con **hover** y **estado seleccionado** (`accent/.14`), y
**clic derecho** que abre el menú contextual de esa fila (ver §6). Alternativa por fila sin mouse
derecho: botón `⋯` que abre el mismo menú.
- **DetailPopup** — patrón **por defecto** para ver/crear/editar el detalle de un ítem de un listado
de gestión (proyectos, actividades, usuarios, catálogos, etc.). Overlay que cubre la ventana y deja
**inactivo el listado detrás** (dim + sin interacción) mientras se usa el popup — a diferencia de un
panel lateral o de un panel apilado debajo del listado, el detalle NUNCA reduce ni empuja el
listado, y siempre aparece completo y en el mismo lugar sin importar el largo de la lista ni la
fila elegida. Reglas duras:
- **Nunca se cierra con clic afuera** (a diferencia de `Flyout`) — solo con el botón "Cerrar" de su
cabecera o una acción explícita del formulario (`Guardar`/`Cancelar`).
- **Alto FIJO por instancia**, no se ajusta al contenido: si el popup tiene pestañas o secciones
internas (p. ej. Info/Comentarios/Documentos), cambiar entre ellas **nunca** cambia el tamaño del
popup — solo el contenido interno hace scroll. El ancho/alto se elige según cuánto contenido
espera esa pantalla (un formulario simple de 2 campos no necesita el mismo alto que un detalle
con subtareas y dependencias), pero una vez abierto queda fijo.
- Header propio: título a la izquierda, botón "Cerrar" (ícono `X`) a la derecha.
- Contrato (React; adaptar al framework del proyecto):
`<DetailPopup open title onClose width height>{contenido}</DetailPopup>` — portal a
`document.body` (igual que `Flyout`/`ContentDialog`), **nunca** anidado dentro del árbol de la
página, para no quedar atrapado en el stacking context de un ancestro y terminar tapado por otro
overlay (bug real: sin portal, un `ContentDialog` abierto DESDE un `DetailPopup` quedaba oculto
detrás de este). Jerarquía de `z-index` entre overlays: `Flyout` (100) < `DetailPopup` (200) <
`ContentDialog` (250) < `Toast` (300) — así una confirmación abierta desde dentro de un
`DetailPopup` siempre queda por encima.
- Secciones internas relacionadas con el ítem (ej. una actividad con Info + Subtareas +
Dependencias + Comentarios + Documentos) van cada una en **su propia pestaña** dentro del popup,
nunca todas apiladas dentro de la pestaña "Info" — mismo criterio que pestañas reales a nivel de
pantalla completa (ver identidad web `UI-UX-LINKEDCORP.md`), aplicado ahora dentro del popup.
- **Master-Detail (Split View)** — patrón **nativo de Windows** (Correo, Explorador): lista angosta a
la izquierda + panel de detalle a la derecha que se actualiza **en el sitio** al seleccionar un
ítem, sin modal. Uso **restringido**: solo para pantallas cuya función principal es explorar/leer
una lista larga como actividad central de esa vista (no para listados de gestión con acciones
crear/editar — ahí va `DetailPopup`). Evitar cualquier variante que ubique el detalle "a un costado"
o "debajo" de un listado de gestión (panel lateral fijo, panel acoplado al borde, panel apilado
bajo la tabla): en la práctica el detalle se siente secundario y el listado pierde protagonismo o
queda "lejos" del detalle cuando la lista crece. Ante la duda entre Master-Detail y `DetailPopup`
para un listado de gestión, usar `DetailPopup`.
- **Menú contextual (clic derecho)** — el patrón de interacción **más característico de Windows**:
ítems con ícono + label + acelerador de teclado a la derecha (`Ctrl+E`, `Del`…), separadores,
submenú con flecha `▸` que se expande al pasar el mouse, ítem destructivo en `danger`. Debe estar
disponible en **toda fila/elemento accionable**, no solo en listados.
- **Barra de menú clásica** (`Archivo · Editar · Ver…`) — **opcional**, solo para apps de
productividad/edición que lo necesiten (no todas las apps modernas la llevan; Configuración o
Correo no la tienen). Si se usa, cada ítem abre un menú desplegable igual al contextual.
- **Flyout** — popover anclado a un control (avatar, botón), con **light-dismiss** (clic fuera o Esc
cierra). Para menús de cuenta, ayuda contextual corta o una confirmación ligada a un botón puntual.
- **InfoBar** — banner de 4 tonos (`info/success/warning/error`) embebido en el contenido, con botón
de cierre `✕`; no empuja al usuario a decidir, solo informa.
- **Toast** — notificación flotante (esquina inferior derecha), autodesaparece (~4s), apilable. Solo
para eventos de fondo — si el usuario debe decidir algo, es un `ContentDialog`, no un toast.
- **Teaching Tip** — "coach mark" anclado con flecha, para presentar una función nueva la primera vez
(onboarding); se descarta con un botón, no reaparece tras cerrarse.
- **Expander (patrón de Configuración)** — fila con ícono + título + descripción + chevron; al hacer
clic expande un cuerpo con los controles de esa sección (toggles, botones). Es el patrón estándar
para pantallas de **Configuración/Ajustes**.
- **Treeview** — árbol jerárquico estilo Explorador de Windows (`▾/▸` para expandir/colapsar,
ícono de carpeta/archivo, selección resaltada). Para categorías, carpetas o estructuras anidadas.
- **Barra de título personalizada** — reemplaza el chrome nativo de Windows: ícono+nombre de la app a
la izquierda (zona **arrastrable**, mueve la ventana), controles **minimizar / maximizar / cerrar**
a la derecha. `Cerrar` se resalta en rojo (`#C42B1C`) al hover; `Maximizar` muestra, al hover, la
vista previa de **Snap Layouts** (2/3/4 particiones) — detalle que distingue a una app "moderna".
- **NavigationView (panel de navegación)** — fijo a la izquierda, con **tres modos**: expandido
(ícono+texto), compacto (solo ícono) y oculto (drawer). Se colapsa con el botón ☰; tiene buscador
propio arriba y, al pie, la cuenta del usuario (abre un `Flyout`).
- **CommandBar** — franja de botones de acción de la vista actual (Nuevo, Actualizar, Eliminar…) con
botón **"···" (overflow)** para acciones secundarias cuando no caben todos los botones.
- **BreadcrumbBar** — ruta de navegación bajo la barra de comandos, segmentos separados por `›`, el
último en negrita y no clicable.
- **Barra de estado** — pie de ventana con texto pequeño: conteo de elementos/selección, estado de
conexión, versión. Equivalente a la barra de estado del Explorador de Windows.
- **KPI / spinner / skeleton / progress bar** — igual criterio que en web: tarjetas de indicador con
delta ▲/▼, spinner circular para cargas cortas, skeleton para listados, barra de progreso para
procesos medibles.
- **Gráficas** — Chart.js local (`chart.umd.js`, sin CDN); colores desde los tokens del tema y se
reconstruyen al cambiar tema/acento. `maintainAspectRatio:false` + contenedor con `max-height`.
- **Plantillas de ventana** — **Login** (ventana pequeña centrada, avatar, usuario/contraseña,
recordarme), **Acerca de** (ventana utilitaria pequeña con ícono, versión, botón de actualización) y
**Reporte/factura** (documento con `Imprimir`/`Exportar PDF`, aislado con `@media print` si el shell
es web-based).
---
## 4. Layout (estructura de la ventana) y NOMENCLATURA de regiones
Úsalos para pedir cambios: "cambia X en `barra-comandos`". La muestra viva rotula visualmente cada
región (chip azul) y cada componente (chip verde) al activar el interruptor "Mostrar nombres" (vista
Resumen, o menú `···` de la barra de comandos).
| Nombre | Qué es | Comportamiento |
|---|---|---|
| `ventana` | contenedor raíz de la app | esquinas redondeadas (8px), sombra; simula el marco de una app de escritorio flotando sobre el escritorio |
| `barra-titulo` | barra de título personalizada | **arrastrable** salvo sobre sus controles; ícono+nombre a la izq., minimizar/maximizar/cerrar a la der. |
| `navegacion` | panel de navegación izquierdo (NavigationView) | **FIJO**, scroll propio si hay muchos ítems; modos expandido/compacto/oculto |
| `col-derecha` | columna derecha | todo lo no-navegación, alto completo de la ventana |
| `barra-comandos` | CommandBar de la vista actual | botones de acción + overflow `···` |
| `migas-pan` | BreadcrumbBar | bajo la barra de comandos; último nivel en negrita |
| `area-contenido` | contenido de la vista | **ÚNICA** región con scroll propio |
| `panel-detalle` | panel derecho en vistas maestro-detalle | se actualiza al seleccionar un ítem, sin modal |
| `divisor` | separador arrastrable entre paneles | cursor `col-resize`; el arrastre con mouse redimensiona los paneles adyacentes |
| `barra-estado` | pie de ventana | conteo de ítems/selección, estado; texto pequeño |
**Comportamiento clave:** `navegacion` queda **fija** (no se desplaza con `area-contenido`); solo
`area-contenido` hace scroll. `barra-titulo`, `barra-comandos`, `migas-pan` y `barra-estado`
permanecen siempre visibles.
**Ventanas secundarias vs. una sola ventana:** a diferencia de la web (todo en una pestaña), una app
Windows puede abrir **ventanas propias** para diálogos de larga duración o utilitarios (Acerca de,
Propiedades, un asistente). Regla: usar una **ventana secundaria** solo cuando el contenido necesita
vivir independientemente de la ventana principal (el usuario puede moverla, alternar entre ambas con
Alt+Tab); si es una decisión puntual ligada al contexto actual, es un `ContentDialog`, no una ventana nueva.
---
## 5. Interacción — pensada primero para mouse
- **Hover en todo lo accionable**: botones, filas de listado, ítems de navegación, ítems de menú y
árbol cambian de fondo al pasar el mouse (`panel` o `accent/.14` si están seleccionados). Es la
señal principal de "esto se puede interactuar" en una app de mouse.
- **Clic derecho = menú contextual**, en cualquier fila/elemento accionable (listados, árbol,
tarjetas). Debe existir también una vía sin botón derecho (botón `⋯`) para paridad con touch/teclado.
- **Tooltips con retardo** (~350ms) en todo botón de solo-ícono y en controles cuyo propósito no sea
obvio por el texto visible; nunca sustituyen a un `ContentDialog` para respuestas del sistema.
- **Cursores con significado**: `pointer` en clicables, `col-resize`/`row-resize` en divisores
arrastrables, `move` en zonas de arrastre (barra de título), `text` en campos.
- **Anillo de foco solo para teclado** (`:focus-visible`), no al hacer clic con el mouse — evita el
"flash" de foco en cada clic que resulta ruidoso en una app mouse-first, sin sacrificar accesibilidad
por teclado (Tab/flechas siguen mostrando el anillo).
- **Snap Layouts**: al pasar el mouse sobre "Maximizar" se muestra la vista previa de particiones de
pantalla — reforzar este detalle si el framework lo expone nativamente (Windows 11 lo da gratis en
WinUI/WPF con el chrome nativo bien configurado).
- **Divisores/splitters arrastrables** entre paneles (p. ej. lista/árbol ↔ detalle) para que el usuario
ajuste el espacio a su gusto; el ancho elegido se **persiste** por vista.
- **Sin scroll horizontal en tablas** cuando sea evitable: preferir ocultar columnas secundarias o
usar `panel-detalle` para el resto de la información antes que forzar scroll-x.
---
## 6. Receta para construir una pantalla
1. **CommandBar** (`Nuevo`, `Actualizar`, acciones contextuales + overflow `···`).
2. **Elegir el patrón de datos** según el caso:
- **Listado + `DetailPopup`** (default para listados de gestión: proyectos, actividades, usuarios,
catálogos…): al hacer clic en una fila u optar "Nuevo", se abre un `DetailPopup` (overlay de
tamaño fijo, listado inactivo detrás, nunca se cierra con clic afuera) con el detalle/formulario
y sus acciones (`Guardar`, `Editar`, `Eliminar`). El listado se ve completo e intacto en cuanto
se cierra el popup.
- **Listado + Master-Detail**: lista con selección simple a la izquierda/arriba, detalle **en el
sitio** a la derecha/abajo, sin modal. Reservado para pantallas cuya función principal es
explorar/leer una lista larga (correo) — no para listados de gestión con crear/editar.
3. **Selección múltiple + acciones por lote**: casillas en la columna izquierda de la tabla; la barra
de estado muestra "`N` de `M` seleccionados"; las acciones de lote aparecen en la `CommandBar`
solo cuando hay selección.
4. **Clic derecho en cada fila** con el menú contextual estándar: Ver detalle, Editar, Duplicar,
Exportar (submenú), separador, Eliminar (`danger`).
5. **Edición**: campos habilitados solo en modo edición; `Guardar` solo si hubo cambios reales;
acciones destructivas siempre confirmadas con `ContentDialog` (tono `warning`, Cancelar/Eliminar).
6. **Pie de listado** (`pie-listado`, igual criterio que en la identidad web): líneas por página
(5·10·20·50·Todo, **default 10**, persistente por listado), rango "Mostrando X–Y de N",
paginación con ventana deslizante de 5 números, y **alto constante** entre páginas (filas de
relleno invisibles en la última página parcial).
---
## 7. Reglas de identidad (do & don't)
- ✅ Barra de título **personalizada** (no la nativa del SO) con drag region + minimizar/maximizar/cerrar.
- ✅ Panel de navegación **fijo**, con modos expandido/compacto/oculto persistentes.
- ✅ Tema oscuro/claro **y** acento del sistema, ambos persistentes; heredar el acento del SO cuando el
framework lo permita.
- ✅ **Toda decisión** del usuario pasa por `ContentDialog`; estados no bloqueantes por `InfoBar`;
eventos de fondo por `Toast`; nada de `MessageBox`/`alert`/`confirm` nativos.
- ✅ **Clic derecho con menú contextual** en toda fila/elemento accionable — es la firma de interacción
de una app Windows mouse-first.
- ✅ `ComboBox` y `DatePicker` **propios** (redondeados, estilables); nunca los controles nativos del
SO/navegador para estos casos — igual criterio que la identidad web.
- ✅ Tipografía del sistema (**Segoe UI Variable**), sin cargar fuentes web — más estable y coherente
con el resto de Windows.
- ✅ Radios de esquina consistentes: `4px` controles, `8px` superficies elevadas y la ventana misma.
- ✅ Un solo set de íconos en toda la app (Lucide o Segoe Fluent Icons), heredando color del contexto.
- ✅ `DetailPopup` (tamaño fijo, nunca se cierra con clic afuera) para ver/crear/editar el detalle de
un ítem de un listado de gestión; Master-Detail solo para pantallas de exploración/lectura pura.
- ✅ Foco visible solo con teclado (`:focus-visible`); hover visible siempre (mouse-first).
- ❌ `MessageBox`/`alert`/`confirm` del sistema. ❌ combos/selects/calendarios nativos sin estilar.
❌ mezclar sets de íconos. ❌ apilar listado + formulario + detalle en una sola pantalla sin
separación clara. ❌ usar `Toast` para pedir una decisión al usuario. ❌ panel de detalle lateral o
debajo del listado en pantallas de gestión (usar `DetailPopup`). ❌ que un `DetailPopup` cambie de
tamaño al moverse entre sus pestañas/secciones internas. ❌ montar `ContentDialog`/`DetailPopup` sin
portal a `document.body` (queda atrapado en el stacking context de un ancestro y puede terminar
tapado por otro overlay). ❌ panel desplegable de `ComboBox`/`DatePicker`/`Flyout` con
`position: absolute` dentro de su propio contenedor (un `Expander`, el body de un `DetailPopup` o
cualquier tarjeta con `overflow` lo recorta o lo oculta) — portar a `document.body` y usar
`position: fixed` calculado desde el trigger.
> Para que una app "se sienta Windows moderna": misma barra de título, mismo panel de navegación,
> mismos cuatro mecanismos de aviso (`ContentDialog`/`InfoBar`/`Toast`/`Flyout`) bien diferenciados,
> clic derecho en todo lo accionable, y los mismos tokens de color/tipografía/radio. Abre
> `UI-UX-WINDOWS.html` para verlo funcionando y pide ajustes por el nombre de región/componente.