Skip to content
WANCRAFT

A.63Buttons & Controls

Border Beam Button

A button whose hairline border carries a travelling two-colour beam that brightens on hover and focus.

NewReactCSSTailwindintermediate

Overview

Border Beam Button runs a short beam of light around its 1px border. The beam is a small gradient square moved along `offset-path: rect()` with the Web Animations API, so it travels at constant speed and turns every rounded corner, and a CSS mask clips it to the border ring. Hovering, keyboard focus or a touch press brightens the beam, speeds it up and adds a soft halo outside the edge. The beam can run all the time or only while engaged, it pauses when the button is offscreen or the tab is hidden, and with reduced motion it becomes a static gradient border. Pass `href` to render a link.

01Installation

Method 01 · Registry

CLI verified

Uses the shadcn CLI in a project initialised with shadcn init. Installs the file to components/ui/border-beam-button.tsx and adds its dependencies.

npx shadcn@latest add https://wancraft.my/r/border-beam-button.json

Method 02 · Copy and paste

  1. 1. No extra dependencies — React and Tailwind CSS only.
  2. 2. Copy the source from the Code tab into components/ui/border-beam-button.tsx.
  3. 3. Import it and adjust props.
Dependencies
None
Peer
react ≥ 18, tailwindcss ≥ 4
Added
13 Oct 2026
Updated
—

02Usage

The default configuration. Change properties above to generate a tailored example in the Usage tab.

example.tsx
import { BorderBeamButton } from "@/components/ui/border-beam-button";

export function BorderBeamButtonExample() {
  return (
    <BorderBeamButton>
      Start building
    </BorderBeamButton>
  );
}

03Props

PropTypeDefaultDescription
childrenReactNode"Start building"Button label.
hrefstring—Render an <a> instead of a <button>. target / rel are forwarded; rel defaults to noreferrer for target="_blank".
variant"solid" | "ghost""solid"Filled dark surface or a quiet outlined surface.
size"sm" | "md" | "lg""md"Height, padding and type size.
shape"pill" | "rounded" | "square""pill"Corner style; the beam path uses the same radius.
durationnumber3000Time for one lap around the border, in ms.
lengthnumber80Length of the beam in px.
colorFromstring"#FF7448"Colour at the head of the beam; also the focus ring colour.
colorTostring"#B6F3D1"Colour the beam fades through towards its tail.
trigger"always" | "hover""always"Run continuously, or only while hovered, keyboard-focused or pressed.
type / disabledstring / boolean"button" / falseNative button attributes. A disabled link drops its href and sets aria-disabled.
...propsHTMLAttributes<HTMLElement>—Forwarded to the <button> / <a>; the ref points to it.

04Features

  • 01Constant-speed beam along offset-path: rect(), turning rounded corners smoothly
  • 02Two-colour gradient beam clipped to the 1px border with a CSS mask
  • 03Hover, keyboard focus or touch press brightens the beam, speeds it up and adds an outer halo
  • 04Always-on or engaged-only trigger; engaged-only stops animating once the beam has faded
  • 05Pauses offscreen (IntersectionObserver) and while the tab is hidden
  • 06Solid and ghost variants, three sizes and three shapes; renders a link with href
  • 07No dependencies beyond React
motion · continuousmotion · tweeninput · hoverinput · focusinput · clickinput · viewport

05Accessibility

  • Renders a native <button>, or an <a> when href is set, so keyboard and assistive technology behave natively.
  • All beam and halo layers are aria-hidden and pointer-events: none.
  • Keyboard focus (:focus-visible) engages the beam just like hover and shows a visible outline in the head colour.
  • With prefers-reduced-motion the beam is replaced by a static gradient border and the press scale is removed.
  • Browsers without offset-path rect() support get the same static gradient border.

06Limitations

  • The moving beam needs CSS offset-path basic shapes (rect() / inset()); browsers without them get the static gradient border.