# Black Box CTA

> A closing call to action on a night band with the product as a glass box: a wireframe with a lit core turning inside. Its faces open in turn to walk through the trial, each with a hairline label, and any of them opens under the pointer.

A CTA Section block from KeyframeUI: a whole landing-page section built around the Black Box component, free to install as source with the shadcn CLI. Built with React, Tailwind CSS and Motion.

- Live preview: https://keyframeui.com/blocks/cta-sections/black-box-cta
- Category: CTA Sections
- Built with: [Black Box](https://keyframeui.com/components/black-box.md)
- npm dependencies: motion, clsx, tailwind-merge

## Installation

Register the @keyframeui registry in `components.json` once per project:

```json
{
  "registries": {
    "@keyframeui": "https://keyframeui.com/r/{name}.json"
  }
}
```

Then add the block. It lands in `components/black-box-cta.tsx`, and the CLI also adds the components it's built with (`components/ui/black-box.tsx`) and `lib/utils.ts`, and installs the npm dependencies:

```bash
npx shadcn@latest add @keyframeui/black-box-cta
```

Or install by URL, without registering the namespace:

```bash
npx shadcn@latest add https://keyframeui.com/r/black-box-cta.json
```

## Usage

Put it where the section goes. The copy, links and data sit in constants at the top of the file; edit them there.

```tsx
import { BlackBoxCta } from "@/components/black-box-cta";

export default function Page() {
  return <BlackBoxCta />;
}
```

## Source

```tsx title="components/black-box-cta.tsx"
"use client";

import * as React from "react";

import { BlackBox, type BlackBoxFace } from "@/components/ui/black-box";

/* ── Content ─────────────────────────────────────────────────
 * Everything you'd change to make the section yours: the
 * colors, the copy, the buttons and the three faces, which walk
 * through the trial. The band is night in both color schemes,
 * so the box is always glass: a wireframe with a lit core.
 * ─────────────────────────────────────────────────────────── */

const NIGHT = { paper: "#07080c", ink: "#f4f5f7", accent: "#7088ff" };

const HEADLINE = ["Open the box", "on your own books."];
const SUBLINE = "Connect a bank feed and watch Basalt close last month. It takes about ten minutes, and the books are yours to keep.";
const PRIMARY_CTA = { label: "Start free", href: "#start" };
const SECONDARY_CTA = { label: "Book a walkthrough", href: "#demo" };
const FINE_PRINT = "Read-only access · SOC 2 Type II · Cancel any time";

const FACES: BlackBoxFace[] = [
  {
    id: "connect",
    label: "Connect",
    detail: "Read-only bank and card feeds, in about ten minutes.",
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.6} strokeLinecap="round" strokeLinejoin="round">
        <path d="M10 14a4 4 0 0 0 5.66 0l3-3a4 4 0 0 0-5.66-5.66l-1 1M14 10a4 4 0 0 0-5.66 0l-3 3a4 4 0 0 0 5.66 5.66l1-1" />
      </svg>
    ),
  },
  {
    id: "close",
    label: "Close",
    detail: "Last month, reconciled while you watch.",
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.6} strokeLinecap="round" strokeLinejoin="round">
        <path d="M5 12.5l4.5 4.5L19 7.5" />
      </svg>
    ),
  },
  {
    id: "keep",
    label: "Keep",
    detail: "The closed books are yours, even if you leave.",
    icon: (
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth={1.6} strokeLinecap="round" strokeLinejoin="round">
        <path d="M5 8h14v11H5zM3.5 5h17v3h-17zM10 12h4" />
      </svg>
    ),
  },
];

/* ── Section ─────────────────────────────────────────────── */

export function BlackBoxCta() {
  return (
    <section
      style={{ "--paper": NIGHT.paper, "--ink": NIGHT.ink, "--accent": NIGHT.accent } as React.CSSProperties}
      className="relative isolate overflow-hidden bg-(--paper) text-(--ink) dark:border-y dark:border-white/[0.08]"
    >
      {/* A low wash of the box's light, behind everything. */}
      <div
        aria-hidden
        className="pointer-events-none absolute inset-0 -z-10 bg-[radial-gradient(60%_70%_at_75%_50%,color-mix(in_srgb,var(--accent)_16%,transparent),transparent)]"
      />
      <div className="mx-auto grid max-w-6xl items-center gap-x-12 gap-y-4 px-6 py-20 sm:py-24 lg:grid-cols-[minmax(0,1fr)_minmax(0,1.15fr)]">
        <div>
          <h2 className="text-4xl leading-[1.05] font-medium tracking-[-0.04em] sm:text-5xl">
            <span className="block">{HEADLINE[0]}</span>{" "}
            <span className="block text-white/45">{HEADLINE[1]}</span>
          </h2>
          <p className="mt-5 max-w-md text-base leading-relaxed text-pretty text-white/65 sm:text-[17px]">{SUBLINE}</p>
          <div className="mt-8 flex flex-wrap items-center gap-3 text-sm font-medium">
            <a
              href={PRIMARY_CTA.href}
              className="rounded-full bg-(--ink) px-5 py-2.5 text-(--paper) transition-opacity duration-150 hover:opacity-85 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--accent)"
            >
              {PRIMARY_CTA.label}
            </a>
            <a
              href={SECONDARY_CTA.href}
              className="rounded-full px-5 py-2.5 ring-1 ring-white/20 transition-colors duration-150 hover:bg-white/[0.06] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--accent)"
            >
              {SECONDARY_CTA.label}
            </a>
          </div>
          <p className="mt-6 text-xs text-white/45">{FINE_PRINT}</p>
        </div>

        <BlackBox
          faces={FACES}
          material="glass"
          className="text-(--ink) [--black-box-light:var(--accent)]"
          aria-label="What happens when you start"
        />
      </div>
    </section>
  );
}
```
