Botón

Lanza una acción o lleva al siguiente paso. Un solo botón principal por grupo de acciones.

Landing y portal

Las dos superficies usan las mismas clases, definidas en public/site/button.css. En la landing se escriben a mano; en el portal las pone el componente Button.

Principal y secundario

html · landing
<a class="button" href="#">Reservar llamada</a>
<a class="button button-outline" href="#">Ver el plan</a>

Pequeño

Cabecera y navegación móvil.

html · landing
<a class="button button-outline button-small" href="#">Área clientes</a>
<a class="button button-small" href="#">Reservar llamada</a>

Claro, sobre fondo oscuro

html · landing
<a class="button button-light button-small" href="#">Reservar llamada</a>

Ancho completo

Dentro de la tarjeta del plan.

html · landing
<a class="button button-block" href="#">Empezar</a>

Con icono

html · landing
<button type="submit" class="button button-small"><span>Preparar email</span><svg viewBox="0 0 16 16" aria-hidden="true"><path d="M8 13V3M4 7l4-4 4 4"/></svg></button>

Del portal: discreto y peligro

html · portal
<button class="button">Guardar cambios</button>
<button class="button button-ghost">Cancelar</button>
<button class="button button-danger">Eliminar</button>

API de clases

Clase Qué hace
button Base: relleno --ink, texto --paper, 44 px de alto, texto de 15 px, radio de 12 px. Hover en --ink-hover.
button-outline Secundario: fondo transparente, borde --line-strong; hover en --paper-2.
button-ghost Sin borde ni fondo, texto --ink-2; hover en --paper-2. Acciones terciarias del portal.
button-subtle Fondo --card con borde --line.
button-danger Relleno --danger, texto blanco. Solo para acciones destructivas.
button-light Para fondos oscuros: relleno --paper, texto --ink.
button-small 36 px de alto, texto de 14 px, radio de 10 px.
button-block Ocupa todo el ancho de su contenedor.

Portal

Button y ButtonLink, en src/components/ui/button.tsx. Traducen sus props a las clases de button.css: variant="outline" → button-outline, size="sm" → button-small. className se añade al final y las utilidades de Tailwind (w-full, márgenes) pueden ajustarlo, porque el botón está en la capa components.

tsx
import { Button, ButtonLink } from '@/components/ui';

<Button>Guardar cambios</Button>
<Button variant="ghost">Cancelar</Button>
<Button variant="danger">Eliminar</Button>
<ButtonLink href="/admin/clients/new" size="sm">Nuevo cliente</ButtonLink>
html · portal
<button class="button">Guardar cambios</button>
<button class="button button-ghost">Cancelar</button>
<a href="#" class="button button-small">Nuevo cliente</a>

Props

Prop Valores Por defecto
variant primary, outline, ghost, subtle, danger primary
size sm (36 px, 14 px, radio de 10 px), md (44 px, 15 px, radio de 12 px) md
type button, submit, reset button

Cuándo usarlo

  • Para una acción: reservar una llamada, empezar la suscripción, enviar un formulario, guardar cambios.
  • Para ir a un destino clave cuando ese destino es la acción del bloque, como «Área clientes».

Cuándo no

  • Dentro de un párrafo o una lista: usa el enlace de texto.
  • Para cambiar de vista dentro de la misma página: usa pestañas.

Reglas

Regla Cómo se comprueba
Un solo botón relleno por grupo de acciones. El secundario es outline; ghost para acciones terciarias. En cada grupo hay como mucho un .button sin modificador de variante.
Sobre fondo night, el botón es button-light. Ningún .button relleno dentro de un bloque con fondo --night.
La etiqueta es un verbo y su objeto, corta y aprobada. Los textos salen del diccionario i18n; no se reescriben sin petición de Andrés.
El icono va después del texto, a 16 px y con trazo de 1,6. El svg es el último hijo y lleva aria-hidden="true".
Altura mínima de 44 px; 36 px en la variante pequeña. min-height de .button y .button-small.

Antipatrones

  • Doble principal: dos botones rellenos uno al lado del otro.
  • Acento como relleno: --accent es para el foco y la selección, no para botones.
  • Sinónimos de clase: no existen .btn, .button-primary ni .button-secondary. Usa solo las clases de la API.
  • Botón como enlace de párrafo: un botón en mitad de un texto rompe la lectura.

Accesibilidad

  • <a> cuando navega y <button type="button"> o type="submit" cuando actúa.
  • El foco visible es global: contorno de 2 px en --accent, separado 3 px en la landing y 2 px en el portal.
  • Los enlaces externos (Calendly) llevan target="_blank" y rel="noopener noreferrer".
  • En el portal, disabled baja la opacidad al 50 % y desactiva el puntero; SubmitButton añade aria-busy mientras envía.

Una sola fuente

Desde el 11 de octubre de 2026 la landing y el portal comparten public/site/button.css (imandresochoa/designloop#11). Cualquier cambio del botón se hace en ese archivo y llega a las dos superficies.

Tokens que usa

--ink--ink-hover--ink-2--paper--paper-2--card--line--line-strong--danger--accent

Enlace con producción

SuperficieFuenteEstadoHuellaRevisada en
Landingpublic/site/button.css
.button .button-outline .button-ghost .button-subtle .button-danger .button-light .button-small .button-block
Sincronizado2ba69fbd2d963caae89e520
Portal de clientessrc/components/ui/button.tsxSincronizado9c0b89d35ff98960e89e520

Producción en el commit 455e861 (2026-10-13). Sync del 2026-10-13.

Relacionados

componentes/boton · Actualizado el 2026-10-11