A two-column comparison that sets a highlighted "our way" column with check-marked rows against a muted "typical agency" column with dash-marked rows, closing with a centered CTA.
Pro blocks install through the shadcn CLI with your license key and ship their full source. Docs and live previews stay open to everyone, so you can read every block's details first.
Swap YOUR_EMAIL and YOUR_KEY for the email and license key on your account. Find your license key on your account page.
Radix flavor
npx shadcn add "https://ui.beste.co/r/agency19?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/agency19?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/agency19.tsx, the badge6 component it uses for the eyebrow, the button1 component it uses for the closing CTA, and its dependencies.
The installed file exports agency19Demo alongside the block: the exact props behind the preview above. Spread it to get a working comparison section in one line.
import { Agency19, agency19Demo } from "@/components/beste/block/agency19";
export default function AboutPage() {
return <Agency19 {...agency19Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Agency19 } from "@/components/beste/block/agency19";
export default function AboutPage() {
return (
<Agency19
label="Why us"
heading="Our way <strong>vs.</strong> the usual agency"
description="Same brief, two very different experiences."
polaris={{ title: "Our way", tag: "Recommended" }}
polarisRows={[
"A senior strategist owns your account from kickoff to launch.",
"Fixed-scope pricing agreed up front.",
"Weekly working sessions where you see real progress.",
]}
typical={{ title: "The usual agency" }}
typicalRows={[
"Your project is handed off to whoever is on the bench.",
"Open-ended hourly billing that quietly balloons.",
"Monthly check-ins long on slides, short on shipped work.",
]}
button={{ label: "Start a project", href: "https://beste.co" }}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
label | string | – | Eyebrow text rendered in Badge6, centered above the heading |
heading | string | – | Section heading, rendered with dangerouslySetInnerHTML |
description | string | – | Centered intro text under the heading |
polaris | ColumnHeader | – | Title (and optional pill tag) for the highlighted left column |
polarisRows | string[] | [] | Check-marked rows in the highlighted column |
typical | ColumnHeader | – | Title (and optional pill tag) for the muted right column |
typicalRows | string[] | [] | Dash-marked rows in the muted column |
button | ActionLink | – | Centered CTA below the columns; hidden entirely when omitted |
className | string | – | Extra classes for the outer <section> |
type ColumnHeader = { title: string; tag?: string };
type ActionLink = { label: string; href: string };heading supports inline <strong> highlighting via dangerouslySetInnerHTML; highlighted text renders in text-primary.polaris column is visually distinguished with a border-2 border-primary outline and Check icons on filled bg-primary badges; the typical column uses a plain border, a bg-muted/30 fill, and Minus icons on bg-muted badges.polaris and typical accept an optional tag pill next to the column title (the demo only sets one on polaris, but typical supports the same field).polarisRows and typicalRows are independent arrays; they are not required to be the same length and render as two separate lists, not paired rows.button is passed.agency16
Studio overview pairing facts, copy and highlight stats with a clean studio image.