Border Beam
A soft light comet that travels along an element's border, curving through every corner because it is a stroked dash on the outline path itself.
Installation
npx smoothui-cli add border-beamFeatures
- The comet is the border: every segment is a
stroke-dasharraydash on the same SVG outline<path>, so it is curved by construction and can never leave the shape — nothing is translated or rotated along the path - Only
stroke-dashoffsetanimates, on a path normalised withpathLength={1}, so the dash slides through a corner instead of pivoting across it - The tail is four dashes sharing one head: each successive layer is longer and fainter, so alpha accumulates towards the head and the exposed far end reads as the tip of the trail
- The halo is a single blurred dash stroked in a lighter tint of the beam colour, mixed towards white in
oklab. Blurring a dark stroke produces a shadow, not a glow, so no layer is ever allowed to be darker than the beam - On dark surfaces the halo composites with
mix-blend-mode: plus-lighter, so the blur adds light instead of laying haze over the card; on light surfaces it composites normally, where an additive glow would wash out to nothing - The ring is a plain hairline in
--color-border, decoupled fromcolorFrom/colorTo— those two only ever colour the beam, so they are free to be as bright as a glow needs radiusaccepts a pixel value or"squircle"for continuous, Apple-style corners with no constant-radius arc at all- Any number of
beams, which are phase offsets of the same normalised offset, so they stay evenly spaced at anyduration reverseruns the offset the other way and flips which end of the dash leads, so the comet still travels head-firstpauseOnHoverfreezes the animation frame loop, only on hover-capable, fine-pointer devices- An
IntersectionObserverskips every style write while the element is scrolled out of view activelets you drive the beam from loading or focus state- Auto-measures with a
ResizeObserver, so the path re-derives on layout change
Notes
radius="squircle" draws the ring and the travel path as a continuous curve, but it does not clip the wrapper — a rectangular background on the same element would show square corners behind a squircle ring. Either leave the wrapper transparent, or clip the surface yourself (the Squircle component does exactly that).
Accessibility
ARIA Attributes
| Attribute | Element | Purpose |
|---|---|---|
aria-hidden="true" | Border ring SVG | Hides the decorative gradient outline from assistive technologies |
aria-hidden="true" | Comet dashes | Hides the travelling lights from assistive technologies |
Screen Reader
- The whole SVG overlay is
aria-hiddenandpointer-events: none, so it never intercepts clicks nor reaches the accessibility tree. - The wrapper adds no role or semantics:
childrenkeep whatever roles, labels and focus order they already had. - When you use the beam as a loading affordance, expose that state separately (for example
aria-busyor a live region) — motion alone is not announced.
Reduced Motion
This component respects prefers-reduced-motion via useReducedMotion from Motion. When reduced motion is preferred, no comet dashes are rendered and no frame loop starts; the border falls back to the same gradient stroke at full opacity, so the element keeps its highlighted look without any travel.
Props
Created by
Powered by
© 2026 SmoothUI. Built by Eduardo Calvo.