All Taste components
Features
Features — numbered alternating rows
Three features told one per row, numbered, with the picture swapping sides and a figure under each.
outlined step numbers · 5 : 7 split · mirrored rows · ruled between rows · stat callout
A booking page that looks like you
Your services, prices and free times on one page with your name on it. Share the link anywhere.
10 minto set up, on average
Deposits that end no-shows
Ask for a small deposit when someone books. If they cancel late, it's yours — automatically.
−70%fewer missed slots, a typical result
import type { ReactNode } from "react";
import { cn } from "@/lib/utils";
const ServicesPicture = () => (
<div className="w-full max-w-[340px] rounded-lg border border-border bg-bg p-4 text-[12.5px] shadow-xl">
<div className="mb-3 flex justify-between"><p className="text-sm font-semibold text-fg">Studio Nila</p><p className="text-fg-subtle">Choose a service</p></div>
<div className="grid gap-2">
{[["Haircut · 45 min", "₹800"], ["Colour · 90 min", "₹2,400"], ["Beard trim · 20 min", "₹350"]].map(([s, p], i) => (
<div key={s} className={cn("flex justify-between rounded border border-border px-3 py-2.5 text-fg", i === 1 && "border-primary bg-primary-soft text-primary-soft-fg")}>
<span>{s}</span><span className="tabular-nums">{p}</span>
</div>
))}
</div>
</div>
);
const DepositPicture = () => (
<div className="grid w-full max-w-[340px] gap-2.5 rounded-lg border border-border bg-bg p-4 text-[12.5px] shadow-xl">
<div className="flex justify-between text-fg-subtle">
<span>Deposit for Thu 10:30</span>
<span className="rounded-full bg-success-soft px-2 text-xs font-medium text-success-fg">Paid</span>
</div>
<p className="text-[26px] font-semibold tracking-tight text-fg">₹500</p>
<div className="h-2 overflow-hidden rounded-full bg-surface-2"><div className="h-full w-1/5 rounded-full bg-primary" /></div>
<p className="text-fg-subtle">₹1,900 left to pay at the studio</p>
</div>
);
const rows: { title: string; text: string; stat: { value: string; label: string }; picture: ReactNode }[] = [
{ title: "A booking page that looks like you", text: "Your services, prices and free times on one page with your name on it. Share the link anywhere.", stat: { value: "10 min", label: "to set up, on average" }, picture: <ServicesPicture /> },
{ title: "Deposits that end no-shows", text: "Ask for a small deposit when someone books. If they cancel late, it’s yours — automatically.", stat: { value: "−70%", label: "fewer missed slots, a typical result" }, picture: <DepositPicture /> },
];
export function FeaturesAlternating() {
return (
<section aria-label="Features" className="bg-bg font-sans">
<div className="mx-auto max-w-6xl divide-y divide-border px-4 sm:px-6">
{rows.map((row, i) => (
<div key={row.title} className="grid items-center gap-7 py-12 lg:grid-cols-[5fr_7fr] lg:gap-16 lg:py-[72px]">
<div className={cn("flex flex-col items-start gap-3.5", i % 2 === 1 && "lg:order-2")}>
{/* Outlined number: transparent fill with a stroke */}
<span aria-hidden className="text-[40px] font-semibold leading-none tracking-[-0.05em] text-transparent [-webkit-text-stroke:1.5px_var(--tst-border-strong)] lg:text-[56px]">
{String(i + 1).padStart(2, "0")}
</span>
<h2 className="text-balance text-2xl font-semibold tracking-tight text-fg lg:text-3xl">{row.title}</h2>
<p className="text-pretty text-[14.5px] leading-relaxed text-fg-muted">{row.text}</p>
<p className="mt-2 flex items-baseline gap-2.5 self-stretch border-t border-dashed border-border-strong pt-4">
<span className="text-[28px] font-semibold tracking-tight tabular-nums text-primary">{row.stat.value}</span>
<span className="text-[13px] text-fg-muted">{row.stat.label}</span>
</p>
</div>
<div aria-hidden className="grid place-items-center rounded-xl bg-surface bg-gradient-to-br from-primary-soft to-surface p-5 sm:p-8 lg:min-h-[300px]">
{row.picture}
</div>
</div>
))}
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.