Skip to content
Kura UI

Border Beam

beta

Animated light beam that travels around its parent's border — a quiet “an agent is working in here” signal for composers, cards and panels.

@kura-ui/react/border-beamCopy page for agents.mdregistry.json

Card with a beam

minimal

Indexing workspace

The beam marks a container the agent is working in.

Composer with two beams

Glow, width, size, speed, a second opposite beam via offset, and toggling active.

full

Ask the agent to change something…

Agent is editing 3 files⌘↵

Running task row

ShimmerText status, a Stop Button and a beam that fades out when stopped.

composition

auth/session.ts

Refactoring token refresh…

Installation

npx shadcn@latest add https://kuro.abstergo.fyi/r/border-beam.json

Copies the source into components/kura/border-beam with its dependencies (kura-theme, utils). Tokens come from the kura-theme item.

When to use it

Use it for

  • A composer, card or panel whose content an agent is currently editing or generating.
  • A running tool call or background task row that should read as live without a spinner.
  • Highlighting the one container on screen that is waiting for or producing AI output.

Reach for something else when

  • Small inline 'thinking' feedback — use thinking-indicator or shimmer-text.
  • Filling a background with colour — use mesh-gradient or aurora.
  • Focus or selection states — use the focus ring (shadow-kura-focus), not a beam.
  • Several beams on one screen at once: it is a signal; more than one or two becomes noise.

Props

PropTypeDefaultDescription
activebooleantrueShow the beam. Toggling fades it in/out over 480ms and pauses the animation while hidden — keep it mounted.
durationnumber6Seconds per lap.
sizenumber0.25Beam length as a share of the lap, 0.05–0.9.
widthnumber1Ring thickness in px.
colorsreadonly string[]—CSS colours from tail to head. Default: transparent → jade at 45% → jade → accent-text. Tokens and color-mix() work.
glowbooleanfalseAdd a blurred copy of the beam for a soft glow (not clipped by the parent unless it has overflow-hidden).
reversebooleanfalseTravel counter-clockwise.
offsetnumber0Starting position as a share of the lap, 0–1. Use 0.5 on a second beam to run two beams opposite each other.

All native attributes of the root element, className and ref pass through.

Anatomy

  1. BorderBeamAbsolutely positioned overlay (`inset-0`, `rounded-[inherit]`, pointer-events none). `data-active` mirrors `active`.data-slot="border-beam"
  2. GlowBlurred wrapper around a thicker ring; only rendered with `glow`.data-slot="border-beam-glow"
  3. RingThe masked conic gradient ring that carries the animation.data-slot="border-beam-ring"

Accessibility

  • Purely decorative (aria-hidden). Pair it with real text — a role=status label such as “Editing 3 files…” — so the busy state is not conveyed by motion alone.
  • It never intercepts pointer events, so the container stays fully interactive.
  • Reduced motion: The beam stops travelling and becomes a static, softly tinted ring (head colour at 45%) so the container still reads as active.

Notes for agents

  • The parent must be `relative` (or otherwise positioned) and should carry the border radius; the beam uses `rounded-[inherit]`.
  • Render it as the last child so it paints above the content edge; it does not take space.
  • Pure CSS: no 'use client' needed. Styles are injected once via a React 19 hoisted <style>.
  • Keep it mounted and flip `active` instead of conditionally rendering, so it fades rather than pops.
  • On wide, short elements the beam speeds up along the short sides (it is an angle sweep); prefer size 0.2–0.35 there.