Skip to content
All Taste components

Testimonials

Testimonials — social post cards

Customer posts shown as social-media style cards with handles, mentions and reply counts.

6 post cards · handle + date · mentions and tags in brand colour · reply / share / like counts · 1–3 columns

Shared by customers

People who book for a living

A few things owners have posted about running their week on Slotwise.

Marta Kowal@martabakes

Moved the bakery’s pre-orders to @slotwise last month. Saturday pickups now arrive in 15-minute waves instead of one long queue out the door.

41286
Theo Adeyemi@theocuts

Deposits at booking cut my no-shows to almost nothing. Wish I’d done this two years ago. #barberlife

921143
Ines Duarte@ines.pilates

Clients can move their own class now. I haven’t answered a single “can I switch to Thursday?” text this week.

2564
Sam Whitlock@whitlockphysio

Three of us share one calendar and nobody has been double-booked since we switched. Small thing, huge relief.

6897
Priya Raman@priyatutors

Parents book the next lesson before they leave. Reminder texts go out on their own. @slotwise pays for itself by Tuesday.

314112
Jonas Berg@bergtattoo

The intake form at booking means I see the design brief before the client walks in. Consults got twice as fast.

5978
import { Heart, MessageCircle, Repeat2 } from "lucide-react";

type Post = { name: string; handle: string; date: string; text: string; replies: number; shares: number; likes: number };

const posts: Post[] = [
  { name: "Marta Kowal", handle: "@martabakes", date: "Mar 4", text: "Moved the bakery’s pre-orders to @slotwise last month. Saturday pickups now arrive in 15-minute waves instead of one long queue.", replies: 4, shares: 12, likes: 86 },
  { name: "Theo Adeyemi", handle: "@theocuts", date: "Feb 27", text: "Deposits at booking cut my no-shows to almost nothing. Wish I’d done this two years ago. #barberlife", replies: 9, shares: 21, likes: 143 },
  { name: "Ines Duarte", handle: "@ines.pilates", date: "Feb 19", text: "Clients can move their own class now. I haven’t answered a single “can I switch to Thursday?” text this week.", replies: 2, shares: 5, likes: 64 },
  { name: "Sam Whitlock", handle: "@whitlockphysio", date: "Feb 11", text: "Three of us share one calendar and nobody has been double-booked since we switched.", replies: 6, shares: 8, likes: 97 },
  { name: "Priya Raman", handle: "@priyatutors", date: "Jan 30", text: "Parents book the next lesson before they leave. Reminder texts go out on their own. @slotwise pays for itself by Tuesday.", replies: 3, shares: 14, likes: 112 },
  { name: "Jonas Berg", handle: "@bergtattoo", date: "Jan 22", text: "The intake form at booking means I see the design brief before the client walks in.", replies: 5, shares: 9, likes: 78 },
];

const initials = (name: string) => name.split(" ").map((w) => w[0]).join("").slice(0, 2);

// Colours @mentions and #tags in the brand colour.
function Rich({ text }: { text: string }) {
  return (
    <>
      {text.split(/([@#][\w.]+)/g).map((part, i) =>
        /^[@#]/.test(part) ? <span key={i} className="text-primary">{part}</span> : part,
      )}
    </>
  );
}

export function TestimonialsSocialPosts() {
  return (
    <section aria-labelledby="posts-title" className="bg-bg px-5 py-12 font-sans sm:px-10 sm:py-20">
      <div className="mx-auto max-w-6xl">
        <div className="mx-auto mb-11 grid max-w-2xl justify-items-center gap-3.5 text-center">
          <p className="text-[13px] font-medium text-primary">Shared by customers</p>
          <h2 id="posts-title" className="text-balance text-3xl font-semibold tracking-tight text-fg sm:text-4xl">People who book for a living</h2>
          <p className="text-base text-fg-muted">A few things owners have posted about running their week on Slotwise.</p>
        </div>
        <div className="grid items-start gap-4 sm:grid-cols-2 lg:grid-cols-3">
          {posts.map((p) => (
            <figure key={p.handle} className="grid gap-3.5 rounded-lg border border-border bg-bg p-5">
              <figcaption className="flex items-center gap-2.5">
                <span className="grid size-9 shrink-0 place-items-center rounded-full bg-primary-soft text-[13px] font-medium text-primary-soft-fg" aria-hidden>{initials(p.name)}</span>
                <div className="min-w-0 flex-1 text-[13.5px] leading-tight">
                  <p className="font-semibold text-fg">{p.name}</p>
                  <p className="truncate text-fg-subtle">{p.handle}</p>
                </div>
                <MessageCircle className="size-[18px] shrink-0 text-fg-subtle" aria-hidden />
              </figcaption>
              <blockquote className="text-pretty text-[14.5px] leading-relaxed text-fg"><p><Rich text={p.text} /></p></blockquote>
              <div className="flex items-center gap-4 border-t border-border pt-3 text-[12.5px] tabular-nums text-fg-subtle">
                <span className="inline-flex items-center gap-1" aria-label={p.replies + " replies"}><MessageCircle className="size-3.5" aria-hidden />{p.replies}</span>
                <span className="inline-flex items-center gap-1" aria-label={p.shares + " shares"}><Repeat2 className="size-3.5" aria-hidden />{p.shares}</span>
                <span className="inline-flex items-center gap-1" aria-label={p.likes + " likes"}><Heart className="size-3.5" aria-hidden />{p.likes}</span>
                <time className="ml-auto">{p.date}</time>
              </div>
            </figure>
          ))}
        </div>
      </div>
    </section>
  );
}

The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.