Botón con borde de luz
Botón oscuro con un borde degradado que gira y un resplandor.
Código completo
Es exactamente el archivo que se descarga. Cópialo a tu proyecto y úsalo.
/**
* Botón oscuro con un borde de luz que gira y un resplandor suave.
* Usa `@property` para animar el ángulo; en navegadores sin soporte el borde queda fijo.
*
* <div style={{ background: "#07070c", padding: 48 }}>
* <GlowBorderButton>Probar ahora</GlowBorderButton>
* </div>
*/
import type { ButtonHTMLAttributes, CSSProperties } from "react";
export type GlowBorderButtonProps = ButtonHTMLAttributes<HTMLButtonElement> & {
/** Tres colores del borde. */
colors?: [string, string, string];
};
const CSS = `
@property --gcw-angle { syntax: "<angle>"; initial-value: 0deg; inherits: false; }
.gcw-btn { position: relative; isolation: isolate; display: inline-flex; align-items: center; justify-content: center; gap: 10px; min-height: 52px; padding: 0 30px;
border: 2px solid transparent; border-radius: 14px; color: #f3f2ff; font-family: inherit; font-size: 15px; font-weight: 600; line-height: 1; letter-spacing: .01em; cursor: pointer;
background: linear-gradient(#0e0e16, #0e0e16) padding-box, conic-gradient(from var(--gcw-angle), var(--gcw-a), var(--gcw-b), var(--gcw-c), var(--gcw-a)) border-box;
animation: gcw-spin 4.5s linear infinite; transition: transform .25s cubic-bezier(.16, 1, .3, 1); }
.gcw-btn::before { content: ""; position: absolute; inset: -2px; z-index: -1; border-radius: inherit; filter: blur(18px); opacity: .42; transition: opacity .3s;
background: conic-gradient(from var(--gcw-angle), var(--gcw-a), var(--gcw-b), var(--gcw-c), var(--gcw-a)); }
.gcw-btn:hover { transform: translateY(-1px); animation-duration: 2.2s; }
.gcw-btn:hover::before { opacity: .85; }
.gcw-btn:active { transform: scale(.985); }
.gcw-btn:focus-visible { outline: 2px solid #fff; outline-offset: 5px; }
.gcw-btn:disabled { opacity: .5; cursor: not-allowed; animation-play-state: paused; }
.gcw-btn svg { width: 18px; height: 18px; }
@keyframes gcw-spin { to { --gcw-angle: 360deg; } }
@media (prefers-reduced-motion: reduce) { .gcw-btn { animation: none; transition: none; } }
`;
export function GlowBorderButton({ colors = ["#7c5cff", "#22d3ee", "#ff5ca8"], className, style, children, ...props }: GlowBorderButtonProps) {
const vars = { "--gcw-a": colors[0], "--gcw-b": colors[1], "--gcw-c": colors[2], ...style } as CSSProperties;
return (
<>
<style>{CSS}</style>
<button type="button" {...props} className={["gcw-btn", className].filter(Boolean).join(" ")} style={vars}>
{children}
</button>
</>
);
}
Úsalo en tu proyecto
Instálalo con la CLI de shadcn.
npx shadcn@latest add https://www.gassierconsulting.com/r/boton-borde-luzEjemplo de uso de Botón con borde de luz
Después de copiar glow-border-button.tsx a tu proyecto, impórtalo y colócalo donde lo necesites.
import { GlowBorderButton } from "./glow-border-button";
export default function Ejemplo() {
return <GlowBorderButton />;
}Accesibilidad y rendimiento
El archivo tiene 47 líneas (2 KB) y define 1 animación con @keyframes. Esto es lo que hace Botón con borde de luz 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).
- Usa @property de CSS para animar valores que normalmente no se interpolan.
Acerca del producto
Un botón oscuro cuyo borde es un degradado cónico que gira, con un resplandor desenfocado detrás. El ángulo se anima con @property, así que el movimiento corre en la GPU sin JavaScript.
Incluye
Un solo archivo React + TypeScript, con los estilos dentro. No usa Tailwind ni bibliotecas externas.
- Tres colores configurables para el borde
- Gira más rápido al pasar el puntero
- Sin JavaScript: solo CSS con @property
- Sin soporte de @property el borde queda fijo
Cómo usarlo
Pensado para fondos oscuros. Pasa los tres colores con la propiedad colors.