All Taste components
Features
Features — accordion with visual
A numbered accordion of features on the left; opening one changes the picture on the right.
4 numbered items · one open at a time · picture follows the open item · picture first on small screens
For studios with regulars
Everything between “can I book?” and “see you Thursday”
01Online booking page
Clients pick a service and a free time, day or night. You set the hours and the gaps between appointments.
Learn more02Deposits and payments
Take a deposit when they book and the rest after. Card, UPI or cash — all in one list.
Learn more03Reminders by WhatsApp and email
A message the day before with a one-tap reschedule link. Fewer no-shows, fewer phone calls.
Learn more04Client notes
Remember the colour formula, the allergy and the favourite playlist. Notes stay with the client.
Learn more"use client";
import { useState, type ReactNode } from "react";
import { ArrowRight, ChevronDown } from "lucide-react";
import { cn } from "@/lib/utils";
type Item = { title: string; text: string; href: string; picture: ReactNode };
/* Replace these with screenshots of your product, or keep the drawn cards. */
const card = "w-full max-w-[340px] rounded-lg border border-border bg-bg p-4 text-[12.5px] text-fg shadow-xl";
const items: Item[] = [
{ title: "Online booking page", href: "/booking", text: "Clients pick a service and a free time, day or night. You set the hours and the gaps between appointments.",
picture: <div className={card}><p className="mb-3 font-semibold">Pick a time · Thu 16 Oct</p><div className="grid grid-cols-4 gap-1.5 text-center">{["9:00", "9:45", "10:30", "11:15", "12:00", "14:00", "14:45", "15:30"].map((t, i) => <span key={t} className={cn("rounded-sm border border-border py-1.5 tabular-nums text-fg-muted", i === 2 && "border-primary bg-primary text-primary-fg")}>{t}</span>)}</div></div> },
{ title: "Deposits and payments", href: "/payments", text: "Take a deposit when they book and the rest after. Card, UPI or cash — all in one list.",
picture: <div className={card + " grid gap-2"}>{[["Deposit · Anaya S.", "₹500"], ["Paid in full · Dev M.", "₹350"], ["Due at visit · Meera I.", "₹800"]].map(([a, b]) => <div key={a} className="flex justify-between rounded border border-border px-3 py-2.5"><span>{a}</span><span className="font-medium tabular-nums">{b}</span></div>)}</div> },
{ title: "Reminders by WhatsApp and email", href: "/reminders", text: "A message the day before with a one-tap reschedule link. Fewer no-shows, fewer phone calls.",
picture: <div className={card + " grid gap-2.5"}><p className="text-fg-subtle">Tomorrow, 9:00 am</p><p className="rounded-lg border border-border px-3 py-2">Hi Anaya! See you tomorrow at 10:30 for Colour. Need to move it? Tap here.</p></div> },
{ title: "Client notes", href: "/clients", text: "Remember the colour formula, the allergy and the favourite playlist. Notes stay with the client.",
picture: <div className={card + " grid gap-2"}><p className="font-semibold">Anaya Shah</p><p className="rounded border border-border px-3 py-2.5">Formula: 7.1 + 20 vol</p><p className="rounded border border-border px-3 py-2.5">Allergic to lavender oil</p></div> },
];
export function FeaturesAccordion() {
const [open, setOpen] = useState(0);
return (
<section aria-labelledby="features-title" className="bg-surface font-sans">
<div className="mx-auto max-w-6xl px-4 py-16 sm:px-6 lg:py-24">
<p className="text-[13px] font-medium text-primary">For studios with regulars</p>
<h2 id="features-title" className="mt-3.5 max-w-2xl text-balance text-3xl font-semibold tracking-tight text-fg sm:text-4xl">
Everything between “can I book?” and “see you Thursday”
</h2>
<div className="mt-12 grid items-center gap-7 lg:grid-cols-[1fr_1.15fr] lg:gap-14">
<div className="border-t border-border">
{items.map((item, i) => {
const isOpen = open === i;
return (
<div key={item.title} className="border-b border-border">
<h3>
<button
type="button"
aria-expanded={isOpen}
onClick={() => setOpen(i)}
className={cn("flex w-full items-center gap-3.5 py-[18px] text-left text-base font-semibold tracking-tight transition", isOpen ? "text-fg" : "text-fg-muted hover:text-fg")}
>
<span className={cn("text-xs font-medium tabular-nums", isOpen ? "text-primary" : "text-fg-subtle")}>{String(i + 1).padStart(2, "0")}</span>
{item.title}
<ChevronDown className={cn("ml-auto size-4 text-fg-subtle transition-transform", isOpen && "rotate-180")} aria-hidden />
</button>
</h3>
{isOpen && (
<div className="grid gap-3 pb-5 pl-[34px]">
<p className="text-pretty text-[14.5px] leading-relaxed text-fg-muted">{item.text}</p>
<a href={item.href} className="inline-flex items-center gap-1 text-sm font-medium text-primary hover:underline">Learn more <ArrowRight className="size-4" aria-hidden /></a>
</div>
)}
</div>
);
})}
</div>
<div aria-hidden className="-order-1 grid place-items-center rounded-xl bg-surface bg-gradient-to-br from-primary-soft to-bg p-5 sm:p-8 lg:order-none lg:min-h-[320px]">
{items[open].picture}
</div>
</div>
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.