Galaxy Button
A glowy CTA with orbiting stars, a conic spark sweep, and a 3D star ring built on transform-style: preserve-3d. Lights up on hover. Ported from jh3y.
hover or focus to light it up
Usage
import { GalaxyButton } from "~/components/buttons/galaxy-button";<GalaxyButton onClick={explore}>Explore</GalaxyButton>// custom iconimport { Rocket } from "lucide-react";<GalaxyButton icon={<Rocket />}>Launch</GalaxyButton>
How it works
This one's all jh3y. The clever bit, and the reason it feels like more than a glow, is the star ring. The button sets transform-style: preserve-3d and a perspective, then a flat circular element gets tipped back with a few rotateX/rotateY transforms so it reads as a disc receding into space. The stars are absolutely-positioned dots pushed out along that disc and spun with a linear orbit animation, so they trace an ellipse instead of a flat circle.
Everything else hangs off a single --active variable that flips from 0 to 1 on hover or focus. The glow, the scale, the star opacity, the conic spark sweep, all of it interpolates from that one number, so the whole thing brightens together. I scoped it to the button (the original toggled the page background via :has), kept a real <button> for focus, and parked the animations behind prefers-reduced-motion.
/* One --active variable drives everything: glow, scale, star opacity. */.galaxy-btn {--active: 0;transform-style: preserve-3d; /* the 3D ring lives in here */perspective: 100vmin;scale: calc(1 + var(--active) * 0.1);box-shadow: 0 0 calc(var(--active) * 6em) calc(var(--active) * 3em)hsl(var(--hue) 97% 61% / .5);}.galaxy-btn:is(:hover, :focus-visible) { --active: 1; }/* The ring is a flat circle tipped into 3D; stars orbit around it. */.galaxy__ring {transform: rotateX(-24deg) rotateY(-30deg) rotateX(90deg);transform-style: preserve-3d;}.star {transform: translate(-50%, -50%) rotate(10deg)translateY(calc(var(--distance) * 1px));animation: galaxy-orbit calc(var(--duration) * 1s) infinite linear;}
Props
| prop | type | default | description |
|---|---|---|---|
| children | ReactNode | "Explore" | Button label. |
| icon | ReactNode | <Sparkles /> | Leading icon. Pass null to omit. |
| …props | ButtonHTMLAttributes | — | Any native button prop (onClick, type, aria-*). |
Original by jh3y.