Stats & values
Stats Row
Three figures with a title and a line of text each, split by thin lines on an inverted band.
Layout and motion from the Findit template — see it in contextimport * as React from "react";
import { cn } from "@/lib/utils";
/*
* Stats Row — three figures, each with a title and a line of text, split by thin lines on an inverted band.
* Source: marcframe/findit → components/sections/FactsSection.tsx (+ design-system FactList).
*
* Layout kept from Framer: figures stack below 768px with a line between them, and sit in three equal columns with
* vertical lines from 768px. The band is compact: half the usual section padding. No motion, as on Framer.
* The band inverts the theme (foreground behind background-coloured text), so it reads dark on a light page and light
* on a dark one. The heading is for screen readers — the figures speak for themselves.
*/
export type StatItem = { value: string; title: string; text: string };
export type StatsRowProps = {
/** Section heading, visually hidden. */
title?: string;
stats?: StatItem[];
className?: string;
};
const defaults = {
title: "Our track record",
stats: [
{ value: "$150M+", title: "Properties sold", text: "Homes and investments closed for our clients since we opened our doors." },
{ value: "1,200+", title: "Happy families", text: "Buyers and renters who found a place they love to come home to." },
{ value: "20 yrs", title: "In the market", text: "Two decades of local knowledge in every neighbourhood we cover." },
],
};
export function StatsRow({ title = defaults.title, stats = defaults.stats, className }: StatsRowProps) {
return (
<section className={cn("bg-foreground py-[calc(var(--section-y)/2)] text-background", className)}>
<h2 className="sr-only">{title}</h2>
<div className="mx-auto flex max-w-(--container) flex-col gap-5 px-(--gutter) md:flex-row">
{stats.map((stat, i) => (
<React.Fragment key={stat.value + stat.title}>
{i > 0 && <div aria-hidden className="h-px shrink-0 bg-background/15 md:h-auto md:w-px" />}
<div className="flex flex-1 flex-col gap-5">
<p className="font-heading text-h1 font-semibold tracking-tight">{stat.value}</p>
<div className="flex flex-col gap-2.5">
<p className="font-medium">{stat.title}</p>
<p className="text-sm opacity-80">{stat.text}</p>
</div>
</div>
</React.Fragment>
))}
</div>
</section>
);
}Installation
$ npx shadcn@latest add https://framebrick.co/r/blocks/stats-row.json1. Add the block tokens to
app/globals.cssonce (theming).npx shadcn@latest add https://framebrick.co/r/blocks/tokens.json2. Copy the block into
components/stats-row.tsx.import * as React from "react"; import { cn } from "@/lib/utils"; /* * Stats Row — three figures, each with a title and a line of text, split by thin lines on an inverted band. * Source: marcframe/findit → components/sections/FactsSection.tsx (+ design-system FactList). * * Layout kept from Framer: figures stack below 768px with a line between them, and sit in three equal columns with * vertical lines from 768px. The band is compact: half the usual section padding. No motion, as on Framer. * The band inverts the theme (foreground behind background-coloured text), so it reads dark on a light page and light * on a dark one. The heading is for screen readers — the figures speak for themselves. */ export type StatItem = { value: string; title: string; text: string }; export type StatsRowProps = { /** Section heading, visually hidden. */ title?: string; stats?: StatItem[]; className?: string; }; const defaults = { title: "Our track record", stats: [ { value: "$150M+", title: "Properties sold", text: "Homes and investments closed for our clients since we opened our doors." }, { value: "1,200+", title: "Happy families", text: "Buyers and renters who found a place they love to come home to." }, { value: "20 yrs", title: "In the market", text: "Two decades of local knowledge in every neighbourhood we cover." }, ], }; export function StatsRow({ title = defaults.title, stats = defaults.stats, className }: StatsRowProps) { return ( <section className={cn("bg-foreground py-[calc(var(--section-y)/2)] text-background", className)}> <h2 className="sr-only">{title}</h2> <div className="mx-auto flex max-w-(--container) flex-col gap-5 px-(--gutter) md:flex-row"> {stats.map((stat, i) => ( <React.Fragment key={stat.value + stat.title}> {i > 0 && <div aria-hidden className="h-px shrink-0 bg-background/15 md:h-auto md:w-px" />} <div className="flex flex-1 flex-col gap-5"> <p className="font-heading text-h1 font-semibold tracking-tight">{stat.value}</p> <div className="flex flex-col gap-2.5"> <p className="font-medium">{stat.title}</p> <p className="text-sm opacity-80">{stat.text}</p> </div> </div> </React.Fragment> ))} </div> </section> ); }
Usage
import { StatsRow } from "@/components/stats-row";
<StatsRow
stats={[
{ value: "$150M+", title: "Properties sold", text: "Homes and investments closed since we opened." },
{ value: "1,200+", title: "Happy families", text: "Buyers and renters who found their place." },
{ value: "20 yrs", title: "In the market", text: "Local knowledge in every neighbourhood." },
]}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
| title | string | — | Section heading for screen readers (visually hidden). |
| stats | { value, title, text }[] | 3 figures | Figures, left to right; three read best. |
| className | string | — | Classes for the <section>. |
- Stacked with a line between figures below 768px; three equal columns with vertical lines from 768px.
- The band inverts the theme (bg-foreground, text-background) and uses half the section padding. No motion.
AI prompt
Paste into v0, Lovable, Bolt or Claude to rebuild this block in your own project.
Create a React + Tailwind CSS block called StatsRow. - <section className="bg-foreground text-background py-[calc(var(--section-y)/2)]"> with a visually hidden h2; container mx-auto max-w-(--container) px-(--gutter). - Figures in a column (gap-5) that becomes a row from 768px, separated by 1px lines (h-px, vertical w-px from 768px) in background/15. Each figure (flex-1): the value in font-heading text-h1 semibold tracking-tight, then (gap-5) its title (font-medium) and text (text-sm, 80% opacity), 10px apart. - Only shadcn variables and block tokens. No motion.











