Ir al contenido

Componentes · Ola 4 · Editorial

Chip

Una etiqueta corta con borde y un conteo opcional: un tema, un filtro. Estático, link o activable, y en grupo de selección única. Tiene 32 px de alto, un borde de 1 px y radio de 2 px; activo o actual, toma el fondo de la selección: blanco en Arche y el acento en cada producto.

import { Chip, ChipGroup } from '@archeblack/ui';

Ejemplos

Estáticos

Los temas del colofón de un post: texto, sin foco ni hover. Con items, ChipGroup es una lista.

  • Filosofía
  • Cultura
Svelte
<script lang="ts">
	import { ChipGroup } from '@archeblack/ui';
</script>

<!-- Los temas del colofón de un post: chips estáticos, en una lista. -->
<ChipGroup aria-label="Temas" items={[{ label: 'Filosofía' }, { label: 'Cultura' }]} />

Links a los temas

Cada tema lleva a su archivo, con su conteo. El actual (current) lleva aria-current="page" y la selección: en Arche y en Hermes.

Svelte
<script lang="ts">
	import '@archeblack/ui/products/hermes.css';
	import { ChipGroup } from '@archeblack/ui';

	// Los temas de Hermes con sus artículos. En la página de un tema, ese chip es el actual.
	const topics = [
		{ label: 'Filosofía', slug: 'filosofia', count: 4 },
		{ label: 'Cultura', slug: 'cultura', count: 3 },
		{ label: 'Videojuegos', slug: 'videojuegos', count: 2 },
		{ label: 'Tecnología', slug: 'tecnologia', count: 1 }
	];
</script>

<!-- Links a cada tema, con su conteo. El actual lleva aria-current="page" y la selección:
     blanca en Arche y el acento en Hermes. -->
