/Click feedback
Click feedback • CSS
Subscribe Shine Button
A dark subscribe pill with a rotating highlight that traces its edge on hover.
Installation
Terminal
npx shadcn@latest add https://microkit.co/r/subscribe-shine-button.jsonCode
TypeScript component
1"use client";23import { useEffect, useRef } from "react";45export function SubscribeShineButton() {6const gradientRef = useRef<HTMLSpanElement>(null);7const spinAnimationRef = useRef<Animation | null>(null);8const settleAnimationRef = useRef<Animation | null>(null);910const startSpinning = () => {11const gradient = gradientRef.current;12if (!gradient || spinAnimationRef.current) return;13settleAnimationRef.current?.cancel();14settleAnimationRef.current = null;15spinAnimationRef.current = gradient.animate([{ transform: "rotate(0deg)" }, { transform: "rotate(360deg)" }], { duration: 3000, easing: "linear", iterations: Infinity });16};1718const settleAtStart = () => {19const gradient = gradientRef.current;20if (!gradient) return;21const spin = spinAnimationRef.current;22if (!spin) return;23const currentTime = typeof spin.currentTime === "number" ? spin.currentTime : 0;24const angle = ((currentTime % 3000) / 3000) * 360;25spin.cancel();26spinAnimationRef.current = null;27settleAnimationRef.current?.cancel();28const settle = gradient.animate([{ transform: `rotate(${angle}deg)` }, { transform: "rotate(0deg)" }], { duration: Math.max((angle / 360) * 3000, 16), easing: "linear", fill: "forwards" });29settleAnimationRef.current = settle;30void settle.finished.then(() => { if (settleAnimationRef.current === settle) { settle.cancel(); settleAnimationRef.current = null; } }, () => {});31};3233useEffect(() => () => { spinAnimationRef.current?.cancel(); settleAnimationRef.current?.cancel(); }, []);3435return (36<button type="button" className="subscribe-shine" onMouseEnter={startSpinning} onMouseLeave={settleAtStart} onFocus={startSpinning} onBlur={settleAtStart}>37<span ref={gradientRef} className="subscribe-shine-gradient" aria-hidden="true" />38<span className="subscribe-shine-inner">Subscribe</span>39</button>40);41}
CSS
1.subscribe-shine {2position: relative;3display: flex;4align-items: center;5justify-content: center;6width: 200px;7height: 60px;8overflow: hidden;9border: 0;10border-radius: 999px;11background: transparent;12padding: 0;13cursor: pointer;14}15.subscribe-shine-gradient {16width: 230px;17height: 250px;18flex: none;19background: linear-gradient(121deg, #1b1b1b 38%, #f0f0f0 50%, #1b1b1b 61%);20}21.subscribe-shine-inner {22position: absolute;23inset: 1px;24display: flex;25align-items: center;26justify-content: center;27border-radius: 999px;28background: #0b0b11;29color: #f0f0f0;30font-size: 13px;31font-weight: 700;32line-height: 1;33text-transform: uppercase;34}35.subscribe-shine:focus-visible {36outline: 2px solid #f97316;37outline-offset: 3px;38}