---
title: "BorderBeam"
description: "A wrapper that draws a traveling or breathing glow along its border."
category: Effects
status: beta
since: 0.3.9
tags: [border, beam, glow, highlight]
syncStatus: reviewed
verified: true
---

## Usage

### Rotating Types
`size` is `sm`, `md`, or `line`; `line` travels along the bottom edge only.
:::TuffDemoWrapper{demo="BorderBeamShowcaseDemo" code-lang="vue"}
---
code: |
  <script setup lang="ts">
  import { computed } from 'vue'

  const colorMode = useColorMode()
  const beamTheme = computed(() => (colorMode.value === 'dark' ? 'dark' : 'light'))
  </script>

  <template>
    <TxBorderBeam :theme="beamTheme" :border-radius="16">
      <TxCard :radius="16" :padding="24">md</TxCard>
    </TxBorderBeam>
    <TxBorderBeam size="sm" :theme="beamTheme">
      <TxButton round variant="secondary">sm</TxButton>
    </TxBorderBeam>
    <TxBorderBeam size="line" :theme="beamTheme" :border-radius="12">
      <TxInput placeholder="line" />
    </TxBorderBeam>
  </template>
---
:::

### Pulse Types
`pulse-inner` breathes inside the border. `pulse-outside` blooms outward from behind the content, so the child must be opaque with its own 1px border.
:::TuffDemoWrapper{demo="BorderBeamPulseDemo" code-lang="vue"}
---
code: |
  <template>
    <TxBorderBeam size="pulse-inner" :active="active" :border-radius="16">
      <TxCard :radius="16" :padding="28">pulse-inner</TxCard>
    </TxBorderBeam>
    <TxBorderBeam size="pulse-outside" :active="active" :border-radius="16">
      <TxCard :radius="16" :padding="28">pulse-outside</TxCard>
    </TxBorderBeam>
    <TxSwitch v-model="active" />
  </template>
---
:::

### Color and Theme
`colorVariant` picks one of four palettes. `theme` tunes the beam for dark or light backgrounds; `auto` follows the system.

```vue
<template>
  <TxBorderBeam color-variant="ocean" theme="light">
    <div class="card">ocean · light</div>
  </TxBorderBeam>
  <TxBorderBeam color-variant="sunset" :strength="0.7">
    <div class="card">sunset · 70%</div>
  </TxBorderBeam>
</template>
```

### Tempo
`duration` is one loop or breath in seconds. `hueRange` bounds the hue drift, and `staticColors` freezes it.

```vue
<template>
  <TxBorderBeam :duration="4" :hue-range="60">
    <div class="card">slow · wide hue swing</div>
  </TxBorderBeam>
  <TxBorderBeam static-colors>
    <div class="card">frozen palette</div>
  </TxBorderBeam>
</template>
```

### Best Practices

- Give the slot content its own background and a corner radius that matches `borderRadius`.
- Leave room around `pulse-outside` for the halo to spill (`overflow: visible`).
- Use one beam per section; with several on screen, lower `strength` or slow `duration`.
- Use `theme="light"` or `"auto"` on light pages; the default dark tuning lacks contrast there.

## API Reference

### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `size` | `'sm' \| 'md' \| 'line' \| 'pulse-outside' \| 'pulse-inner'` | `'md'` | Type preset: rotating (`sm`, `md`, `line`) or pulse. |
| `colorVariant` | `'colorful' \| 'mono' \| 'ocean' \| 'sunset'` | `'colorful'` | Palette; `mono` also freezes the hue. |
| `theme` | `'dark' \| 'light' \| 'auto'` | `'dark'` | Tunes the beam for the background; `auto` follows the system. |
| `strength` | `number` | `1` | Beam-layer intensity (0–1); leaves the slot content untouched. |
| `duration` | `number` | `1.96` / `3.1` / `2.3` | Cycle length in seconds; defaults are for rotating, `line`, and pulse. |
| `active` | `boolean` | `true` | Plays the effect; toggling fades it in or out. |
| `borderRadius` | `number` | auto-detected | Beam corner radius in px. |
| `brightness` | `number` | per-type preset (`1.3`) | Glow brightness multiplier. |
| `saturation` | `number` | `1.2` (dark) | Glow saturation multiplier. |
| `hueRange` | `number` | `30` | Hue drift in degrees; capped at 13 for `line`. |
| `staticColors` | `boolean` | `false` | Turns off the hue animation. |

### Events

| Event | Payload | Description |
|------|------|------|
| `activate` | - | Fires when the fade-in ends. |
| `deactivate` | - | Fires when the fade-out ends. |

### Slots

| Slot | Props | Description |
|------|------|------|
| `default` | - | The wrapped content. |

### CSS Variables

| Variable | Source | Description |
|------|------|------|
| `--beam-strength` | `strength` | Beam-layer opacity, clamped to 0–1. |
| `--pulse-glow-sx` / `--pulse-glow-sy` | internal measurement | Per-axis halo scale of `pulse-outside`, from the element size. |
| `--pulse-glow-boost` | optional consumer hook | Pulse glow gain; defaults to `1`. |

## Overview

- Every effect layer is `pointer-events: none` and never blocks the slot; the slot content supplies its own focus styling.
- Without `borderRadius`, the first slot element's `border-top-left-radius` is used, falling back to the type preset.
- Offscreen (256px margin), the animation pauses without emitting `activate` / `deactivate`.
- Under reduced motion, the pulse types stop breathing.

## Technologies

- Each instance injects its own `<style>` scoped by `data-beam`; the pulse types run on a shared ~30fps rAF loop.
- `styles.ts` and `pulse-driver.ts` are ported from [Jakubantalik/Libraries · border-beam](https://github.com/Jakubantalik/Libraries/tree/main/packages/border-beam) (MIT © Jakub Antalik).
- Source: `packages/tuffex/packages/components/src/border-beam/`.

<TuffDocSourceLink />
