El criterio de completitud · medido el 19 de agosto de 2026
Lo que falta se cuenta, no se recuerda
Si con las piezas del kit se puede rearmar una copia de un producto real, el kit está completo; lo que no se pueda rearmar es exactamente lo que falta. El producto es GestorSalon —el vertical más completo del ecosistema— y la medición es mecánica: 2.154 archivos leídos, 252 símbolos del kit encontrados en uso, 625 componentes propios genéricos catalogados. Lo que salió de ahí son dos listas distintas, y la más incómoda es la primera.
- Símbolos en uso
- 252
- Existían y no se mostraban
- 113
- Componentes propios
- 625
- Huecos reales del kit
- 7
Cómo se mide
Tres pasadas, en este orden. Primero se leen los 2.154 archivos del producto y se anota cada símbolo del kit que aparece, con cuántas veces se usa, en cuántos archivos y con qué props. Segundo, se pregunta al paquete instalado qué exporta de verdad cada subpath — no a su documentación, que puede estar atrasada, sino al paquete. Tercero se cruzan las dos listas contra los especímenes que esta galería monta.
El resultado del cruce es un número que no se puede discutir: de los 252 símbolos que el producto usa, 139 estaban en la galería y 113 no. Ninguno de esos 113 es una pieza que haya que construir: todos existen, publicados, en la versión instalada. Eran capacidad pagada que nadie sabía que tenía.
Lo que este método NO puede ver, y se dice antes de los números
La lectura es por expresiones regulares sobre el texto, con un autómata que descarta comentarios y cadenas — no un árbol de sintaxis. Cuenta bien lo que está escrito de la forma normal y no ve lo que se arma dinámicamente. Y midió contra la versión del kit realmente resoluble en el node_modules del producto, que ese día estaba un día atrasada respecto de su propio package.json. Los dos límites cambian números al margen; ninguno cambia las conclusiones, porque las conclusiones se apoyan en diferencias de un orden de magnitud, no de un dígito.
Las 113 que el kit ya tenía
Están todas montadas ahora, cada una con su ficha, su especificador de import y las props que el producto realmente le pasa. Este es el reparto por familia, y el reparto cuenta una historia por sí solo.
| Familia | Piezas | Lo que dice el número |
|---|---|---|
| Entrada | 44 | La más grande, y la que explica por qué: acá viven las siete piezas del subpath `forms` —entre ellas las cinco del formulario validado, que después de Button son los cinco símbolos más usados del kit en todo el producto— y las siete que sólo existen en la raíz del paquete. |
| Respuesta | 20 | Ninguna era una pieza nueva: son las versiones COMPUESTAS de las cinco que la galería ya mostraba armadas. |
| Presentación | 14 | Cuatro de ellas sin subpath: `ScrollArea`, `GradientText`, `DashboardContainer` y `PercentageBadge`. |
| Comportamiento | 12 | `useConfirmDialog` entre ellas, con un espécimen viejo que enseñaba a reimplementarla a mano. |
| Movimiento | 9 | Ocho son el vocabulario de movimiento —duraciones, curvas, resortes— que no estaba documentado en ninguna parte. |
| Utilidades | 6 | Cinco son de temporadas: parsear un rango sin año es de lo más difícil que tiene este dominio y estaba resuelto. |
| Navegación | 6 | Mismo patrón que en Respuesta: la galería mostraba el sidebar armado, el producto usa su interior. |
| Datos | 2 | El buscador con rebote y el título accesible de una tabla. |
Cobertura no es lo mismo que utilidad
Las veinte de «Respuesta» son el caso que más enseña: no falta ni una pieza de esa familia. Faltaba la mitad de cada pieza. La galería mostraba el panel lateral armado y el producto usa el panel en seis partes; mostraba el tooltip armado y el producto usa los tres pedazos; mostraba la paleta de comandos entera y el producto usa las siete primitivas sueltas para meter un buscador adentro de otro panel. Un catálogo puede tener cobertura completa y estar enseñando la mitad que nadie usa.
Y montar las 44 de «Entrada» destapó algo que ninguna firma decía: FormLabel no funciona suelto. Su tipo es una etiqueta HTML y nada más, y fuera de un FormField lanza en tiempo de ejecución y voltea la ruta con un 500 — con el typecheck y el control estructural los dos en verde. Apareció al abrir la página, no al compilarla.
Y armar bien ese mismo espécimen destapó un defecto del kit
Al escribir el formulario como corresponde —FormField con sus reglas, FormLabel, FormControl, FormMessage— el estado de error resultó ir un render atrasado. Medido en la versión instalada, en la página del Muestrario, con el campo obligatorio vacío: tres envíos seguidos y el campo sigue declarando aria-invalid="false" sin mensaje. Al escribir un valor válido, recién ahí la etiqueta se pone en rojo y aparece «El salón necesita un nombre» — sobre un campo que ya está bien.
Como un campo inválido no provoca renders nuevos, el error no se muestra nunca mientras el campo está mal, y sí se muestra una vez justo después de arreglarse. Un lector de pantalla recibe lo contrario de la verdad en los dos momentos. Son las cinco piezas más usadas del kit en el producto: 30 archivos, cerca de 890 usos. La causa probable —una línea del paquete compilado que lee el estado del campo sin quedar suscripta a sus cambios— queda anotada donde vive el espécimen; la corrección es de quien gobierna el package, no de este puesto.
El dato de método, que es por lo que está acá: esto no lo ve un typecheck, no lo ve un control estructural, y no lo ve una captura de pantalla. Sólo aparece usando la pieza —vaciando el campo, tocando Guardar, mirando qué dice el atributo— que es lo que un espécimen bien hecho obliga a hacer y una tabla de props no.
Los siete huecos reales
De los 625 componentes propios genéricos del producto, la enorme mayoría son composiciones de su dominio que no tienen por qué salir de ahí. Estos siete no: no tienen equivalente en los 642 exports del paquete, resuelven un problema que vuelve en cada vertical, y están ordenados por cuánto duele — cuántas pantallas toca, si lo ve el cliente final, y si es la clase de cosa que se implementa mal la primera vez.
Una imagen remota que se banque una URL rota
Es el componente propio genérico más usado de todo el producto. El kit tiene con qué SUBIR una imagen (ImageUpload, ImagePickerDialog), con qué construir su URL (getImageUrl) y con qué mirarla en grande (Lightbox, PhotoGalleryModal) — y nada con qué MOSTRARLA. Toda superficie que pinta una foto cargada por un cliente termina escribiendo su propio guard de error, y la que no lo escribe muestra el ícono de imagen rota.
RemoteImage · 30 usos en 26 archivos · src/components/shared/remote-image.tsx:72Imprimir
Cero símbolos del kit contienen la palabra «print», sobre 642 exports de la raíz. Un salón imprime el contrato, la lista de invitados y el resumen de caja; una heladería imprime el ticket; una clínica imprime la orden. Es una superficie entera —tipografía, márgenes, cortes de página, qué se oculta al imprimir— que hoy cada vertical descubre de nuevo.
PrintSheet + PrintSummaryCard · 9 usos en 6 archivos · src/components/shared/print-sheet.tsx:35 y :84La pantalla de error de una aplicación
El kit tiene `ErrorBoundary` (que atrapa) y `EmptyState` (que explica un vacío), y nada entre los dos: la página completa que dice qué pasó, ofrece reintentar y ofrece volver. Dieciséis archivos la usan y está compuesta enteramente de piezas del kit — o sea que el hueco no es de capacidad, es de composición.
AppErrorPage · 16 usos en 16 archivos · src/components/ui/app-error-page.tsx:15Forzar el esquema claro en una superficie pública
Una propuesta que se le manda a un cliente no puede salir en oscuro porque el cliente tenga el teléfono en oscuro. El kit tiene `ThemeToggle` para cambiarlo y nada para FIJARLO. La implementación propia necesita un script inline antes del primer pintado y un MutationObserver para que nada se lo vuelva a dar vuelta: es infraestructura, no una decisión de producto, y por eso pertenece al kit.
ForceLightProvider · 5 usos en 5 archivos · src/components/public/force-light.tsx:41El cajón de navegación móvil
El kit trae `MobileBottomNav` (la barra de abajo) y `SidebarNavigation` (la columna de escritorio). El cajón que entra de costado en móvil —con su bloqueo de scroll, su trampa de foco y su cierre al navegar— no está, y es el tercer patrón obligatorio de cualquier app de gestión en teléfono.
AppNavDrawer · 6 usos en 6 archivos · src/components/layout/app-nav-drawer.tsx:130El fondo decorativo que sigue al tema
Las superficies que se comparten con un cliente —invitación, propuesta, portal— necesitan un fondo con carácter que no sea una imagen. Sin una pieza del kit, cada una lo resuelve con su propio degradado y su propia superposición a pantalla completa: diez de esas superposiciones están escritas a mano en el producto, y ninguna comparte z-index ni curva de opacidad con las otras.
ThemeBackground · 3 usos en 2 archivos · src/components/portal/theme-patterns.tsx:69 · más 10 superposiciones `fixed inset-0` escritas a manoEl flujo de importar datos
Pegar un CSV, ver el ejemplo del formato esperado, previsualizar filas, marcar las que fallan. Aparece en todo producto que reemplaza una planilla, que son todos. Es el hueco más grande de los siete en superficie, y el único donde no está claro cuánto es genérico y cuánto es del dominio: por eso va último y va con esa duda escrita.
UnifiedImportExamplesSheet + ImportFromPackageDialog · 17 usos en 17 archivos · src/components/shared/unified-import-examples-sheet.tsx:320
Por qué siete y no cincuenta
Porque un backlog de cincuenta ítems no se ejecuta: se archiva. El filtro fue duro a propósito — entra sólo lo que (a) no existe con ningún nombre en el paquete instalado, (b) el producto usa en más de un archivo, y (c) es infraestructura y no una decisión de negocio. Lo que quedó afuera por (c) es mucho y está bien que quede afuera: una tarjeta de reserva de salón no va a un kit compartido por más veces que aparezca.
El hueco más grande no es una pieza que falta
Es que las piezas que hay no se encuentran. De los 254 imports del kit en el producto, 231 entran por la raíz y 23 por alguno de los diecinueve subpaths publicados. Y 196 de esos símbolos viven en un subpath de familia y se importan igual desde la raíz. El mapa de exports está cuidado, versionado y documentado — y el producto real trata al paquete como un solo barril.
Trece piezas de las 113 agravan la misma cosa desde el otro lado: no las expone ningún subpath, sólo la raíz. Una galería organizada por familias —ésta— no tiene dónde ponerlas, y por eso llevaban sin aparecer desde que existen. Y un hook aparece catalogado en una familia cuyo subpath no lo exporta ni en tipos ni en tiempo de ejecución.
La consecuencia práctica, que es la que importa
Doce componentes del producto tienen exactamente el nombre de un export del kit, y suman 72 usos. Cuando alguien reimplementa una pieza y le pone el mismo nombre que la pieza que ya existía, el problema no fue de vocabulario ni de criterio: fue que no la encontró. Ese es el argumento más fuerte que hay para que esta galería exista, y también la vara con la que se la va a juzgar dentro de seis meses.
Las reglas de cómo se mide
Cada una con el incidente que la produjo. Una regla sin su caso es una opinión con formato de norma, y a los tres meses nadie sabe por qué está — que es cuando alguien la saca.
Fondo e ink se fijan juntos, y ninguno de los dos se toma prestado del otro
Tres incidentes distintos, el mismo error de raíz: alguien fijó uno de los dos y dejó que el otro viniera heredado. (A) El escenario de los especímenes fijaba el fondo del kit y no el color: el texto heredaba el ink del SITIO, que sigue a la preferencia del sistema operativo mientras el fondo del kit no, y con el sistema en claro daba rgb(20,24,29) sobre rgb(13,14,20) — 1.08 a 1, con 112 de 157 nodos de una sola ruta por debajo de su piso. (B) Cuatro pantallas del portal de GestorSalon pintan su fondo con el token de TEXTO, `from-content to-content`: el mismo error con los factores invertidos. (C) El encabezado de estos bloques nuevos usaba el acento al 10% —un fondo TRASLÚCIDO del kit— junto a `text-content`: el papel del sitio se ve a través, el fondo efectivo queda claro y el ink del kit sigue siendo casi blanco. Daba 1.01 a 1 en las ocho familias. Con fondo opaco da 13.8 a 1, medido en las catorce rutas y en los dos esquemas.
Un token de color tiene un rol, y el rol no es intercambiable aunque el valor sirva
Es el corolario del incidente B de la regla anterior, y merece enunciarse solo porque se comete al revés de lo que uno espera: el token de texto usado como superficie no da error, no da warning y hasta puede verse bien en el esquema en el que se lo probó. Lo que se rompe es la promesa de que invertir el tema invierte la pantalla — porque los dos extremos del gradiente son el mismo rol, y ese rol se mueve para el lado contrario.
Un fondo traslúcido no cierra el par: deja pasar la superficie de abajo
Corolario del incidente C, y es el que se escapa a quien ya conoce la regla. `bg-container` + `text-content` está bien. `bg-primary/10` + `text-content` está mal, y se parece muchísimo: el 10% deja ver el papel del sitio, que sí se da vuelta con la preferencia del sistema, mientras el ink del kit no. La regla operativa: si el color viene del kit, el fondo que lo acompaña tiene que ser OPACO y del kit.
Un número medido en un solo esquema no está medido
El defecto de arriba era invisible midiendo sólo en oscuro. Aparece entero al forzar la preferencia en claro, que además es el esquema con el que la mayoría de la gente abre una página.
Un token mal calibrado cuesta doce páginas, no una
El gris terciario del sitio da 3.56 a 1 sobre el papel claro en texto de 10,5 px — el tamaño exacto de las etiquetas de las fichas técnicas. Falla el piso AA en las doce rutas del Muestrario a la vez, y es UN SOLO VALOR. Arreglarlo es una línea; encontrarlo cuesta doce mediciones si se busca página por página.
Un control que pasa no valida el instrumento: tiene que ejercitar el camino que el caso real usa
Dos mitades, y la segunda es la que enseña. (1) Un medidor de contraste reportó 1.00 a 1 —texto invisible— sobre un nodo que mide 5.55 a 1. Su control era negro puro sobre blanco puro, daba 21.00 en las veinticuatro corridas, y por eso se dio la medición por buena; pero ese control sólo ejercita el camino de fondos OPACOS, y lo que estaba roto era la composición de capas TRASLÚCIDAS: su aritmética usaba el alfa del frente y trataba el fondo como opaco, así que dos capas del mismo tono al 12% colapsaban en ese tono sólido y el texto quedaba «sobre sí mismo». (2) Al escribir el control que faltaba, el primer intento TAMPOCO servía: apilaba las dos capas traslúcidas sobre el fondo opaco de la página, y con una base opaca abajo ni un medidor con ese bug colapsa —le da 5.48 contra 5.55— así que el control pasaba igual. Recién ejercita el camino real cuando la pila arranca traslúcida, sin base opaca. Verificado en las dos direcciones: instrumento sano 1.96, instrumento con el bug exacto 1.00 y aborta; y los otros dos controles pasan en los dos casos, que es precisamente el punto.
Un gate que pasa a la primera no está verificado
Se falsifica cada rama: se rompe a propósito, se mira que reclame, se restaura y se compara el hash del archivo. Al ampliar el control de esta galería para que conozca los 19 subpaths del paquete se hicieron las dos mitades — con la lista vieja daba dos hallazgos sobre código correcto; con la nueva da cero y sigue atrapando un símbolo inventado.
Un control que sólo conoce parte de su dominio no aprueba: ensucia
El control de esta galería verificaba los símbolos importados contra una lista de 8 subpaths escrita a mano, y el paquete publica 19. Un espécimen que importara de `@solu30/ui-kit/forms` —donde vive la segunda pieza más usada del kit en todo GestorSalon— no pasaba en silencio: caía en la rama «no encontré sus tipos» y reportaba un problema que no existía. Un control que no puede mirar algo tiene que decir eso y no otra cosa, y la forma de que no se atrase es que la lista salga del paquete, no del control.
Mismo rótulo, dos números, es un defecto
El índice de componentes mostraba «150 exports» para una familia y su propia ficha mostraba 149. Los dos números eran correctos y contaban cosas distintas: uno parsea los bloques del archivo de tipos e incluye los tipos, el otro cuenta valores en tiempo de ejecución. El defecto es el rótulo compartido, no el número.
Un número del catálogo no es un número del paquete
El catálogo de GestorSalon midió contra la versión de `@solu30/ui-kit` REALMENTE resoluble en su `node_modules` —5.2.0— mientras su `package.json` y su lock declaran 5.8.0, que aparece treinta veces en el lock y 5.2.0 ni una. `node_modules` quedó un día atrás de la última instalación. Y esto no es una nota al pie: esta galería corre la 5.8.1 y exporta 666 símbolos en runtime; la 5.2.0 que el producto resuelve exporta 640. Cuatro de las piezas montadas acá —`Collapse` y tres transiciones de movimiento— existen en la de acá y no en la de allá. Una ficha puede verse impecable en esta página y no compilar en el repo que la va a consumir, y el desfase es INVISIBLE desde acá. Por eso cada ficha lleva el dato por símbolo en vez de confiarlo a que alguien lo recuerde. Todo lo que se mide contra «lo instalado» tiene que decir contra QUÉ instalado, porque un `pnpm install` mueve el piso.
Un contador que lee el texto crudo cuenta los comentarios
La primera pasada de esta misma medición tokenizó el texto completo de los especímenes para saber qué símbolos ya estaban montados, y dio 108. El encabezado de uno de los archivos explica EN PROSA por qué `FormField`, `FormItem`, `FormControl` y `FormMessage` quedaban deliberadamente afuera — y el contador leyó esos cuatro nombres del comentario y los dio por montados. Son, después de `Button`, los cuatro símbolos más usados del kit en todo el producto: 187, 187, 181 y 159 usos. Sacando comentarios antes de tokenizar, el número real es 113. La ironía es el dato: el comentario que documenta una ausencia es lo que la hace invisible al medidor.
Un archivo de intercambio entre agentes se verifica al consumirlo, no al anunciarlo
El catálogo que ordena todo este trabajo se anunció completo y se leyó completo. Noventa segundos después medía 0 bytes: quien lo produjo seguía vivo y lo estaba reescribiendo. Entre «existe y parsea» y «lo leí» cabe una reescritura entera, y un JSON a medias no da error de lectura: da un objeto incompleto que se parece a un dato. La forma correcta de publicar uno es escribir a un temporal y renombrar al final, porque el rename es atómico y nunca deja al lector viendo un archivo a medias. La forma correcta de consumirlo es verificar tamaño y forma en el momento de leerlo, y si no cierra, parar en vez de seguir con datos parciales.
Una tarea que miente sobre lo hecho es el peor dato de un plan
Una fase figuraba terminada desde las 10:58, su ruta daba 404, y el historial de git no tiene un solo commit que haya creado esa carpeta. Un plan con una tarea falsa es peor que un plan vacío: el vacío se nota, la mentira se hereda.
Las reglas de qué le falta a un kit
Las de arriba sirven para no mentirse con los números. Éstas son las que salieron de mirar el resultado, y son las que se aplican al medir el vertical número dos.
Un símbolo que exige contexto se monta con su contexto o no se monta
`FormLabel` y `FormDescription` se montaron sueltos, como si fueran una etiqueta y un párrafo. Llaman a `useFormField()`, que exige el proveedor que abre `FormField`, y la ruta entera pasó a 500 — no el espécimen: la ruta, porque el error es de render y está en el nivel de arriba. Ni el typecheck ni el control estructural lo ven, porque el tipo de `FormLabel` es el de una etiqueta HTML y nada más. Y la parte cara: el archivo de especímenes que este bloque vino a acompañar YA lo tenía escrito, dos líneas arriba de donde se escribió el import, explicando que ese subpath quedaba deliberadamente afuera por exactamente este motivo. Leer el catálogo no alcanza: hay que leer el archivo al que uno se va a sumar. Las tres salidas honestas son montarlo con su proveedor de verdad, usar la pieza suelta equivalente —que acá es `Label`, del subpath `input`— o documentarlo sin renderizarlo; lo que no es una salida es montarlo suelto y ver si anda.
Un espécimen que sólo se mira no prueba nada: hay que usarlo
Las cinco piezas del formulario validado se montaron bien, compilaron, pasaron el control estructural y en la captura se ven perfectas. Recién al VACIAR el campo obligatorio y tocar Guardar apareció que el estado de error va un render atrasado: tres envíos seguidos con el campo vacío y `aria-invalid` sigue en `false` sin mensaje, y el error aparece —una sola vez— justo después de escribir un valor correcto. Son las cinco piezas más usadas del kit en el producto. El defecto no lo ve un typecheck, no lo ve un gate y no lo ve una captura: sólo lo ve alguien que interactúa.
Dos APIs paralelas para la misma pieza son un agujero, aunque las dos estén publicadas
La galería mostraba `Sheet`, `Tooltip`, `CommandPalette`, `ConfirmDialog` y `useToast`, y declaraba la familia cubierta. El producto usa las otras cinco: `SheetRoot` con sus seis partes en 106 archivos, `TooltipRoot` con sus tres en 41, las siete primitivas de `Command`, `useConfirmDialog` en 11, y `toast` —el singleton importable— en 295. Cobertura del 100% por familia, y 0% de la API que el producto realmente escribe. La versión compuesta no es «la de bajo nivel»: es la que hace falta apenas el pie del panel deja de poder viajar con el scroll del cuerpo.
Un símbolo al que sólo se llega por la raíz no está en ninguna familia
Trece de los 113 —`ScrollArea`, `FormSection`, `FormSheet`, `GradientText`, `DashboardContainer`, `PercentageBadge`, los tres de edición en línea, los dos de imágenes y los dos hooks de confirmación— no los expone ningún subpath. Una galería organizada por familias no tiene dónde ponerlos, y por eso llevaban sin aparecer desde que existen. El hueco no es del catálogo: es del mapa de exports del paquete.
Los tipos de un subpath pueden no coincidir con su runtime, ni con la raíz
`useConfirmDialog` está catalogado en la familia «hooks», y ni los tipos ni el runtime de `@solu30/ui-kit/hooks` lo exportan: sólo la raíz. Un consumidor que lo busque donde el catálogo dice que está no lo encuentra, y el error que recibe no le dice dónde mirar.
Un mapa de exports que nadie usa no es un mapa: es documentación
De los 254 imports del kit en GestorSalon, 231 entran por la raíz y 23 por un subpath. Y 196 de esos símbolos VIVEN en un subpath de familia y se importan igual desde la raíz. Diecinueve subpaths cuidadosamente publicados, y el producto real trata al paquete como un solo barril.
El mismo símbolo importado desde dos especificadores es una decisión que nadie tomó
`SPRING` entra desde `@solu30/ui-kit/tokens` en 10 archivos y desde la raíz en 4, en el mismo repositorio. Ninguna de las dos formas está mal, y esa es exactamente la razón por la que conviven: cuando las dos funcionan, la elección la termina haciendo el autocompletado.
Dos funciones hermanas con unidades distintas son un error esperando
`addDurationToTime(hora, duración)` toma HORAS y su vecina `calcDurationMinutes(desde, hasta)` devuelve MINUTOS. Están contiguas en el mismo módulo y nada en el nombre lo dice. En la misma familia, `parseMonthDay` LANZA con una entrada inválida mientras su hermana `tryParseMonthDay` devuelve `undefined` — y la que usa el producto es la que lanza.
Un componente propio con el mismo nombre que uno del kit es la duplicación más cara
Doce componentes de GestorSalon tienen exactamente el nombre de un export del kit —`ImageUpload`, `StatusBadge`, `CollapsibleSection`, `MetricCard`, `InlineText`, `TableRow`, entre otros— y suman 72 usos. Uno de esos archivos vuelve a declarar cuatro constantes del vocabulario de movimiento del kit con sus mismos nombres. No es que alguien haya decidido no usar el kit: es que nadie supo que estaba, y el nombre idéntico prueba que el problema no era de vocabulario.
Lo que no es un componente no aparece en un catálogo de componentes, y por eso se reescribe
`selectCls` es la cadena de clases con la que el kit viste un `<select>` nativo. No tiene markup, así que ninguna galería la muestra. GestorSalon tiene nueve `<select>` nativos. Lo mismo pasa con las duraciones, las curvas y los resortes: ocho constantes de movimiento que se importan a mano en 14 archivos y que no estaban documentadas en ninguna parte de esta galería hasta hoy.
La otra lista, que no es de este puesto
La misma pasada que dice qué le falta al kit dice qué está mal implementado del lado del producto, y son dos listas con dueños distintos. Ésta se entrega a quien mantiene el vertical; acá queda sólo la medición, sin ejecutarla, porque arreglar código de un producto ajeno desde el puesto del sistema de diseño es como se rompen dos repositorios a la vez.
| Lo medido | Cuánto | Por qué importa |
|---|---|---|
| Componentes propios con el nombre de uno del kit | 12 · 72 usos | Prueba que el problema fue de descubrimiento, no de criterio. |
| Colores escritos a mano en TSX | 103 · 39 distintos | Cada uno es un punto que no se da vuelta con el tema. |
Tablas <table> nativas | 32 | Y un solo título accesible de tabla en todo el producto. |
<select> nativos | 9 | El kit publica la cadena de clases exacta para vestirlos. |
| Superposiciones a pantalla completa a mano | 10 | Ninguna comparte z-index ni curva de opacidad con las otras. |
Combinaciones de clases repetidas (flex gap-2 items-center) | 314 · 212 archivos | El candidato más claro a componente de layout del kit. |
Para qué sirve esta página
Para el vertical número dos. Cuando toque medir la heladería, el club o el SDR, el método ya está escrito y las reglas ya están pagadas: se corre el catálogo, se cruza contra lo montado, se separan las dos listas y se entrega cada una a su dueño. Lo que no hay que volver a descubrir es que la cobertura no es utilidad, que el símbolo que no se encuentra se reimplementa con su mismo nombre, que un número medido en un solo esquema no está medido, y que la versión contra la que se mide hay que decirla siempre — porque el producto que se está midiendo puede estar resolviendo otra.
Medición del 19 de agosto de 2026 sobre GestorSalon y sobre @solu30/ui-kit 5.8.1 instalado · los 113 símbolos están montados en las ocho familias de /kit/componentes · el reparto por familia sale del mismo módulo de datos que alimenta las fichas