@humano-ui/frontend-ui
v0.5.0
Published
Presets de UI compartidos para los dominios infoplan-*-web: barra de consulta, tablas, inputs, toolbars, LOVs, navegación, acciones, diálogos, feedback, layout de registro, carga de archivos y tema (marca y densidad)
Readme
@humano-ui/frontend-ui
Presets de UI compartidos para los dominios infoplan-*-web (reclamos, suscripción,
productos, pólizas, personas, facturación, finanzas, core, configuración).
Los 9 dominios nacieron del mismo template y hoy repiten —y hacen divergir— la misma barra de consulta, la misma tabla, los mismos inputs, los mismos modales de búsqueda y el mismo toolbar. Este paquete es la fuente única de esas piezas.
Instalación
pnpm add @humano-ui/frontend-uiPeer dependencies (las pone el dominio, no la librería):
pnpm add react react-dom @mui/material @mui/icons-material @emotion/react @emotion/styled| Peer | Rango soportado |
| --------------------- | --------------- |
| react / react-dom | >=19 |
| @mui/material | >=6.5.0 <8 |
| @mui/icons-material | >=6.5.0 <8 |
| @emotion/* | >=11 |
Formatos: el paquete se publica en ESM (import → dist/index.js) y CommonJS
(require → dist/index.cjs), cada uno con sus tipos (index.d.ts / index.d.cts).
Vite y los demás bundlers usan el ESM; Jest y los scripts Node en CommonJS cargan el CJS
sin transformIgnorePatterns.
Vitest y SSR. El ESM importa MUI por rutas profundas y @mui/material 6.5 no declara mapa
exports, así que el cargador ESM de Node las trata como imports de directorio y falla. Solo
afecta a quien pase el paquete por ese cargador: Vitest con la dependencia externalizada (lo
predeterminado) o renderizado en servidor. Se desbloquea con una línea:
// vitest.config.ts
test: { server: { deps: { inline: [/@humano-ui[\/]frontend-ui/] } } }Desaparecerá al subir a @mui/material 7, que sí declara exports.
DateInputno depende de@mui/x-date-pickers: hoy conviven 3 majors de esa librería entre dominios y el preset debe funcionar en todos sin negociar versión.
Uso mínimo
import { ThemeProvider, CssBaseline } from '@mui/material';
import {
createInfoplanTheme,
NotificationProvider,
ConfirmProvider,
PageContainer,
FilterBar,
DataTable,
} from '@humano-ui/frontend-ui';
const theme = createInfoplanTheme('light');
export function App() {
return (
<ThemeProvider theme={theme}>
<CssBaseline />
<NotificationProvider>
<ConfirmProvider>
<PageContainer title="Consulta de afiliados">
<FilterBar fields={fields} values={values} onChange={setValues} onSearch={buscar} />
<DataTable columns={columns} rows={rows} getRowId={(r) => r.id} />
</PageContainer>
</ConfirmProvider>
</NotificationProvider>
</ThemeProvider>
);
}Qué trae
| Área | Exports |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
| Theme | createInfoplanTheme, primaryColors, grayColors, statusColors, densityTokens, resolveDensity |
| Layout | PageContainer, SectionCard, PageTabs, SummaryHeader, ContextPanel, ContextStrip/useRevealOnScroll |
| Inputs | TextInput, SelectInput, NumericInput, DateInput, CatalogSelect, CatalogAutocomplete, FieldShell, FileDropzone |
| Consulta | FilterBar (+ tipos de campo) |
| Tabla | DataTable, exportCsv |
| Toolbar | ActionToolbar, ActionMenu, SplitActionButton, IconActionButton, IconActionBar |
| Diálogos | ConfirmDialog, ConfirmProvider/useConfirm, LookupDialog, SelectionModal, DetailPopover, ReasonDialog, PromptProvider/usePrompt |
| Feedback | EmptyState, StatusChip, AlertMark, NotificationProvider/useNotify |
| Datos | ReadOnlyField, FieldGrid, FactGrid, ReadOnlyCheck |
Novedades de la 0.5.0 — el vocabulario de la lectura, que es la mitad del trabajo de una
pantalla de expediente y de la que el paquete no tenía nada (FieldShell viste un control
editable; DetailFact solo existe dentro de DetailPopover/SummaryHeader/ContextPanel). Salen
de AR130020 (Mantenimiento de Reclamaciones) y de una medición incómoda: el mismo par clave/valor
está copiado 12 veces en el monorepo y solo esa pantalla lo llama 62 veces. Nada existente
cambia:
ReadOnlyField— par clave/valor de solo lectura (clave 11/600 arriba, valor 13,5/500 debajo). No es un input deshabilitado: el valor se lee con la tinta principal. El vacío es un guion largo en tinta terciaria y el0es un dato;monopara identificadores y montos,widepara el valor largo,tooltipque describe el valor sin renombrarlo.FieldGrid— su rejilla:auto-fitconminmax(minColumnWidth, 1fr), así que las columnas las decide el ancho disponible y no un juego de breakpoints; 22 px entre columnas y 14 entre filas.FactGrid— franja de hechos con juntas de 1 px hechas con elgapde la rejilla (nunca un borde por celda, que se duplica en cada junta): cabecera de registro o pie de totales, con escalafact/total, acento, monoespaciada y huecos deliberados ({ spacer: true }).ReadOnlyCheck— indicador de lectura con forma de casilla y dos ejes: el ícono dice si está marcado y el color del rótulo dice si el dato existe.role="checkbox"+aria-readonly, nunca unCheckboxdeshabilitado (invita al clic y se apaga aunque esté encendido).
Novedades de la 0.3.0 — ningún componente nuevo: la versión abre desde fuera lo que impedía a
una pantalla migrada de Oracle Forms (donde nada puede cambiar de aspecto) sustituir sus piezas
locales por las del paquete. Todo aditivo y con el default igual a la 0.2.0, salvo los dos
arreglos de AlertMark marcados abajo:
AlertMark—describeChildata el motivo al control conaria-describedby(cambia el DOM del hijo, no su nombre accesible),reserveSpacereserva la franja de la barra en vez de pintarla encima del control (cambia el píxel) ysxajusta el envoltorio. Los dos primeros vienen encendidos y se apagan confalse.IconActionButton—disabledColor(el azul atenuado del Forms en vez del gris del tema),width="auto"(leyendas enteras, sin topes ni elipsis),focusOutline={false}(sin anillo de foco),sx(relleno, atenuación, tipografía de la leyenda) yariaDescribedBy/aria-describedby, que es lo que hace que el motivo deAlertMarkllegue al botón.ReasonDialog—childrencomo shell (cuerpo propio con la misma cabecera, aviso y pie),confirmMode="validate-on-confirm"(el primario sigue activo y valida al pulsarlo),autoFocusFirstField={false}(sin salto de foco al primer campo, como en los modales del legacy),closeOnBackdrop,dividers,slotSx,ReasonField.ariaLabelyrequiredMessage, y el tipo de campo'number'condecimals/thousandSeparator/min/max.fieldspasó a opcional. Se exportanReasonConfirmMode(para tiparconfirmModefuera del JSX) yReasonDialogSlotSx(para tiparslotSxen una constante). Ojo: ensancharReasonFieldTyperompe unswitchexhaustivo connever(TS2322); se arregla añadiendo el caso'number'.
Novedades de la 0.2.0 (en una frase cada una):
StatusChip— chip de estado con tono explícito (success/warning/error/info/neutral), tamaño y punto.PageTabs— pestañas de pantalla con contador, deshabilitadas con motivo y panel accesible; controladas o no.SummaryHeader— encabezado de registro: título, estatus, chips, grilla de datos clave, avisos y acciones; sticky opcional.ActionMenu— menú "Más acciones" agrupado, con ítems deshabilitados por motivo, externos y peligrosos.SplitActionButton— botón principal (el siguiente estatus) + caret con todas las transiciones posibles.ReasonDialog+usePrompt()— captura de motivo (select, texto, textarea, fecha) con obligatorios; por promesa víaPromptProvider.ContextPanel— carril lateral de contexto por secciones (facts, enlaces, contenido libre, colapsables).FileDropzone— zona de carga de archivos con validación de extensión y tamaño en español, operable por teclado.createInfoplanTheme(mode, { brand, typography })— marca opcional aplicada a ambos modos; los defaults no cambian.IconActionButton/IconActionBar— botón de ícono con leyenda corta debajo y su fila: repone el reconocimiento que tenían las filas de íconos sin texto del Forms.AlertMark— barra que subraya un control para avisar de algo que mirar (endoso, devolución, spool); nunca un anillo alrededor.ContextStrip+useRevealOnScroll()— franja sticky de una línea que aparece cuando la cabecera del registro sale por arriba, y desaparece al volver.SectionCard summary— resumen de una línea visible solo con la card colapsada, para no tener que abrirla para saber qué hay dentro.createInfoplanTheme(mode, { density })—'compact'compacta el espaciado entre secciones y los paddings de superficie sin tocar el alto de los inputs.
El detalle por versión está en CHANGELOG.md.
Estructura del código
src/ combina dos convenciones; las dos son válidas (Storybook y vitest usan globs src/**):
- Carpetas por área con archivos planos —
dialogs/,feedback/,filter/,inputs/,layout/,table/,theme/,toolbar/— donde cada pieza esNombre.tsx+Nombre.stories.tsx+Nombre.test.tsxy los tipos compartidos del área van en<area>-types.ts. Es la convención original (0.1.0). - Carpetas por componente en
src/components/<Nombre>/con barrilindex.ts— las piezas de la 0.2.0 (StatusChip,PageTabs,SummaryHeader,ActionMenu/SplitActionButton,ReasonDialog/PromptProvider,ContextPanel,FileDropzone,IconActionButton/IconActionBar,AlertMark,ContextStrip), que traen varios archivos internos cada una.
Para ubicar una pieza: src/index.ts es el único punto de entrada público (agrupado por área)
y desde ahí sale su ruta. Lo que no está en src/index.ts es interno
(dialogs/statusChipPalette.ts, internal/storyFixtures.ts).
Catálogo visual
El catálogo vivo (variantes, props, modo claro/oscuro) es Storybook:
pnpm storybook # desde la raíz del workspace infoplan-web-uiReglas de diseño que el preset ya aplica
- Título sobre el input, nunca label flotante de MUI.
- Encabezado de pantalla con solo el nombre de la pantalla (sin
Sección | Pantalla). - Márgenes horizontales de 24px (
px: 3) en el contenedor de página. - Mensajes de validación y error en español.
- Iconografía de los inputs en
primary, en claro y en oscuro.
Publicación
El runbook de publicación vive en docs/PUBLICACION.md, dentro del workspace del repositorio; no acompaña al paquete.
