Side-by-side intro with animated number counters on scroll, expanding accent bars, and hover-lift value cards. For impact-driven companies.
Split intro (copy and CTAs on the left, a hero photo on the right) followed by a row of scroll-triggered animated number counters and a grid of hover-lift value cards. Built for impact-driven companies that want their stats to feel alive rather than static text.
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/about25?email=YOUR_EMAIL&license_key=YOUR_KEY"Base UI flavor
npx shadcn add "https://ui.beste.co/r-base/about25?email=YOUR_EMAIL&license_key=YOUR_KEY"This installs the block to components/beste/block/about25.tsx and the badge and button shadcn/ui primitives it depends on.
The installed file exports about25Demo alongside the block: the exact props behind the preview above. Spread it to get a working about section in one line.
import { About25, about25Demo } from "@/components/beste/block/about25";
export default function AboutPage() {
return <About25 {...about25Demo} />;
}Then replace the demo with your own props. Written out, a trimmed setup looks like this:
import { About25 } from "@/components/beste/block/about25";
export default function AboutPage() {
return (
<About25
badge={{ label: "Who We Are", variant: "outline" }}
heading="Building the future of sustainable energy"
description="Engineers, scientists, and dreamers united by one mission."
image={{
src: "https://images.unsplash.com/photo-1497440001374-f26997328c1b?w=900&h=500&fit=crop",
alt: "Solar panel array at sunset",
}}
stats={[
{ value: 12, suffix: "GW", label: "Clean Energy Delivered" },
{ value: 340, suffix: "+", label: "Communities Powered" },
]}
values={[
{ title: "Radical Transparency", description: "Every watt visible in real time." },
{ title: "Community First", description: "We co-design every project locally." },
]}
buttons={[{ label: "Our Projects", href: "https://beste.co" }]}
/>
);
}| Prop | Type | Default | Description |
|---|---|---|---|
badge | { label: string; variant?: "default" | "secondary" | "outline" } | – | Eyebrow badge above the heading |
heading | string | – | Section heading in the left column |
description | string | – | Lead paragraph in the left column |
image | { src: string; alt: string } | – | Photo in the right column |
stats | StatItem[] | [] | Row of animated number counters below the intro |
values | ValueItem[] | [] | Hover-lift value cards below the stats |
buttons | ButtonItem[] | [] | CTA row under the description |
className | string | – | Extra classes for the outer <section> |
type StatItem = { value: number; suffix?: string; prefix?: string; label: string };
type ValueItem = { title: string; description: string };
type ButtonItem = {
label: string;
href?: string;
variant?: "default" | "secondary" | "outline" | "ghost" | "link" | "destructive";
};AnimatedNumber component: an IntersectionObserver (threshold 0.3) fires once when the stat scrolls into view, then a requestAnimationFrame loop counts from 0 to value over 1600ms with a cubic ease-out curve. A hasAnimated ref guarantees it only plays once, even if the element re-enters the viewport later.stat.value must be a plain number; prefix and suffix are rendered as static strings around the animated digits (the demo uses suffix for units like "GW", "+", and ".7%").h-1 w-12) expands to the stat's full column width on hover via group-hover:w-full, purely a CSS hover effect independent of the number animation.grid-cols-2 sm:grid-cols-4 layout regardless of how many stats are passed; it is not the dynamic column-count pattern.bg-muted/50 panel that shifts to bg-muted on hover (transition-colors duration-300) and sit in a fixed sm:grid-cols-3 grid.values[0].description contains a literal em dash ("Every watt generated, every dollar spent — visible to our stakeholders in real time.") reproduced here exactly as it appears in the source.about46
An about intro followed by a horizontally scrollable strip mixing image, stat, quote and values cards.
about14
Horizontal stats row at the top followed by a centered story card with heading, body text, and CTAs.
about28
Full-width animated marquee stats ticker, split layout with intro text and leadership avatars on the left, full-height image on the right. For SaaS and product companies.
about27
Left intro with image, right vertical timeline with staggered scroll-reveal animation. Numbered steps with sliding content. For startup journeys.
about5
Side-by-side layout with a tall image on the left and company story, inline stats, and CTAs on the right.
about8
Four-column stats grid with large numbers, titles, and supporting descriptions. Perfect for impact and results sections.