Botón minimalista con flecha
Texto con subrayado que se dibuja y una flecha en un círculo que se llena.
Código completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
/**
* Botón minimalista: texto con subrayado que se dibuja y una flecha en un círculo que se llena.
* Hereda el color del texto; cambia `--gca-ink` y `--gca-paper` para invertirlo sobre fondos oscuros.
*
* <ArrowButton>Ver el proyecto</ArrowButton>
* <ArrowButton href="/contacto">Escríbenos</ArrowButton>
*/
import type { AnchorHTMLAttributes, ButtonHTMLAttributes, ReactNode } from "react";
type CommonProps = { children: ReactNode; className?: string };
export type ArrowButtonProps =
| (CommonProps & ButtonHTMLAttributes<HTMLButtonElement> & { href?: undefined })
| (CommonProps & AnchorHTMLAttributes<HTMLAnchorElement> & { href: string });
const CSS = `
.gca-btn { display: inline-flex; align-items: center; gap: 18px; padding: 0; border: 0; background: none; color: var(--gca-ink, #111111);
font-family: inherit; font-size: 20px; font-weight: 500; line-height: 1.2; letter-spacing: -.01em; text-decoration: none; cursor: pointer; }
.gca-label { padding-bottom: 3px; background: linear-gradient(currentColor, currentColor) 0 100% / 100% 1px no-repeat; transition: background-size .5s cubic-bezier(.16, 1, .3, 1); }
.gca-btn:hover .gca-label, .gca-btn:focus-visible .gca-label { background-position: 100% 100%; background-size: 0 1px; animation: gca-draw .5s cubic-bezier(.16, 1, .3, 1) .15s forwards; }
.gca-icon { display: inline-grid; width: 48px; height: 48px; flex: none; place-items: center; border: 1px solid currentColor; border-radius: 50%; overflow: hidden;
transition: background-color .35s cubic-bezier(.16, 1, .3, 1), color .35s; }
.gca-icon svg { width: 18px; height: 18px; transform: rotate(-45deg); transition: transform .45s cubic-bezier(.16, 1, .3, 1); }
.gca-btn:hover .gca-icon, .gca-btn:focus-visible .gca-icon { background: var(--gca-ink, #111111); color: var(--gca-paper, #ffffff); }
.gca-btn:hover .gca-icon svg, .gca-btn:focus-visible .gca-icon svg { transform: rotate(0deg); }
.gca-btn:focus-visible { outline: 2px solid currentColor; outline-offset: 6px; border-radius: 999px; }
@keyframes gca-draw { from { background-size: 0 1px; background-position: 0 100%; } to { background-size: 100% 1px; background-position: 0 100%; } }
@media (prefers-reduced-motion: reduce) { .gca-label, .gca-icon, .gca-icon svg { transition: none; } .gca-btn:hover .gca-label { animation: none; background-position: 0 100%; background-size: 100% 1px; } }
`;
export function ArrowButton({ children, className, ...props }: ArrowButtonProps) {
const classes = ["gca-btn", className].filter(Boolean).join(" ");
const content = (
<>
<span className="gca-label">{children}</span>
<span className="gca-icon" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 6l6 6-6 6" /></svg>
</span>
</>
);
return (
<>
<style>{CSS}</style>
{"href" in props && props.href !== undefined ? (
<a {...(props as AnchorHTMLAttributes<HTMLAnchorElement>)} className={classes}>{content}</a>
) : (
<button type="button" {...(props as ButtonHTMLAttributes<HTMLButtonElement>)} className={classes}>{content}</button>
)}
</>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/boton-flechaEjemplo de uso de Botón minimalista con flecha
Después de copiar arrow-button.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { ArrowButton } from "./arrow-button";
export default function Ejemplo() {
return <ArrowButton />;
}Personaliza Botón minimalista con flecha con variables CSS
Define estas variables en el contenedor o en tu hoja de estilos para cambiar los colores sin tocar el componente. Si no las defines, se usa el valor por defecto.
| Variable | Valor por defecto |
|---|---|
--gca-ink | #111111 |
--gca-paper | #ffffff |
Accesibilidad y rendimiento
El archivo tiene 53 líneas (3 KB) y define 1 animación con @keyframes. Esto es lo que hace Botón minimalista con flecha por quien lo usa:
- Detecta prefers-reduced-motion y baja o quita el movimiento cuando la persona lo pide.
- Muestra un anillo de foco visible al navegar con teclado (:focus-visible).
- Expone su estado a tecnologías de apoyo con atributos aria-*.
Acerca del producto
Un botón sin caja: el subrayado se borra y se vuelve a dibujar al pasar el puntero, y la flecha dentro del círculo gira de diagonal a horizontal mientras el círculo se llena. Puede ser botón o enlace.
Incluye
Un solo archivo React + TypeScript, con los estilos dentro. No usa Tailwind ni bibliotecas externas.
- Botón o enlace (si pasas href)
- Hereda el color del texto
- Invertible sobre fondos oscuros con dos variables
- Sin JavaScript
Cómo usarlo
Pasa href para renderizarlo como enlace. Para fondos oscuros cambia --gca-ink y --gca-paper.