Skip to content

BorderBeam — spec

Synthesized from Ant Design BorderBeam, with host-surface guidance cross-checked against MUI Paper / Card and shadcn-ui Card. BorderBeam is a decorative emphasis layer, not a semantic status, focus, or validation border.

When to use

  • A single container needs controlled visual emphasis: featured AI panel, recommended card, login panel, onboarding highlight, or primary dashboard module.
  • The surface already has a clear semantic role and the beam only increases visual salience.
  • The child host is a real DOM element or a component that forwards its ref to a DOM element.

When NOT to use: - Validation, focus, selected, error, success, warning, or destructive state. Use semantic border/status tokens instead. - Dense dashboards with many cards. More than one or two beams on a viewport reads as noise. - Motion-sensitive or high-focus workflows where a moving border competes with reading or data entry. - Containers whose root cannot provide a stable DOM ref, position context, or border radius.

Anatomy

BorderBeam
├── Child host element
│   ├── Existing surface content
│   └── Beam effect layer (portal, aria-hidden)
└── Gradient / inset / radius CSS variables
Part Purpose Required Default if omitted
Child host The decorated element that receives the portal layer. yes Plain text or non-ref children render without the beam.
Beam effect layer Absolutely-positioned visual border effect inside the host. internal Hidden until browser support and host resolution pass.
Gradient Beam color or gradient stops. no Uses primary theme gradient.
Inset offset Moves the effect outward from the host edge. no Inferred from host border width.
Radius bridge Mirrors the host border radius for alignment. internal Reads computed radius during initialization.

API

<BorderBeam
  color={[
    { color: "var(--color-primary-default)", percent: 0 },
    { color: "var(--color-accent-default)", percent: 100 },
  ]}
  outset={0}
>
  <section className="featured-panel">
    <h2>AI review ready</h2>
    <p>3 design-system risks need review.</p>
  </section>
</BorderBeam>
Prop Type Default Description
children ReactNode Decorated content. Must resolve to a single host DOM element for the beam to render.
color string \| { color: string; percent: number }[] theme primary gradient Solid beam color or ordered gradient stops. percent is authored as 0 to 100; implementation maps it into the visible beam segment.
outset number \| string host border width Offset from the container edge. Use 0 when the host clips overflow or already owns a visible border.
className string Class applied to the beam effect layer, not the child host.
style CSSProperties Inline styles for the beam effect layer, including custom CSS variables.
prefixCls string design-system prefix Advanced namespace override. Prefer provider-level configuration.

API choices made

  • Keep the API intentionally small. BorderBeam should decorate a surface; it should not become a full Card variant system.
  • Keep color as either one semantic token string or explicit gradient stops. Do not add intent="success" / intent="error" because that would imply semantic status.
  • Treat outset as an alignment escape hatch. Most product code should rely on host border inference or set outset={0} for clipped cards.
  • Do not expose speed, direction, or looping props by default. Constant decorative motion should be rare, reduced-motion-safe, and globally governed by motion tokens.

States

State Trigger Visual / behavior
Default Host resolves and browser supports required CSS masking / offset-path Beam layer renders around the host, pointer-events: none, aria-hidden="true".
Unsupported CSS Browser lacks mask or offset-path support Beam stays hidden; child content remains unchanged.
Missing host Plain text, fragment, non-ref component, or SVG child Beam is skipped; child content still renders.
Hover Pointer over host No built-in change. Host component may own its normal hover state.
Focus-visible Keyboard focus on host or child control Beam must not replace the 2px focus ring. Focus ring keeps at least 3:1 contrast per keyboard-and-focus.md.
Active Pointer / keyboard activation on host content No built-in change. Interactive child components own active feedback.
Disabled Disabled content inside host Beam should usually be removed; a disabled surface should not attract attention.
Loading Async content inside host Keep only if it helps identify the active module; never use the beam as loading progress.
Error Error content inside host Remove or recolor through semantic error UI; do not use decorative beam as the only error indicator.
Reduced motion prefers-reduced-motion: reduce Hide the moving effect or freeze it into a non-moving border highlight.

Variants

Emphasis level

