We've spent years refining the details. Here's what sets us apart.
Familiar interface patterns mean your team can start working immediately. No training sessions required.
Built on modern infrastructure with global edge caching. Every action feels instant.
SOC 2 Type II certified, GDPR compliant, with SSO and advanced audit logs included.
One plan, one price. No hidden fees, no surprise overages, no complicated tiers.
Real people who understand the product. Average response time under 2 hours.
Full API access, webhooks, and 100+ integrations. Build exactly what you need.
Two-column grid of numbered items (01, 02, etc.) with circular badges, titles, and descriptions. Perfect for why-choose-us sections, benefits lists, or key differentiators.
List of features tagged with zero-padded circular numbers ("01", "02", ...) instead of icons, laid out as either a single centered column or a two-column grid depending on the columns prop.
Free block
This block is free. No license or account is required: install it with the CLI and use it in unlimited projects.
Radix flavor
npx shadcn add "https://ui.beste.co/r/feature34"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/feature34"This installs the block to components/beste/block/feature34.tsx and the shadcn/ui badge and button components it depends on.
The installed file exports feature34Demo alongside the block: the exact props behind the preview above. Spread it to get a working numbered list in one line.
import { Feature34, feature34Demo } from "@/components/beste/block/feature34";
export default function Page() {
return <Feature34 {...feature34Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { Feature34 } from "@/components/beste/block/feature34";
export default function Page() {
return (
<Feature34
badge={{ label: "Why us", variant: "default" }}
heading="Four reasons teams choose us"
description="We've spent years refining the details."
columns={1}
features={[
{
id: "feature-1",
title: "No learning curve",
description: "Familiar interface patterns mean your team can start immediately.",
},
{
id: "feature-2",
title: "Transparent pricing",
description: "One plan, one price. No hidden fees.",
},
]}
buttons={[{ id: "btn-1", label: "Start free trial", href: "/signup" }]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | { label: string; variant?: "default" | "secondary" | "outline" } | – | Badge above the heading |
heading | string | – | Section heading |
description | string | – | Section intro text |
features | NumberedFeature[] | [] | Numbered rows; the section renders nothing when this is empty |
buttons | ButtonItem[] | [] | CTA buttons below the list |
columns | 1 | 2 | 2 | 2 lays out a md:grid-cols-2 grid; 1 centers a single max-w-3xl column |
className | string | – | Extra classes for the outer <section> |
type NumberedFeature = {
id: string;
title: string;
description: string;
};
type ButtonItem = {
id: string;
label: string;
href?: string;
variant?: "default" | "secondary" | "outline" | "ghost" | "link" | "destructive";
};null when features is empty, so it never renders a header with no rows beneath it.padStart(2, "0") ("01", "02", ...); it is not a prop and cannot be overridden per item.columns is coerced with Number(columns) before the === 2 check, so it tolerates a stringified "2" being passed even though the type only declares 1 | 2.border-primary text-primary, unlike feature23/feature26/feature29/feature107 which accept a custom icon node per item.columns grid switch itself.