# Border Beam Card

> React card for shadcn/ui with an animated border-beam glow on the compound Card API, for featured plans and active AI tasks.

Source: https://www.cult-ui.com/docs/components/border-beam-card

## Example

```tsx title="border-beam-card-demo.tsx"
"use client"

import { useId, useState } from "react"

import {
  BorderBeamCard,
  BorderBeamCardContent,
  BorderBeamCardDescription,
  BorderBeamCardHeader,
  BorderBeamCardTitle,
} from "@/components/ui/border-beam-card"

export default function BorderBeamCardDemo() {
  const [strength, setStrength] = useState(1)
  const [active, setActive] = useState(true)
  const strengthId = useId()
  const activeId = useId()

  return (
    <main className="flex w-full flex-col items-center justify-center">
      <div className="flex w-full max-w-3xl flex-col gap-14">
        <header className="space-y-2 text-center">
          <h2 className="font-semibold text-foreground text-xl tracking-tight">
            Border beam card
          </h2>
          <p className="text-pretty text-muted-foreground text-sm">
            <span className="text-foreground/90">BorderBeamCard</span> wraps{" "}
            <code className="rounded bg-muted px-1.5 py-0.5 font-mono text-foreground text-xs">
              Card
            </code>{" "}
            with the same header / content slots. Effect layers use{" "}
            <span className="text-foreground/90">pointer-events: none</span>.
          </p>
        </header>

        <section className="space-y-3">
          <h3 className="font-semibold text-foreground text-lg tracking-tight">
            Composable card
          </h3>
          <p className="text-pretty text-muted-foreground text-sm">
            Same slots as <span className="text-foreground/90">Card</span> —
            header, title, description, content.
          </p>
          <BorderBeamCard>
            <BorderBeamCardHeader>
              <BorderBeamCardTitle>Border beam card</BorderBeamCardTitle>
              <BorderBeamCardDescription>
                Uses <span className="text-foreground/90">Card</span> layout
                tokens; <span className="text-foreground/90">beamSize</span>{" "}
                controls the glow preset,{" "}
                <span className="text-foreground/90">size</span> matches card
                density (<span className="text-foreground/90">sm</span> /
                default).
              </BorderBeamCardDescription>
            </BorderBeamCardHeader>
            <BorderBeamCardContent>
              <p className="text-foreground/90 text-xs/relaxed">
                Body content sits in{" "}
                <span className="font-mono text-[0.8rem]">CardContent</span>,
                with padding aligned to the root{" "}
                <span className="font-mono text-[0.8rem]">size</span>.
              </p>
            </BorderBeamCardContent>
          </BorderBeamCard>
        </section>

        <section className="space-y-3">
          <h3 className="font-semibold text-foreground text-lg tracking-tight">
            Color variants
          </h3>
          <div className="grid gap-4 sm:grid-cols-2">
            <BorderBeamCard colorVariant="colorful" theme="auto">
              <BorderBeamCardContent className="pt-0">
                <p className="font-medium text-foreground text-sm">colorful</p>
              </BorderBeamCardContent>
            </BorderBeamCard>
            <BorderBeamCard colorVariant="mono" staticColors theme="auto">
              <BorderBeamCardContent className="pt-0">
                <p className="font-medium text-foreground text-sm">mono</p>
              </BorderBeamCardContent>
            </BorderBeamCard>
            <BorderBeamCard colorVariant="ocean" theme="auto">
              <BorderBeamCardContent className="pt-0">
                <p className="font-medium text-foreground text-sm">ocean</p>
              </BorderBeamCardContent>
            </BorderBeamCard>
            <BorderBeamCard colorVariant="sunset" theme="auto">
              <BorderBeamCardContent className="pt-0">
                <p className="font-medium text-foreground text-sm">sunset</p>
              </BorderBeamCardContent>
            </BorderBeamCard>
          </div>
        </section>
      </div>
    </main>
  )
}
```

Border Beam Card is a React card component for shadcn/ui built on the border-beam package. Use it to highlight a featured pricing plan, an active AI task, or an announcement on dashboards and landing pages.

## Installation

### CLI

```bash
npx shadcn@latest add @cult-ui/border-beam-card
```

### Manual

**Install the required dependencies:**

```bash
npm install border-beam
```

**Add the shadcn `card` component if you do not already have it.**

**Copy and paste the following code into your project.**

