Ir al contenido

Componentes · Ola 1 · Formularios

Checkbox

Marca o desmarca una opción independiente, con estado mixto para las listas.

import { Checkbox } from '@archeblack/ui';

Ejemplos

Con label

El uso más común: opciones independientes, cada una con su texto. bind:checked sigue el estado.

Svelte
<script lang="ts">
	import { Checkbox } from '@archeblack/ui';

	let weekly = $state(true);
	let deploys = $state(false);
</script>

<div style:display="grid" style:gap="var(--arche-spacing-1)">
	<Checkbox bind:checked={weekly} label="Enviar un resumen semanal" />
	<Checkbox bind:checked={deploys} label="Notificar cada despliegue" />
</div>

Con descripción

description explica la opción en text-muted, debajo del label.

Svelte
<script lang="ts">
	import { Checkbox } from '@archeblack/ui';
</script>

<Checkbox
	label="Notificar cada despliegue"
	description="Un correo por cada despliegue a producción, con el autor y el resultado."
/>

Estado mixto

Una casilla que agrupa a otras: indeterminate mientras solo algunas están marcadas.

Svelte
<script lang="ts">
	import { Checkbox } from '@archeblack/ui';

	const projects = $state([
		{ name: 'Portal de clientes', selected: true },
		{ name: 'API de pagos', selected: false },
		{ name: 'Motor de búsqueda', selected: false }
	]);

	const count = $derived(projects.filter((project) => project.selected).length);
</script>

<div style:display="grid" style:gap="var(--arche-spacing-1)">
	<!-- Mixta mientras solo algunos están marcados. El clic marca o desmarca todos. -->
	<Checkbox
		label="Seleccionar todos"
		checked={count === projects.length}
		indeterminate={count > 0 && count < projects.length}
		onchange={(event) => {
			for (const project of projects) project.selected = event.currentTarget.checked;
		}}
	/>
	<div style:display="grid" style:gap="var(--arche-spacing-1)" style:padding-inline-start="1.75rem">
		{#each projects as project (project.name)}
			<Checkbox bind:checked={project.selected} label={project.name} />
		{/each}
	</div>
</div>

Deshabilitada

disabled apaga la casilla y su texto, marcada o no.

Svelte
<script lang="ts">
	import { Checkbox } from '@archeblack/ui';
</script>

<div style:display="grid" style:gap="var(--arche-spacing-1)">
	<Checkbox label="Copias de seguridad diarias" disabled />
	<Checkbox label="Registro de auditoría" checked disabled />
	<Checkbox label="Plan de empresa" indeterminate disabled />
</div>

Sin texto visible

En una fila de tabla la casilla va sola: el nombre accesible va en aria-label.

Svelte
<script lang="ts">
	import { Checkbox } from '@archeblack/ui';
</script>

<!-- Sin texto visible (una fila de tabla, por ejemplo): el nombre va en aria-label. -->
<Checkbox aria-label="Seleccionar Portal de clientes" />
<Checkbox aria-label="Seleccionar API de pagos" checked />

Props

Props de Checkbox
PropDescripción
bind:checked? boolean Por defecto falseSi la casilla está marcada.
bind:indeterminate? boolean Por defecto falseEstado mixto: una casilla que agrupa a otras y solo algunas están marcadas. Se dibuja como una raya. El navegador lo apaga cuando el usuario hace clic.
label? string Texto de la casilla y su nombre accesible.
description? string Texto de ayuda debajo del label, en text-muted. Se asocia al input con aria-describedby.
children? Snippet Contenido del label cuando hace falta marcado, como un link. Tiene prioridad sobre label.
aria-label? string Nombre accesible cuando no hay texto visible. Si otro texto de la página ya la nombra, aria-labelledby con su id. Hace falta uno de label, children, aria-label o aria-labelledby: TypeScript rechaza una casilla sin nombre.
disabled? boolean Por defecto falseDeshabilita la casilla. El texto pasa a text-disabled.
class? ClassValue Clases del producto; se suman a arche-checkbox, el <label> que envuelve al control y su texto.
...rest HTMLInputAttributes Todo lo demás va al <input>: name, value, required, aria-invalid, onchange… El tipo lo fija el componente.

Accesibilidad

  • Es un <input type="checkbox"> nativo dibujado con appearance: none: el rol, el estado, el envío del formulario y la barra espaciadora son los del navegador.
  • El foco es el de Arche y se dibuja sobre la propia casilla.
  • Un <label> envuelve la casilla y su texto: toda la fila es clickeable y mide al menos 24 × 24 px, también sin texto.
  • El nombre accesible es solo el label; la descripción se anuncia aparte, con aria-describedby.
  • El estado mixto se anuncia como «mixto» (indeterminate es la propiedad nativa del input).
  • El borde de la casilla llega a 3:1 contra todas las superficies (border-control).
  • En colores forzados, la casilla marcada se pinta con Highlight y la marca con HighlightText: el estado no depende de un fondo que el navegador reemplaza.
  • Sin texto visible, el nombre va en aria-label o aria-labelledby. Los tipos exigen uno de los cuatro: TypeScript rechaza una casilla sin nombre.

Qué evitar

  • Una casilla para una acción que tiene efecto inmediato, como activar un servicio. Un Switch. La casilla es para opciones que se confirman después, al guardar o enviar.
  • Casillas para elegir una sola opción entre varias. Un RadioGroup: comunica que las opciones son excluyentes.
  • Un label negativo («No enviar correos»). El label dice lo que pasa al marcarla: «Enviar un resumen semanal».
  • Una casilla sin texto y sin aria-label. Siempre un nombre: el label, o aria-label si no hay texto visible.
  • Un <input type="checkbox"> suelto con estilos propios. <Checkbox>: el foco, el tamaño del objetivo y los colores forzados ya están resueltos.