# Vortex CTA band

> Dark rounded call-to-action band over a brand-tinted particle vortex, with two actions and fine print.

A shadcn/ui block from the [@velora](https://velora.colorlib.com) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/velora/cta-vortex).

- Page, with a live preview: https://shadcn.exchange/r/velora/cta-vortex
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/velora/cta-vortex-light-58d9bc571c04669b.png
- Registry item: https://velora.colorlib.com/r/cta-vortex.json
- Categories: cta-sections
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://velora.colorlib.com/r/cta-vortex.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- npm packages: `lucide-react`
- Registry items: `utils`, `button`, `https://velora.colorlib.com/r/vortex.json`

## Files

### `src/components/blocks/cta-vortex.tsx`

```tsx
import { ArrowRightIcon, CheckIcon, SparklesIcon } from "lucide-react";

import { Button } from "@/components/ui/button";
import { Vortex } from "@/components/velora/vortex";

const EYEBROW = "Ready when you are";
const TITLE = "Ship your next release in an afternoon";
const COPY =
  "Bring your roadmap, docs and deploys into one calm workspace. Acme sets up in minutes and grows with your team.";
const PRIMARY = { label: "Start for free", href: "#" };
const SECONDARY = { label: "Talk to sales", href: "#" };
const PERKS = ["Free for teams up to 10", "No credit card required", "Cancel anytime"];

/**
 * Dark call-to-action band with a brand-tinted particle vortex swirling
 * behind the copy. The `dark` class scopes the dark theme tokens to the
 * band, so it stays dark on light pages and lifts off dark ones.
 */
export function CtaVortex() {
  return (
    <section className="px-6 py-24 sm:py-32 lg:px-8">
      <div className="dark relative isolate mx-auto max-w-6xl overflow-hidden rounded-3xl border bg-card px-6 py-20 text-center text-foreground shadow-2xl shadow-brand/10 sm:px-12 sm:py-28">
        <Vortex particles={900} speed={0.8} range={0.95} />
        {/* Calms the bright centre of the swirl so the copy stays readable. */}
        <div
          aria-hidden
          className="pointer-events-none absolute inset-0 bg-radial from-card/85 from-10% via-card/40 via-35% to-transparent to-65%"
        />
        {/* On narrow screens the copy spans the full width of the swirl. */}
        <div aria-hidden className="pointer-events-none absolute inset-0 bg-card/60 sm:hidden" />
        <div
          aria-hidden
          className="pointer-events-none absolute inset-x-0 top-0 h-px bg-gradient-to-r from-transparent via-brand-to/60 to-transparent"
        />

        <div className="relative mx-auto max-w-2xl">
          <p className="inline-flex items-center gap-2 rounded-full border bg-background/60 px-3 py-1 text-sm text-muted-foreground backdrop-blur">
            <SparklesIcon aria-hidden className="size-4 text-brand-to" />
            {EYEBROW}
          </p>
          <h2 className="mt-6 text-3xl font-semibold tracking-tight text-balance sm:text-5xl">
            {TITLE}
          </h2>
          <p className="mx-auto mt-5 max-w-xl text-base text-pretty text-muted-foreground sm:text-lg">
            {COPY}
          </p>

          <div className="mt-10 flex flex-col items-center justify-center gap-3 sm:flex-row">
            <Button
              asChild
              size="lg"
              className="h-11 w-full rounded-full bg-foreground px-6 text-background hover:bg-foreground/90 sm:w-auto"
            >
              <a href={PRIMARY.href}>
                {PRIMARY.label}
                <ArrowRightIcon aria-hidden />
              </a>
            </Button>
            <Button
              asChild
              size="lg"
              variant="outline"
              className="h-11 w-full rounded-full bg-background/40 px-6 backdrop-blur sm:w-auto"
            >
              <a href={SECONDARY.href}>{SECONDARY.label}</a>
            </Button>
          </div>

          <ul className="mt-10 flex flex-col items-center justify-center gap-x-6 gap-y-2 text-sm text-muted-foreground sm:flex-row">
            {PERKS.map((perk) => (
              <li key={perk} className="flex items-center gap-2">
                <CheckIcon aria-hidden className="size-4 text-brand-to" />
                {perk}
              </li>
            ))}
          </ul>
        </div>
      </div>
    </section>
  );
}
```