```tsx title="border-beam-card.tsx"
"use client"

/**
 * Cult-pro wrapper: [`border-beam`](https://www.npmjs.com/package/border-beam) around the same
 * compound API as `@/components/ui/card` (`BorderBeamCard` + `BorderBeamCardHeader`, …).
 *
 * The package sets `overflow: hidden` on the beam root; we set `overflow: visible` so the bloom
 * (especially `beamSize="line"`) is not clipped.
 *
 * Defaults: same concentric-radius shell as `HaloSelectTrigger` — outer `rounded-2xl` + `p-px`,
 * inner `rounded-[calc(1rem-1px)]` so the beam curve matches the card (not a smaller radius than
 * `Card`’s `rounded-2xl`). Layered shadow on the card; `text-balance` / `text-pretty` on title and
 * description wrappers.
 */
import type { ComponentProps, CSSProperties } from "react"
import { forwardRef } from "react"
import {
  BorderBeam,
  type BorderBeamProps,
  type BorderBeamSize,
} from "border-beam"

import { cn } from "@/lib/utils"
import {
  Card,
  CardAction,
  CardContent,
  CardDescription,
  CardFooter,
  CardHeader,
  CardTitle,
} from "@/components/ui/card"

/**
 * Outer rim matches `Card`’s `rounded-2xl` (1rem); `p-px` reserves the 1px track for the beam (same
 * idea as `HaloSelectTrigger`’s `rounded-xl` + `p-px` + inner `rounded-[11px]`).
 */
const borderBeamCardShellClass = cn(
  "relative w-full rounded-2xl p-px",
  /* Inset highlight on the shell — same family as `HaloSelectTrigger` shadow stack */
  "before:pointer-events-none before:absolute before:inset-0 before:rounded-[inherit] before:shadow-[inset_0_1px_0_rgba(255,255,255,0.45)]",
  "dark:before:shadow-[inset_0_1px_0_rgba(255,255,255,0.06)]"
)

/** Inner radius = outer `rounded-2xl` − 1px padding (concentric corners). */
const borderBeamCardInnerCurveClass = "rounded-[calc(1rem-1px)]"

/** Layered, low-contrast depth — works on varied backgrounds (see make-interfaces-feel-better). */
const borderBeamCardSurfaceClass =
  "shadow-[0_1px_0_rgba(0,0,0,0.04),0_1px_2px_-0.5px_rgba(0,0,0,0.07)] dark:shadow-[0_1px_0_rgba(255,255,255,0.06),0_1px_2px_-0.5px_rgba(0,0,0,0.45)]"

export type BorderBeamCardProps = Omit<BorderBeamProps, "children" | "size"> & {
  children: React.ReactNode
  /** Card layout density — same as `Card` `size` (`default` | `sm`). */
  size?: "default" | "sm"
  /** Beam preset — passed to `BorderBeam` as `size` (`sm` | `md` | `line`). */
  beamSize?: BorderBeamSize
  /** Classes merged onto the inner `Card`. */
  cardClassName?: string
  /** @deprecated Use `cardClassName` */
  contentClassName?: string
}

export const BorderBeamCard = forwardRef<HTMLDivElement, BorderBeamCardProps>(
  function BorderBeamCard(
    {
      children,
      className,
      cardClassName,
      contentClassName,
      size: cardSize = "default",
      beamSize = "md",
      theme = "auto",
      borderRadius,
      style: beamStyle,
      ...beamProps
    },
    ref
  ) {
    const explicitBeamRadius = borderRadius

    const beamMergedStyle: CSSProperties | undefined =
      explicitBeamRadius != null || beamStyle != null
        ? {
            ...beamStyle,
            ...(explicitBeamRadius != null
              ? { borderRadius: explicitBeamRadius }
              : {}),
          }
        : undefined

    const cardRadiusStyle: CSSProperties | undefined =
      explicitBeamRadius != null
        ? { borderRadius: explicitBeamRadius }
        : undefined

    return (
      <div
        className={borderBeamCardShellClass}
        ref={ref}
        style={
          explicitBeamRadius != null
            ? { borderRadius: explicitBeamRadius + 1 }
            : undefined
        }
      >
        <BorderBeam
          borderRadius={explicitBeamRadius}
          className={cn(
            "overflow-visible! block w-full",
            explicitBeamRadius == null
              ? borderBeamCardInnerCurveClass
              : undefined,
            className
          )}
          size={beamSize}
          style={beamMergedStyle}
          theme={theme}
          {...beamProps}
        >
          <Card
            className={cn(
              borderBeamCardSurfaceClass,
              explicitBeamRadius == null && "rounded-[calc(1rem-1px)]!",
              cardSize === "sm" &&
                "gap-3 py-3 text-sm *:[data-slot=card-content]:px-3",
              cardClassName,
              contentClassName
            )}
            style={cardRadiusStyle}
          >
            {children}
          </Card>
        </BorderBeam>
      </div>
    )
  }
)

BorderBeamCard.displayName = "BorderBeamCard"

export function BorderBeamCardHeader(props: ComponentProps<typeof CardHeader>) {
  return <CardHeader {...props} />
}
BorderBeamCardHeader.displayName = "BorderBeamCardHeader"

export function BorderBeamCardTitle({
  className,
  ...props
}: ComponentProps<typeof CardTitle>) {
  return <CardTitle className={cn("text-balance", className)} {...props} />
}
BorderBeamCardTitle.displayName = "BorderBeamCardTitle"

export function BorderBeamCardDescription({
  className,
  ...props
}: ComponentProps<typeof CardDescription>) {
  return <CardDescription className={cn("text-pretty", className)} {...props} />
}
BorderBeamCardDescription.displayName = "BorderBeamCardDescription"

export function BorderBeamCardAction(props: ComponentProps<typeof CardAction>) {
  return <CardAction {...props} />
}
BorderBeamCardAction.displayName = "BorderBeamCardAction"

export function BorderBeamCardContent(
  props: ComponentProps<typeof CardContent>
) {
  return <CardContent {...props} />
}
BorderBeamCardContent.displayName = "BorderBeamCardContent"

export function BorderBeamCardFooter(props: ComponentProps<typeof CardFooter>) {
  return <CardFooter {...props} />
}
BorderBeamCardFooter.displayName = "BorderBeamCardFooter"
```

**Update the import paths to match your project setup.**
