Ir al contenido
Evaluar mi proyecto
Componentes · BotonesDisponible

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.

arrow-button.tsx53 líneas
Descargar
/**
 * 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.

terminal.sh1 líneas
npx shadcn@latest add https://www.gassierconsulting.com/r/boton-flecha

Ejemplo 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.

ejemplo.tsx5 líneas
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.

VariableValor 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-*.
Licencia
MIT
Dependencias
React >=18
Compatibilidad
React · Next.js · Sin Tailwind

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.