0250
Inputs / Form fields Creacion Revision

Checkbox

Publicado
Lectura
4 min

El Checkbox parece trivial hasta que uno cuenta sus estados (marcado, no marcado, indeterminado, disabled, focus, error) y sus modos (single, grupo con select-all, persistente entre sesiones). Esta ficha documenta el Checkbox del sistema en mayo de 2026, con énfasis en su estado indeterminado, históricamente la fuente del 80% de los bugs reportados.

Decomposición del componente

Las seis capas del componente

01 · Átomo color.neutral.950 · color.red.500 · space.4 · radius.xs

Primitivos. Sin verdes ni ámbares como decoración: el checkbox usa el rojo accent solo para estado marcado.

02 · Compuesto color.checkbox.bg.unchecked · color.checkbox.bg.checked · color.checkbox.icon.checked · color.checkbox.border · space.checkbox.size

Semánticos. El size 18px corresponde a la altura de x del cuerpo tipográfico.

03 · Regla contract test tres estados · hit-target ampliado 44×44 · grupo padre con estado mixed

Governance específica del estado indeterminate: propagable solo vía JS. La técnica exige validación de grupo completo, no del item aislado.

04 · Pieza <Checkbox checked|indeterminate|unchecked label='...'>

Tres estados semánticos. indeterminate solo se deriva de grupo (select-all), nunca se declara aisladamente.

05 · Familia Inputs / Form fields · emparentado con Radio y Toggle

Checkbox es binario con confirmación posterior. Radio es excluyente. Toggle es binario con aplicación inmediata.

06 · Estado reposo · hover · focus-visible · checked · indeterminate · disabled · invalid · agent-aware

indeterminate existe solo via JS, no como atributo HTML.

Tokens consumidos

Semánticos

color.checkbox.bg.unchecked oklch(0.99 0.005 75)

Fondo en estado no marcado

color.checkbox.bg.checked oklch(0.53 0.18 26)

Fondo cuando está marcado, color action primary

color.checkbox.icon.checked oklch(0.99 0.005 75)

Icono check sobre fondo accent, contraste AAA

color.checkbox.border oklch(0.78 0.005 75)

Borde unificado con resto de inputs

space.checkbox.size 1.125rem

18px, alineado con la altura de la x del cuerpo de texto

Técnicas de governance aplicadas

Técnicas activas

Estado indeterminado obligatorio

Herramienta
Contract test
Cobertura
Grupos de checkboxes con padre y N hijos

Si el componente recibe estado=indeterminate, el atributo HTML5 indeterminate se aplica via JS (no es propagable como atributo declarativo). El test cubre los tres estados visualmente y aria-checked='mixed'.

Hit-target ampliado

Herramienta
Wrapper label clickeable
Cobertura
Toda el área del label más el cuadro suma >=44x44px

WCAG 2.5.5. La regla rechaza checkboxes con label de menos de 24 caracteres porque el área hit no alcanzaría el mínimo táctil.

Estado físico

Agentic-consumable desde noviembre de 2025. Un agente puede componer formularios con grupos de checkboxes; el contract incluye reglas para grupo (todo seleccionado, ninguno, mixed).

Estados soportados

hover, focus-visible, disabled, checked, indeterminate, invalid, agent-aware. El estado indeterminate es la única que requiere JavaScript para aplicarse (no existe atributo HTML).

Composiciones prohibidas

Reglas activas

indeterminate declarativo aislado

Herramienta
OPA · block level
Cobertura
Patrón correcto solo vía grupo

Agente que proponga checked='mixed' como atributo declarativo en un Checkbox aislado recibe rechazo. Solo grupo padre + hijos puede producir indeterminate.

Label inexistente o menor de 24 caracteres sin wrapper

Herramienta
OPA · block level
Cobertura
Hit-target WCAG 2.5.5

La suma del cuadro (18px) más el label debe alcanzar hit-target 44×44. Labels muy cortos requieren wrapper clickeable ampliado.

Grupo sin fieldset/legend

Herramienta
OPA · warning
Cobertura
SC 1.3.1 Info and Relationships

Un grupo de checkboxes relacionados debe vivir dentro de fieldset con legend. Sin legend, el SR lee items inconexos.

Interoperabilidad

  • Consumido por: CheckboxGroup, FormRow, SettingsPanel, TableRowSelect.
  • Consume: Label asociado por for/id, opcionalmente HelperText y ErrorMessage.
  • Con qué compone mal: junto a un Toggle con semántica parecida (decisión sin confirmar), dentro de Toast (efímero).
  • Sustituibles por: Toggle si el cambio es inmediato sin submit; Switch es sinónimo no canónico (se rechaza).

Medición propuesta

Eventos planificados

checkbox.toggle

Herramienta
OTLP · Events
Cobertura
Cada cambio de estado

Atributos: from, to, group (si aplica), ruta. Permite detectar patrones donde el usuario marca y desmarca en secuencia rápida (indicador de error de interpretación).

checkbox.group_mixed_resolution

Herramienta
OTLP · Metrics
Cobertura
Cómo se resuelve el estado mixed

Si el grupo padre llega a all vs none desde mixed, qué acción lo disparó. Informa si el 'select all' se usa o si los usuarios resuelven item-a-item.

Mutación plástica (Estado 3)

Qué muta y qué permanece

Hit-target size-clickeable = derive(pointer × viewport)

Touch amplía área clickeable del label a 48×48; desktop fine mantiene 44×44 por el wrapper ampliado.

Focus ring ring-intensity = derive(prefers-contrast)

Con high-contrast el focus ring sube un tono de contraste y dobla grosor a 3px.

Animación del check duration = derive(prefers-reduced-motion)

Con reduced-motion, el tick aparece instantáneo. Sin preferencia, fade-in 120ms.

Fijo por contract three-state enum · aria-checked mixed · label obligatorio

Contract que el agente no muta.

Rollback automático si se propone ocultar el check visual en estado checked (el lector debe ver el estado siempre) o si el hit-target se compacta por debajo de 44×44 bajo cualquier pretexto contextual.

Genealogía

Árbol de evolución

<input type='checkbox'> nativo estilizado

Reemplazo CSS clásico con clip-path para esconder el control y SVG decorativo encima.

Consumidor Diseñador y desarrollador

Componente React + estado indeterminado

Primer support para grupos. El bug del estado mixed apareció en cuatro productos durante seis meses.

Consumidor Producto · 12 productos

Checkbox governable

Contract test que cubre los tres estados como matriz. Hit-target ampliado obligatorio. Migrado a accent-color CSS donde el navegador lo soporta.

Consumidor Producto · 28 productos

Checkbox.AI · expuesto vía MCP

Schema de grupo expuesto con estados (all, none, mixed). Agente tier-2 puede componer listas filtrables sin inventar estados.

Consumidor Humano + agente

Notas del editor

Descartes catalogados

Variants rechazadas

variant='switch-style'

Checkbox con apariencia de switch. Confusión semántica: switch implica on/off inmediato, checkbox implica selección que se confirma luego. Se mantuvo como componente <Toggle /> separado con su contrato propio.

variant='tri-state-cycle'

Click cíclico checked → indeterminate → unchecked. Imposible de explicar al usuario en menos de cinco palabras y rompía las expectativas de gestores de pantalla. Se restringió a estados binarios con indeterminate sólo derivado de grupo.

Referencias cruzadas