<div style="display: grid; gap: var(--arche-spacing-5); width: 100%">
	{#each [undefined, 'hermes'] as product (product ?? 'arche')}
		<ChipGroup
			data-product={product}
			aria-label="Temas"
			items={topics.map((topic) => ({
				label: topic.label,
				href: `#${topic.slug}`,
				current: topic.slug === 'cultura',
				count: topic.count,
				countLabel: topic.count === 1 ? '1 artículo' : `${topic.count} artículos`
			}))}
		/>
	{/each}
</div>

Selección única

El filtro de las publicaciones: ChipGroup con options y bind:value. Es un radiogroup: prueba con Tab y las flechas.

Tema elegido: Todas

Svelte
<script lang="ts">
	import '@archeblack/ui/products/hermes.css';
	import { ChipGroup } from '@archeblack/ui';

	let topic = $state('all');

	const options = [
		{ value: 'all', label: 'Todas', count: 5 },
		{ value: 'filosofia', label: 'Filosofía', count: 4 },
		{ value: 'cultura', label: 'Cultura', count: 3 },
		{ value: 'videojuegos', label: 'Videojuegos', count: 2 },
		{ value: 'tecnologia', label: 'Tecnología', count: 1 }
	].map((option) => ({
		...option,
		countLabel: option.count === 1 ? '1 artículo' : `${option.count} artículos`
	}));

	const chosen = $derived(options.find((option) => option.value === topic)?.label);
</script>

<!-- El filtro de las publicaciones: una sola opción a la vez. Es un radiogroup: Tab entra en la
     elegida y las flechas cambian la selección. -->
<div data-product="hermes" style="display: grid; gap: var(--arche-spacing-3); width: 100%">
	<ChipGroup aria-label="Filtrar publicaciones por tema" {options} bind:value={topic} />
	<p style="margin: 0; color: var(--arche-color-text-muted)">
		Tema elegido: {chosen}
	</p>
</div>

Activables

Varios a la vez: cada chip es un botón con aria-pressed y bind:pressed. Deshabilitado, el texto y el borde se apagan.

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

	let filosofia = $state(true);
	let cultura = $state(false);
	let videojuegos = $state(false);
</script>

<!-- Chips activables, para elegir varios temas a la vez. Cada uno es un botón con aria-pressed;
     el grupo lleva su nombre con role="group". -->
<div
	role="group"
	aria-label="Temas de la búsqueda"
	style="display: flex; flex-wrap: wrap; gap: var(--arche-spacing-2)"
>
	<Chip label="Filosofía" bind:pressed={filosofia} />
	<Chip label="Cultura" bind:pressed={cultura} />
	<Chip label="Videojuegos" bind:pressed={videojuegos} />
	<Chip label="Tecnología" pressed={false} disabled />
</div>

Conteo

La cifra en mono, con countLabel para leerla con su unidad.

Todo 7 resultados Publicaciones 5 resultados Temas 2 resultados
Svelte
<script lang="ts">
	import { Chip } from '@archeblack/ui';
</script>

<!-- El conteo va en mono con cifras tabulares. countLabel dice cómo se lee: el lector de pantalla
     oye «Publicaciones 5 resultados» y no solo la cifra. -->
<div style="display: flex; flex-wrap: wrap; gap: var(--arche-spacing-2)">
	<Chip label="Todo" count={7} countLabel="7 resultados" />
	<Chip label="Publicaciones" count={5} countLabel="5 resultados" />
	<Chip label="Temas" count={2} countLabel="2 resultados" />
</div>

Props

Chip

Props de Chip
PropDescripción
label? string El texto del chip.
children? Snippet Contenido propio en lugar de label.
count? number | string Un conteo al final, en IBM Plex Mono de 12 px con cifras tabulares, en text-subtle.
countLabel? string Cómo se lee el conteo («3 artículos»). El lector de pantalla oye este texto; en la pantalla se ve la cifra.
href? string Con href, el chip es un <a>.
current? boolean Solo con href: la página actual. Pone aria-current="page" y el aspecto de la selección.
bind:pressed? boolean Con pressed (aunque sea false), el chip es un <button aria-pressed> que se prende y se apaga.
onPressedChange? (pressed: boolean) => void Se llama al prender o apagar, con el valor nuevo, después de actualizar pressed y solo si el cambio se aceptó.
disabled? boolean Por defecto falseSolo en un chip activable.
class? ClassValue Se suma a arche-chip.
...rest HTMLAttributes Van al elemento: <span>, <a> o <button>.

ChipGroup

Props de ChipGroup
PropDescripción
options? ChipGroupOption[] Selección única: { value, label, count?, countLabel?, disabled? }. El grupo es un radiogroup de Bits UI y cada opción, un chip con role="radio".
bind:value? string Con options: el valor elegido.
onValueChange? (value: string) => void Con options: se llama al elegir otra opción, después de actualizar value y solo si el cambio se aceptó.
name? string Con options: el nombre del campo para enviar el formulario.
required? boolean Por defecto falseCon options y name: exige elegir una opción.
disabled? boolean Por defecto falseCon options: deshabilita todo el grupo.
items? ChipGroupItem[] Lista: las props de un Chip por ítem (y una key opcional). El grupo es un <ul> con un <li> por chip.
aria-label | aria-labelledby? string El nombre del grupo. Obligatorio con options (TypeScript lo exige); opcional en una lista.
class? ClassValue Se suma a arche-chip-group.
...rest HTMLAttributes Van al radiogroup o al <ul>.

Accesibilidad

  • El elemento sale de las props: sin href ni pressed es texto (<span>), con href un link y con pressed un botón con aria-pressed. Un chip estático no recibe el foco ni cambia con el puntero.
  • El chip actual de una lista de links lleva aria-current="page": el lector anuncia «página actual», además del fondo de la selección.
  • Un grupo de selección única es un radiogroup con nombre: una sola parada del tabulador, las flechas mueven la selección y el lector anuncia «1 de 5». No es una fila de botones con aria-pressed, que se leerían como interruptores sueltos.
  • Con countLabel, el conteo se lee como texto («Filosofía 4 artículos»); sin él, la cifra sola es parte del nombre.
  • Mide al menos 32 px de alto (WCAG 2.5.8). El foco es el anillo de Arche; activo y con foco, el halo y el brillo de la selección se suman.
  • Un chip que es un control (un link, un botón activable o una opción de un grupo) tiene el borde en border-control, que llega a 3:1 contra el fondo como el límite de todo control; en hover sube a border-control-hover. El chip estático, que no es un control, lo lleva en border-strong.
  • La selección no depende del brillo: en colores forzados pasa a Highlight con HighlightText, y el borde a ButtonBorder.

Qué evitar

  • Píldoras (radio completo) o corchetes alrededor del texto. El radio de 2 px de los controles de Arche (D11a).
  • Una fila de chips activables para elegir una sola opción. ChipGroup con options: un radiogroup, con el teclado de un grupo de radios.
  • Marcar el tema actual solo con el color. Un link con current: aria-current="page" y el fondo de la selección.
  • Chips para acciones («Guardar», «Compartir»). Button. Un chip nombra un tema o un filtro.