Skip to content
All Taste components

Features

Alternating feature rows

Two features told in more depth, text and picture swapping sides from row to row.

2 rows · checklist · mirrored layout · stacks below 620px

Reminders

Follow-ups that sound like you

Write the message once. Fernbill sends it at the right moment and stops the second the client pays.

  • Three tones, from friendly to firm
  • Stops as soon as the invoice is paid
  • Skips weekends and public holidays

Cash flow

See who owes what, at a glance

Every client, every open invoice, sorted by what needs you first.

  • Late invoices float to the top
  • Totals in your home currency
  • One click to resend or mark paid
import { Check } from "lucide-react";
import { cn } from "@/lib/utils";

const rows = [
  {
    eyebrow: "Reminders",
    title: "Follow-ups that sound like you",
    body: "Write the message once. Fernbill sends it at the right moment and stops the second the client pays.",
    points: ["Three tones, from friendly to firm", "Stops as soon as the invoice is paid", "Skips weekends and public holidays"],
    image: { src: "/features/reminders.png", alt: "A reminder email scheduled for Thursday at 9:00" },
  },
  {
    eyebrow: "Cash flow",
    title: "See who owes what, at a glance",
    body: "Every client, every open invoice, sorted by what needs you first.",
    points: ["Late invoices float to the top", "Totals in your home currency", "One click to resend or mark paid"],
    image: { src: "/features/cash-flow.png", alt: "A list of clients with late, due and paid invoices" },
  },
];

export function FeatureRows() {
  return (
    <section aria-label="Features" className="bg-bg font-sans">
      <div className="mx-auto grid max-w-6xl gap-20 px-4 py-20 sm:px-6 lg:gap-28">
        {rows.map((row, i) => (
          <div key={row.title} className="grid items-center gap-10 lg:grid-cols-2 lg:gap-16">
            <div className={cn(i % 2 === 1 && "lg:order-2")}>
              <p className="text-[13px] font-medium text-primary">{row.eyebrow}</p>
              <h2 className="mt-3 text-balance text-3xl font-semibold tracking-tight text-fg">{row.title}</h2>
              <p className="mt-4 text-base leading-relaxed text-fg-muted">{row.body}</p>
              <ul className="mt-6 grid gap-2.5 text-sm text-fg">
                {row.points.map((p) => (
                  <li key={p} className="flex items-start gap-2.5">
                    <Check className="mt-0.5 size-4 shrink-0 text-primary" aria-hidden />
                    {p}
                  </li>
                ))}
              </ul>
            </div>
            <div className="overflow-hidden rounded-xl border border-border bg-surface p-6 sm:p-10">
              <img src={row.image.src} alt={row.image.alt} className="w-full rounded-lg border border-border bg-bg shadow-xl" />
            </div>
          </div>
        ))}
      </div>
    </section>
  );
}

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