Blocks / Marketing
Testimonials
A large pull quote with the figure behind it, three short quotes with results, and a row of customer names.
From the kitchens
Less in the bin, and fewer late calls to suppliers.
We cut waste from 7% to 3% of food spend in ten weeks. Nobody worked harder. We just stopped ordering cream for a Tuesday that was never going to come.
I used to count flour sacks on a Sunday night. Now they are scanned in when the pallet lands, and Sunday is mine again.
Aoife BrennanOwner and baker, Halfmoon Bakery, Bristol 4 hours a week backMoving oat milk between three cafes was a group chat and a guess. Now it is a transfer, and both counts agree at close.
Dev MalhotraOperations lead, Fieldhouse Cafes, Manchester 3 sites, one stock countIt showed we were binning a third of the Sunday beef. We dropped two ribs from the order and only the accountant noticed.
Rhian EvansLandlady and cook, The Drovers Arms, Llandeilo £310 a month less on beef
Kitchens counting with Larder
- Marrow
- Halfmoon Bakery
- The Drovers Arms
- Fieldhouse
- Little Fennel
- Bramble & Rye
- Tidewater
- Okra Kitchen
Install
Writes the block to components/blocks/testimonials.tsx and its .css, and every part it uses to components/equip/, with the parts those are built from.
npx https://equip.studio311.app/equip.tgz add block:testimonialsBuilt from 7 parts
Notes
- Every quote is a figure with a blockquote and a figcaption, so the words stay tied to the person who said them.
- Avatars take an empty alt because the name is written beside them; pass src for real photos.
- The customer names are styled text in a labelled list; swap in logo images with alt text if you have them.
Source
components/blocks/testimonials.tsx158 lines
import { Avatar } from "@/components/equip/avatar";
import { Badge } from "@/components/equip/badge";
import { Card } from "@/components/equip/card";
import { Heading } from "@/components/equip/heading";
import { Sparkline } from "@/components/equip/sparkline";
import { Stat } from "@/components/equip/stat";
import { Text } from "@/components/equip/text";
import "./testimonials.css";
/*
* What kitchens say after a few months: one long quote with the number behind it, three short ones
* hung on a ticket rail like orders on the pass, and a row of kitchens set as type.
*/
export default function Testimonials() {
return (
<section className="blk-testimonials" aria-labelledby="testimonials-title">
<div className="blk-testimonials-inner">
<header className="blk-testimonials-head">
<Text size="s" weight="strong" tone="quiet">
From the kitchens
</Text>
<Heading level={2} id="testimonials-title" className="blk-testimonials-title">
Less in the bin, and fewer late calls to suppliers.
</Heading>
</header>
<div className="blk-testimonials-feature">
<figure className="blk-testimonials-feature-words">
<span className="blk-testimonials-mark" aria-hidden="true">
“
</span>
<blockquote className="blk-testimonials-quote">
<p>
We cut waste from 7% to 3% of food spend in ten weeks. Nobody worked harder. We just stopped ordering
cream for a Tuesday that was never going to come.
</p>
</blockquote>
<figcaption className="blk-testimonials-who">
<Avatar name="Ines Duarte" alt="" size="l" />
<span className="blk-testimonials-who-text">
<Text as="span" weight="strong">Ines Duarte</Text>
<Text as="span" size="s" tone="quiet">Head chef, Marrow, Wilton Way, Hackney</Text>
</span>
</figcaption>
</figure>
<div className="blk-testimonials-proof">
<Stat
label="Waste, as a share of food spend"
value={3}
unit="%"
hint="Was 7% the week before Larder"
locale="en-GB"
/>
<div className="blk-testimonials-spark">
<Sparkline
className="blk-testimonials-spark-line"
label="Waste as a percent of food spend, weekly for ten weeks"
values={[7.1, 6.8, 6.4, 5.7, 5.2, 4.6, 4.1, 3.6, 3.2, 3]}
width={200}
height={56}
min={0}
area
showLast
locale="en-GB"
/>
<span className="blk-testimonials-spark-axis" aria-hidden="true">
<span>Week 1</span>
<span>Week 10</span>
</span>
</div>
</div>
</div>
<ul className="blk-testimonials-rail" aria-label="More kitchens">
<Card as="li" className="blk-testimonials-ticket">
<figure className="blk-testimonials-small">
<blockquote className="blk-testimonials-small-quote">
<p>
I used to count flour sacks on a Sunday night. Now they are scanned in when the pallet lands, and
Sunday is mine again.
</p>
</blockquote>
<figcaption className="blk-testimonials-who">
<Avatar name="Aoife Brennan" alt="" />
<span className="blk-testimonials-who-text">
<Text as="span" size="s" weight="strong">Aoife Brennan</Text>
<Text as="span" size="s" tone="quiet">Owner and baker, Halfmoon Bakery, Bristol</Text>
</span>
</figcaption>
</figure>
<div className="blk-testimonials-result">
<Badge tone="ok" dot>4 hours a week back</Badge>
</div>
</Card>
<Card as="li" className="blk-testimonials-ticket">
<figure className="blk-testimonials-small">
<blockquote className="blk-testimonials-small-quote">
<p>
Moving oat milk between three cafes was a group chat and a guess. Now it is a transfer, and both
counts agree at close.
</p>
</blockquote>
<figcaption className="blk-testimonials-who">
<Avatar name="Dev Malhotra" alt="" />
<span className="blk-testimonials-who-text">
<Text as="span" size="s" weight="strong">Dev Malhotra</Text>
<Text as="span" size="s" tone="quiet">Operations lead, Fieldhouse Cafes, Manchester</Text>
</span>
</figcaption>
</figure>
<div className="blk-testimonials-result">
<Badge dot>3 sites, one stock count</Badge>
</div>
</Card>
<Card as="li" className="blk-testimonials-ticket">
<figure className="blk-testimonials-small">
<blockquote className="blk-testimonials-small-quote">
<p>
It showed we were binning a third of the Sunday beef. We dropped two ribs from the order and only
the accountant noticed.
</p>
</blockquote>
<figcaption className="blk-testimonials-who">
<Avatar name="Rhian Evans" alt="" />
<span className="blk-testimonials-who-text">
<Text as="span" size="s" weight="strong">Rhian Evans</Text>
<Text as="span" size="s" tone="quiet">Landlady and cook, The Drovers Arms, Llandeilo</Text>
</span>
</figcaption>
</figure>
<div className="blk-testimonials-result">
<Badge tone="ok" dot>£310 a month less on beef</Badge>
</div>
</Card>
</ul>
<div className="blk-testimonials-kitchens">
<Text size="s" tone="faint" className="blk-testimonials-kitchens-label" id="testimonials-kitchens-label">
Kitchens counting with Larder
</Text>
<ul className="blk-testimonials-marks" aria-labelledby="testimonials-kitchens-label">
<li className="blk-testimonials-wordmark" data-look="heavy">Marrow</li>
<li className="blk-testimonials-wordmark" data-look="italic">Halfmoon Bakery</li>
<li className="blk-testimonials-wordmark" data-look="mono">The Drovers Arms</li>
<li className="blk-testimonials-wordmark" data-look="spaced">Fieldhouse</li>
<li className="blk-testimonials-wordmark" data-look="boxed">Little Fennel</li>
<li className="blk-testimonials-wordmark" data-look="italic">Bramble & Rye</li>
<li className="blk-testimonials-wordmark" data-look="heavy">Tidewater</li>
<li className="blk-testimonials-wordmark" data-look="mono">Okra Kitchen</li>
</ul>
</div>
</div>
</section>
);
}components/blocks/testimonials.css293 lines
@layer blocks {
.blk-testimonials {
container: blk-testimonials / inline-size;
background: var(--eq-bg);
color: var(--eq-ink);
}
.blk-testimonials-inner {
display: grid;
gap: calc(var(--eq-space-6) * 1.5);
max-width: 76rem;
margin-inline: auto;
padding: calc(var(--eq-space-6) * 1.5) var(--eq-space-4);
}
.blk-testimonials-head {
display: grid;
justify-items: start;
gap: var(--eq-space-3);
max-width: 40rem;
}
.blk-testimonials-head > * {
margin: 0;
}
.blk-testimonials-title {
font-size: clamp(1.75rem, 5.5cqi, 3rem);
line-height: 1.06;
letter-spacing: -0.025em;
text-wrap: balance;
}
/* ---- The pull quote ---- */
.blk-testimonials-feature {
display: grid;
gap: var(--eq-space-6);
padding: var(--eq-space-5) var(--eq-space-4);
border: 1px solid var(--eq-line);
border-radius: var(--eq-radius-l);
background: var(--eq-surface);
}
.blk-testimonials-feature-words {
display: grid;
align-content: start;
gap: var(--eq-space-5);
min-width: 0;
margin: 0;
}
.blk-testimonials-mark {
display: block;
height: 0.5em;
margin-bottom: calc(var(--eq-space-3) * -1);
color: var(--eq-ink-3);
font: var(--eq-weight-strong) calc(var(--eq-text-l) * 5) / 1 var(--eq-font);
}
.blk-testimonials-quote {
margin: 0;
}
.blk-testimonials-quote > p {
margin: 0;
color: var(--eq-ink);
font: var(--eq-weight-strong) clamp(1.375rem, 4.2cqi, 2.375rem) / 1.18 var(--eq-font);
letter-spacing: -0.02em;
text-wrap: pretty;
}
.blk-testimonials-who {
display: flex;
align-items: center;
gap: var(--eq-space-3);
min-width: 0;
}
.blk-testimonials-who-text {
display: grid;
min-width: 0;
}
.blk-testimonials-who-text > * {
margin: 0;
}
/* The number behind the quote: a figure and ten weeks of it falling. */
.blk-testimonials-proof {
display: grid;
align-content: space-between;
gap: var(--eq-space-5);
min-width: 0;
padding: var(--eq-space-4);
border-radius: var(--eq-radius-m);
border: 1px solid var(--eq-line);
background:
radial-gradient(circle at 1px 1px, var(--eq-line-strong) 1px, transparent 0) 0 0 / 18px 18px,
color-mix(in oklab, var(--eq-surface) 60%, var(--eq-bg));
}
.blk-testimonials-spark {
display: grid;
gap: var(--eq-space-1);
width: fit-content;
max-width: 100%;
}
.blk-testimonials-spark-line {
color: var(--eq-chart-1);
}
.blk-testimonials-spark-axis {
display: flex;
justify-content: space-between;
color: var(--eq-ink-3);
font: var(--eq-weight) var(--eq-text-xs) / 1.2 var(--eq-font-mono);
font-variation-settings: var(--eq-font-mono-settings);
}
/* ---- The ticket rail: short quotes hang from a bar like orders on the pass ---- */
.blk-testimonials-rail {
--_hang: calc(var(--eq-space-5) + var(--eq-space-2));
display: grid;
grid-template-columns: minmax(0, 1fr);
gap: calc(var(--_hang) + var(--eq-space-5)) var(--eq-space-4);
margin: 0;
padding: var(--_hang) 0 0;
list-style: none;
}
.blk-testimonials-ticket {
justify-content: space-between;
}
/* The rail, drawn per ticket so a stacked column still hangs; side by side the pieces meet in the gap. */
.blk-testimonials-ticket::after {
content: "";
position: absolute;
z-index: 0;
top: calc(var(--_hang) * -1);
inset-inline: calc(var(--eq-space-4) / -2);
height: var(--eq-space-2);
box-sizing: border-box;
border-block: 1px solid var(--eq-line-strong);
background: var(--eq-tint-strong);
}
/* The clip each ticket hangs from. */
.blk-testimonials-ticket::before {
content: "";
position: absolute;
z-index: 1;
top: calc(var(--_hang) * -1 + var(--eq-space-1));
inset-inline-start: var(--eq-space-5);
box-sizing: border-box;
width: var(--eq-space-3);
height: calc(var(--_hang) - var(--eq-space-1) + 1px);
border: 1px solid var(--eq-line-strong);
border-radius: var(--eq-radius-s);
background: var(--eq-surface);
}
.blk-testimonials-small {
display: grid;
gap: var(--eq-space-4);
margin: 0;
}
.blk-testimonials-small-quote {
margin: 0;
}
.blk-testimonials-small-quote > p {
margin: 0;
color: var(--eq-ink);
font-size: var(--eq-text-l);
line-height: 1.45;
text-wrap: pretty;
}
.blk-testimonials-result {
display: flex;
padding-top: var(--eq-space-3);
border-top: 1px dashed var(--eq-line-strong);
}
/* ---- Kitchens, set as type ---- */
.blk-testimonials-kitchens {
display: grid;
gap: var(--eq-space-4);
padding-top: var(--eq-space-5);
border-top: 1px solid var(--eq-line);
}
.blk-testimonials-kitchens-label {
margin: 0;
}
.blk-testimonials-marks {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: var(--eq-space-4) var(--eq-space-6);
margin: 0;
padding: 0;
list-style: none;
color: var(--eq-ink-2);
}
.blk-testimonials-wordmark {
margin: 0;
font: var(--eq-weight-strong) var(--eq-text-l) / 1.2 var(--eq-font);
white-space: nowrap;
}
.blk-testimonials-wordmark[data-look="heavy"] {
font-size: calc(var(--eq-text-l) * 1.25);
letter-spacing: -0.04em;
}
.blk-testimonials-wordmark[data-look="italic"] {
font-style: italic;
font-weight: var(--eq-weight);
letter-spacing: -0.01em;
}
.blk-testimonials-wordmark[data-look="mono"] {
font: var(--eq-weight) var(--eq-text-m) / 1.2 var(--eq-font-mono);
font-variation-settings: var(--eq-font-mono-settings);
}
.blk-testimonials-wordmark[data-look="spaced"] {
font-size: var(--eq-text-s);
letter-spacing: 0.24em;
}
.blk-testimonials-wordmark[data-look="boxed"] {
padding: var(--eq-space-1) var(--eq-space-2);
border: 1px solid currentColor;
border-radius: var(--eq-radius-s);
font-size: var(--eq-text-m);
}
@container blk-testimonials (width >= 40rem) {
.blk-testimonials-inner {
padding-inline: var(--eq-space-6);
}
.blk-testimonials-feature {
padding: var(--eq-space-6);
}
.blk-testimonials-rail {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.blk-testimonials-rail > :last-child {
grid-column: 1 / -1;
}
}
@container blk-testimonials (width >= 60rem) {
.blk-testimonials-inner {
padding-block: calc(var(--eq-space-6) * 2.5);
gap: calc(var(--eq-space-6) * 1.75);
}
.blk-testimonials-feature {
grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
gap: calc(var(--eq-space-6) * 1.5);
padding: calc(var(--eq-space-6) * 1.5);
}
.blk-testimonials-rail {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
.blk-testimonials-rail > :last-child {
grid-column: auto;
}
.blk-testimonials-kitchens {
grid-template-columns: auto minmax(0, 1fr);
align-items: center;
gap: var(--eq-space-6);
}
}
}