Level Use Visual rule
subtle Secondary highlight, recommendation card Low-opacity token gradient, no extra shadow.
default One primary featured surface Primary to accent gradient, one beam per viewport region.
campaign Marketing or onboarding hero module Stronger gradient is allowed, but still respects reduced motion and contrast.

Host surface

Host Rule
Card / Paper Put radius and position: relative on the actual root element.
Button / link card Keep the focus ring outside or above the beam; do not rely on the beam for focus.
Modal / dialog Avoid except for onboarding. Motion around modal edges can distract from the task.
Data table / form Avoid. Continuous motion is disruptive for scanning and input.

Tokens consumed

--color-primary-default
--color-primary-hover
--color-accent-default
--color-focus-ring
--color-border-emphasis
--radius-md
--radius-lg
--border-width-sm
--motion-duration-slow
--motion-easing-linear

If your design system does not have --color-border-emphasis, map the default beam to primary/accent tokens and keep semantic status tokens separate.

Accessibility

  • Semantics: the beam layer is decorative and must render with aria-hidden="true".
  • Keyboard: BorderBeam itself is not focusable and adds no keyboard behavior. Any interactive child keeps its native keyboard contract.
  • Focus: never use the moving beam as focus indication. Interactive descendants need a visible 2px focus ring with at least 3:1 contrast against adjacent colors.
  • Reduced motion: hide the moving beam for prefers-reduced-motion: reduce, or replace it with a static border. This follows motion/principles.md.
  • Pointer behavior: the effect layer uses pointer-events: none so it cannot block clicks, text selection, or hover states on the host.
  • Contrast: because the beam is decorative, it does not carry required information. If a design uses border color to communicate state, provide text/icon redundancy and at least 3:1 non-text contrast.
  • Screen readers: no announcement is needed for beam appearance. Announce only the actual state or content change inside the host.
  • Touch target: if the decorated host is interactive, keep the host target at least 44x44 on mobile and at least 24x24 for WCAG 2.2 AA web minimum.
type FeaturedModuleProps = {
  title: string;
  description: string;
  action: React.ReactNode;
};

export function FeaturedModule({ title, description, action }: FeaturedModuleProps) {
  return (
    <BorderBeam
      color={[
        { color: "var(--color-primary-default)", percent: 0 },
        { color: "var(--color-accent-default)", percent: 100 },
      ]}
      outset={0}
    >
      <section className="featured-module" aria-labelledby="featured-module-title">
        <div>
          <h2 id="featured-module-title">{title}</h2>
          <p>{description}</p>
        </div>
        {action}
      </section>
    </BorderBeam>
  );
}
.featured-module {
  position: relative;
  overflow: hidden;
  border: 1px solid var(--color-border-subtle);
  border-radius: var(--radius-lg);
  background: var(--color-bg-elevated);
}

.featured-module:focus-within {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .ant-border-beam::before {
    display: none;
  }
}

Edge cases

  • Non-ref child: function components must forward a ref to the real DOM root, or the beam cannot mount.
  • Plain text / fragment: render content without decoration. Do not wrap automatically because it can change layout and semantics.
  • Static positioning: the beam may inject, but deterministic placement needs position: relative on the host.
  • Overflow clipping: use outset={0} when the host has overflow: hidden; negative offsets can be clipped unpredictably.
  • Changing radius: radius is read during initialization. If responsive or state-driven radius changes matter, set the final radius on the host before mount or remount the decorated host.
  • Custom gradient stops: clamp authored percent to 0..100; preserve a transparent tail so the beam has a visible fade.
  • RTL: the decorative direction does not need semantic mirroring. If brand motion direction matters, define it in the motion system rather than per component.
  • Print: hide the beam in print; decorative motion and gradients do not belong on invoices, reports, or contracts.
  • Korean B2B sensitive-data surfaces: use sparingly. One highlighted review panel is acceptable; continuous decoration around HR or payroll forms can reduce perceived seriousness.

Don't

  • Don't use BorderBeam as a substitute for focus-visible, selected, validation, or status borders.
  • Don't decorate every card in a grid.
  • Don't pass literal brand hex values in product code; use semantic color tokens.
  • Don't wrap a component that cannot forward a DOM ref and then treat the missing beam as a rendering bug.
  • Don't animate around long-form reading, tables, or data-entry forms unless the user explicitly requested a guided highlight.

References