Seleccionar una librería
Antes de cualquier decisión, aplica product-ui §1 (el diario de gusto y precedencia) y §5 (qué habilidad es dueña de qué). Una regla del diario que nombre una librería gana.
Cuando se invoque sin una tarea, pide una en una sola línea y detente.
Orden de decisión
Recorre estos pasos de arriba a abajo. Detente en el primer paso que resuelva completamente la tarea.
- ¿Qué está ya instalado? Lee
package.json. Si una librería listada o un competidor ya hace el trabajo, úsalo. Señala una mejor elección en una línea, y nunca cambies una dependencia sin que te lo pidan. Por qué: una segunda librería para el mismo trabajo duplica el bundle y las convenciones. - ¿La plataforma lo resuelve completamente? Revisa la tabla de abajo. Por qué: la plataforma no tiene coste de bundle, ni ruta de actualización ni riesgo de abandono.
- ¿La lista tiene una entrada? Abre references/catalogue.md, encuentra la categoría y toma la entrada marcada como Default. Recomienda una librería, no un menú.
- ¿Esa entrada está mantenida? Revisa la columna de estado. Si dice Unmaintained (Sin mantenimiento), nunca la recomiendes; usa el reemplazo nombrado en la entrada.
- ¿Nada encaja? Di "esta tarea no está en la lista", luego elige desde tu propio conocimiento y ejecuta la verificación de abajo sobre ella. Por qué: un paquete no verificado es la forma habitual en que el código abandonado se cuela.
"Resuelve completamente" significa que cada requisito de la tarea se cumple, incluyendo comportamiento de teclado, enfoque y lector de pantalla. Si un requisito falla, ve al paso 3.
Plataforma primero
| Tarea | Respuesta de la plataforma | Pasar a una librería cuando |
|---|---|---|
| Modal | <dialog> con showModal() | Necesitas diálogos apilados con salida animada en los navegadores que soportas, o gestión de enfoque no modal |
| Popover, panel desplegable, tarjeta tipo tooltip | Atributo popover, más posicionamiento con anclaje CSS donde se soporte | Necesitas volteo por colisión en todas partes, o un menú con enfoque rotativo |
| Acordeón, divulgación | <details name> | Necesitas estado controlado o altura animada más allá de interpolate-size |
| Modo oscuro sin alternancia | prefers-color-scheme, color-scheme, light-dark() | El usuario elige el tema manualmente y debe persistir |
| Entrada de fecha, hora, mes | <input type="date"> y sus hermanos | Necesitas rangos, un calendario personalizado o una apariencia consistente |
| Formato de números, tiempo relativo, plurales, listas | Intl.NumberFormat, RelativeTimeFormat, PluralRules, ListFormat | Nunca. Usa siempre Intl |
| Código de un solo uso, campo único | <input autocomplete="one-time-code" inputmode="numeric"> | Necesitas una caja por dígito |
| Movimiento de entrada, salida y diseño | Transiciones CSS, @starting-style, WAAPI, Transiciones de Vista | Necesitas muelles, gestos o animación de diseño interrumpible |
| Validación de formularios | Validación de restricciones (required, pattern, setCustomValidity) | Necesitas reglas entre campos o asíncronas, o un esquema tipado |
| Select con pocas opciones | <select> | Necesitas búsqueda, selección múltiple o filas enriquecidas |
| Encabezados fijos, snap de scroll, listas perezosas | CSS position: sticky, scroll-snap, content-visibility: auto | La lista tiene 1,000+ filas |
Pares
| Roto | Arreglado | Por qué |
|---|---|---|
Un modal con <div> y una trampa de enfoque escrita a mano | <dialog> y showModal() | Trampa de enfoque, Esc y fondo inerte vienen gratis |
npm i react-beautiful-dnd | @dnd-kit/react | El primero está obsoleto y sin mantenimiento |
npm i vaul para un cajón | Base UI Drawer, o <dialog> estilizado como lámina | El propio README de vaul dice que está sin mantenimiento |
| Un toast construido desde una librería de modales | Base UI Toast | Apilamiento, pausa al pasar el ratón y deslizar ya están resueltos |
setInterval contando un número | NumberFlow | Los dígitos giran con diseño correcto y movimiento reducido |
5,000 <tr> renderizadas a la vez | TanStack Virtual bajo TanStack Table, o Virtuoso para listas | El coste de renderizado crece con las filas, no con el viewport |
new Intl.NumberFormat reemplazado por un paquete de moneda | Intl.NumberFormat | Las reglas de locale vienen en el navegador |
Verificar antes de recomendar
Ejecuta esto en cualquier paquete, esté listado o no. Un estado del catálogo puede ser más antiguo que tu sesión.
npm view <pkg> time.modified license version
- Mantenido: última publicación en los últimos 12 meses, o un push al repositorio en los últimos 6 meses con una versión publicada.
- Lento: completo en funcionalidades, sin publicación durante 12–24 meses, el repositorio aún responde issues. Utilizable. Di que es lento.
- Sin mantenimiento: archivado, un README que lo diga, o sin publicación durante 24+ meses con fallos abiertos. Nunca lo recomiendes.
- Lee la licencia. Informa de cualquier cosa que no sea MIT, ISC, BSD o Apache-2.0 (MPL-2.0 y AGPL necesitan una nota).
- Verifica las dependencias pares contra la versión de React del proyecto.
Formato de respuesta
Un bloque, sin menú:
Base UI Toast para toasts. Apila, pausa al pasar el ratón y se desliza. No para nada que necesite acción; eso se queda en pantalla. MIT, mantenido.
npm i @base-ui/react.
Siempre da: para qué sirve, cuándo no usarlo, licencia, estado con la fecha que viste.
Antes de terminar
- Se leyó
package.json, y la elección no duplica una librería ya instalada. - Se verificó la respuesta de la plataforma y, si se saltó, la razón es una cláusula.
- Se ejecutó
npm viewen la elección, y el estado en la respuesta es el de hoy, no el del catálogo. - No se recomienda nada marcado como Sin mantenimiento.