Componentes · Ola 1 · Acciones
Button
Dispara una acción o, como enlace, lleva a otra página con el mismo aspecto. La acción principal es luz blanca, también dentro de los productos: el acento del producto no toca los botones.
import { Button } from '@archeblack/ui';
import { IconPlus } from '@archeblack/ui/icons';
Ejemplos
Variantes
primary para la acción principal, secondary (por defecto) para las demás, ghost para las de bajo peso, danger para las destructivas y link dentro de un texto.
<script lang="ts">
import { Button } from '@archeblack/ui';
</script>
<Button variant="primary">Crear proyecto</Button>
<Button>Invitar</Button>
<Button variant="ghost">Cancelar</Button>
<Button variant="danger">Eliminar</Button>
<Button variant="link">Ver documentación</Button> Tallas
sm en tablas y barras densas, md en la interfaz y lg en formularios de una sola acción. Una fila de primary, una de secondary y una de solo ícono, cada una en las tres tallas con el mismo contenido. El ícono mide 16 px en sm y md, y 20 px en lg.
<script lang="ts">
import { Button } from '@archeblack/ui';
import { IconPlus } from '@archeblack/ui/icons';
</script>
<!--
Una fila por variante (y una de solo ícono) con sus tres tallas y el mismo contenido: solo
cambia la talla. El ícono mide 16 px en sm y md, y 20 px en lg.
-->
<div style:display="grid" style:justify-items="center" style:gap="var(--arche-spacing-4)">
<div
style:display="flex"
style:flex-wrap="wrap"
style:align-items="center"
style:gap="var(--arche-spacing-3)"
>
<Button variant="primary" size="sm">Crear</Button>
<Button variant="primary">Crear</Button>
<Button variant="primary" size="lg">Crear</Button>
</div>
<div
style:display="flex"
style:flex-wrap="wrap"
style:align-items="center"
style:gap="var(--arche-spacing-3)"
>
<Button size="sm">Abrir</Button>
<Button>Abrir</Button>
<Button size="lg">Abrir</Button>
</div>
<div
style:display="flex"
style:flex-wrap="wrap"
style:align-items="center"
style:gap="var(--arche-spacing-3)"
>
<Button size="sm" icon={IconPlus} aria-label="Agregar" />
<Button icon={IconPlus} aria-label="Agregar" />
<Button size="lg" icon={IconPlus} aria-label="Agregar" />
</div>
</div> Con íconos
iconStart e iconEnd acompañan al texto. icon hace un botón de solo ícono, con aria-label obligatorio.
<script lang="ts">
import { Button } from '@archeblack/ui';
import { IconArrowRight, IconDots, IconEdit, IconPlus, IconX } from '@archeblack/ui/icons';
</script>
<Button variant="primary" iconStart={IconPlus}>Nuevo proyecto</Button>
<Button iconEnd={IconArrowRight}>Continuar</Button>
<!-- Solo ícono: aria-label es obligatorio. -->
<Button variant="ghost" icon={IconDots} aria-label="Más acciones" />
<Button icon={IconEdit} aria-label="Editar" />
<Button variant="ghost" size="sm" icon={IconX} aria-label="Cerrar" /> En curso
loading muestra el indicador en lugar del ícono, ignora los clics y conserva el foco. El texto no cambia, así el botón no salta de ancho. Pulsa «Guardar cambios» para verlo.
<script lang="ts">
import { Button } from '@archeblack/ui';
import { IconDeviceFloppy, IconRefresh } from '@archeblack/ui/icons';
let saving = $state(false);
function save() {
saving = true;
setTimeout(() => (saving = false), 2500);
}
</script>
<!--
El indicador reemplaza al ícono y el texto queda igual, así el botón no cambia de ancho.
aria-busy avisa que la acción está en curso y el botón conserva el foco.
-->
<Button variant="primary" iconStart={IconDeviceFloppy} loading={saving} onclick={save}>
Guardar cambios
</Button>
<Button loading>Exportando</Button>
<Button variant="ghost" icon={IconRefresh} aria-label="Actualizando" loading /> Deshabilitado
Todas las variantes se apagan igual, salvo link, que no tiene caja: fondo hover translúcido, sin borde y texto text-disabled. Como el fondo es luz translúcida, sobre cualquier capa (la página, una tarjeta o un diálogo en surface-overlay) el botón queda un paso más claro que ella y no parece un hueco.
<script lang="ts">
import { Button } from '@archeblack/ui';
</script>
<Button variant="primary" disabled>Publicar</Button>
<Button disabled>Duplicar</Button>
<Button variant="ghost" disabled>Descartar</Button>
<Button variant="danger" disabled>Eliminar</Button>
<Button variant="link" disabled>Ver registro</Button> Como enlace
Con href se dibuja un <a> con el mismo aspecto.
<script lang="ts">
import { Button } from '@archeblack/ui';
import { IconExternalLink } from '@archeblack/ui/icons';
</script>
<!-- Con href es un <a>: navega, se abre en otra pestaña y se lee como enlace. -->
<Button href="#props" variant="primary">Ver las props</Button>
<Button href="#accessibility" iconEnd={IconExternalLink}>Accesibilidad</Button>
<p>
El botón de solo ícono exige un nombre. <Button href="#avoid" variant="link">Qué evitar</Button>
</p> Grupo de acciones
El pie típico de un formulario: una sola acción primaria, al final.
<script lang="ts">
import { Button } from '@archeblack/ui';
import { IconSend } from '@archeblack/ui/icons';
</script>
<!-- La acción principal va al final y es la única primaria del grupo. -->
<div style:display="flex" style:flex-wrap="wrap" style:gap="var(--arche-spacing-2)">
<Button variant="ghost">Cancelar</Button>
<Button>Guardar borrador</Button>
<Button variant="primary" iconEnd={IconSend}>Publicar</Button>
</div> Props
| Prop | Descripción |
|---|---|
variant? 'primary' | 'secondary' | 'ghost' | 'danger' | 'link' Por defecto 'secondary' | primary es la acción principal (una por vista); secondary, las demás; ghost, las de bajo peso; danger, las destructivas; link, una acción con aspecto de enlace. |
size? 'sm' | 'md' | 'lg' Por defecto 'md' | Alto de 1,75 rem (sm, texto de 13 px), 2,25 rem (md) o 2,75 rem (lg). Crece con la fuente del usuario. Los íconos miden 16 px en sm y md, y 20 px en lg. |
children? Snippet | El texto del botón. Es obligatorio salvo en el botón de solo ícono. |
iconStart? IconGlyph | Ícono antes del texto, decorativo. Mientras carga, el indicador giratorio ocupa su lugar. |
iconEnd? IconGlyph | Ícono después del texto, decorativo. |
icon? IconGlyph | Botón de solo ícono: un cuadrado del alto de la talla. No admite texto, y los tipos exigen aria-label. |
aria-label? string | Nombre accesible. Obligatorio con icon; con texto no hace falta. |
loading? boolean Por defecto false | Acción en curso: indicador giratorio, aria-busy="true" y aria-disabled="true". Ignora clics y teclado sin sacar el foco, y conserva el aspecto de su variante. |
disabled? boolean Por defecto false | Como botón usa el atributo nativo disabled. Como enlace se queda sin href, con role="link" (o el role que pases) y aria-disabled="true". Se ve con fondo hover translúcido, sin borde ni brillo, y texto text-disabled. |
href? string | Con href se dibuja un <a> con el mismo aspecto. Admite target, rel, download y el resto de atributos de enlace. |
type? 'button' | 'submit' | 'reset' Por defecto 'button' | Solo en el <button>. Para enviar un formulario, type="submit". |
class? ClassValue | Clases del producto; se suman a arche-button. |
...rest HTMLButtonAttributes | HTMLAnchorAttributes | Cualquier otro atributo va al <button> o al <a>, incluidos los eventos como onclick. |
Accesibilidad
- Es un
<button>nativo contype="button"por defecto: no envía un formulario por accidente, y Enter y espacio lo activan. - Con
hrefes un<a>: se lee como enlace y navega. Usahrefpara ir a otro lugar y el botón para hacer algo. - El botón de solo ícono exige
aria-label(TypeScript lo rechaza sin él). El ícono es decorativo: el nombre va en el botón. - Mientras carga,
aria-disableden vez dedisabled: el botón no pierde el foco y el lector de pantalla lo sigue encontrando.aria-busyindica que la acción está en curso; anuncia el resultado con un mensaje de estado. Si cambias el texto («Guardando…»), que el ancho del botón no salte. - El indicador giratorio se detiene con movimiento reducido; el texto y
aria-busysiguen diciendo que la acción está en curso. - El foco es el anillo de Arche, y su halo se mantiene con el puntero encima: el brillo del hover se suma, no lo reemplaza. En colores forzados, cada botón con caja muestra su borde con el color del sistema y el inactivo pasa a
GrayText. - El texto de todas las variantes supera 4,5:1. El texto deshabilitado está exento, por eso un botón deshabilitado necesita un motivo visible cerca.
Qué evitar
- Varios botones
primaryen la misma vista. Uno solo para la acción principal; las demás,secondaryoghost. - Un botón que navega (
onclickcongoto). Pasahref: se dibuja un<a>y funcionan abrir en otra pestaña y copiar el enlace. -
disabledmientras se guarda.loading: el foco se queda en el botón y el usuario sabe que la acción está en curso. - Un botón deshabilitado sin explicación. Di al lado qué falta para habilitarlo, o déjalo habilitado y valida al enviar.
- Un ícono suelto dentro de
childreno un SVG propio.iconStart,iconEndoicon, con un ícono de@archeblack/.ui/ icons -
dangerpara acciones que no destruyen nada. Resérvalo para eliminar o revocar, con un texto que diga qué se pierde.