p441z/Komponen/BorderBeam
Efek · components/effects/border-beam.tsx

BorderBeam

A beam of light circling a card's border.

47 barisGitHub ↗
Pasang lewat shadcn CLI

Baru pertama pakai kit ini? Baca panduan pemasangannya

Recommended

Tentang

BorderBeam — a short beam of light that travels around a card's border. Put it inside any `relative` element with a border radius; it follows the radius. CSS only, uses the kit's `animate-border-beam` utility. Color defaults to the theme primary (`--color-primary`).

Use on the single highlighted card of a section (the recommended plan, the featured video). Reduced motion: the beam is hidden. The beam is clipped to the element, so it never adds scroll.

Cara pakai

<div className="relative rounded-2xl border">…<BorderBeam /></div>

Kode sumber

components/effects/border-beam.tsx · 47 baris
import * as React from "react";

import { cn } from "@/lib/utils";

/**
 * BorderBeam — a short beam of light that travels around a card's border. Put it inside any
 * `relative` element with a border radius; it follows the radius. CSS only, uses the kit's
 * `animate-border-beam` utility. Color defaults to the theme primary (`--color-primary`).
 *
 * Use on the single highlighted card of a section (the recommended plan, the featured video).
 * Reduced motion: the beam is hidden. The beam is clipped to the element, so it never adds scroll.
 *
 * USAGE
 *   <div className="relative rounded-2xl border">…<BorderBeam /></div>
 */

interface BorderBeamProps {
  className?: string;
  /** Beam length in px. */
  size?: number;
  /** Seconds per lap. */
  duration?: number;
  /** Seconds to offset the start. */
  delay?: number;
  colorFrom?: string;
  colorTo?: string;
}

export default function BorderBeam({ className, size = 220, duration = 9, delay = 0, colorFrom = "var(--color-primary)", colorTo = "transparent" }: BorderBeamProps) {
  // The beam is a pseudo-element travelling around the edge. The mask hides it visually, but its box
  // still pokes out past the corners and would widen the page (horizontal scroll on phones). The
  // outer layer has no border, so clipping it cuts exactly at the edge and keeps the beam visible.
  return (
    <div aria-hidden className="pointer-events-none absolute inset-0 overflow-hidden rounded-[inherit] motion-reduce:hidden">
      <div
        className={cn(
          "absolute inset-0 rounded-[inherit] [border:1.5px_solid_transparent]",
          "[mask-clip:padding-box,border-box] [mask-composite:intersect] [mask-image:linear-gradient(transparent,transparent),linear-gradient(#000,#000)]",
          "after:absolute after:aspect-square after:w-[calc(var(--size)*1px)] after:animate-border-beam after:[animation-delay:var(--delay)] after:[background:linear-gradient(to_left,var(--color-from),var(--color-to),transparent)] after:[offset-anchor:90%_50%] after:[offset-path:rect(0_auto_auto_0_round_calc(var(--size)*1px))]",
          className,
        )}
        style={{ "--size": size, "--duration": `${duration}s`, "--delay": `-${delay}s`, "--color-from": colorFrom, "--color-to": colorTo } as React.CSSProperties}
      />
    </div>
  );
}