Know what's coming in
Paid and expected income by month, so a quiet month never surprises you.
Features
Features shown as a mosaic of different-sized cards, each with a small picture of the product.
4 tiles · chart · timeline · chips · progress · wide/narrow spans
From the first invoice to the last reminder, you can see where every payment stands.
Paid and expected income by month, so a quiet month never surprises you.
Friendly first, firm later.
Your client pays in theirs.
See the moment a client views the invoice, and when they pay.
const months = [
{ m: "May", value: 46, paid: true }, { m: "Jun", value: 62, paid: true }, { m: "Jul", value: 38, paid: true },
{ m: "Aug", value: 74, paid: true }, { m: "Sep", value: 58, paid: true }, { m: "Oct", value: 82, paid: false },
{ m: "Nov", value: 50, paid: false },
];
const reminders = [
{ when: "On the due date", what: "A friendly note" },
{ when: "3 days late", what: "A gentle nudge" },
{ when: "10 days late", what: "A firm reminder" },
];
const currencies = ["USD", "EUR", "GBP", "INR", "AUD", "SGD", "+18"];
const stages = [
{ label: "Sent · 2 Oct", done: true },
{ label: "Viewed · 3 Oct", done: true },
{ label: "Paid", done: false },
];
function Tile({ title, body, className = "", children }:
{ title: string; body: string; className?: string; children: React.ReactNode }) {
return (
<article className={"flex flex-col justify-between gap-6 overflow-hidden rounded-xl border border-border bg-surface p-6 " + className}>
<div>
<h3 className="text-base font-semibold tracking-tight text-fg">{title}</h3>
<p className="mt-1 text-sm leading-relaxed text-fg-muted">{body}</p>
</div>
{children}
</article>
);
}
export function FeatureBento() {
return (
<section aria-labelledby="bento-title" className="bg-bg font-sans">
<div className="mx-auto max-w-6xl px-4 py-20 sm:px-6">
<div className="max-w-xl">
<h2 id="bento-title" className="text-balance text-3xl font-semibold tracking-tight text-fg sm:text-4xl">One tidy place for money coming in</h2>
<p className="mt-4 text-base leading-relaxed text-fg-muted sm:text-lg">From the first invoice to the last reminder, you can see where every payment stands.</p>
</div>
<div className="mt-12 grid gap-3 md:grid-cols-6">
<Tile className="md:col-span-4" title="Know what’s coming in" body="Paid and expected income by month, so a quiet month never surprises you.">
<div aria-hidden className="flex h-32 items-end gap-2">
{months.map((x) => (
<div key={x.m} className="flex h-full flex-1 flex-col justify-end gap-1.5 text-center text-[11px] text-fg-subtle">
<span className={(x.paid ? "bg-primary" : "bg-primary-soft") + " block rounded-t-sm"} style={{ height: x.value + "%" }} />
{x.m}
</div>
))}
</div>
</Tile>
<Tile className="bg-primary-soft md:col-span-2" title="Reminders on autopilot" body="Friendly first, firm later.">
<ol className="grid gap-3 border-l border-border-strong pl-4 text-[13px]">
{reminders.map((r) => (
<li key={r.when} className="relative">
<span className="absolute -left-[21px] top-1 size-2.5 rounded-full border-2 border-primary bg-bg" />
<p className="font-medium text-fg">{r.when}</p>
<p className="text-fg-subtle">{r.what}</p>
</li>
))}
</ol>
</Tile>
<Tile className="md:col-span-2" title="Bill in 24 currencies" body="Your client pays in theirs.">
<div className="flex flex-wrap gap-1.5">
{currencies.map((c) => (
<span key={c} className="rounded border border-border bg-bg px-2 py-1 text-xs font-medium tabular-nums text-fg">{c}</span>
))}
</div>
</Tile>
<Tile className="md:col-span-4" title="Know when it’s been opened" body="See the moment a client views the invoice, and when they pay.">
<div className="grid grid-cols-3 gap-2 text-xs text-fg-muted">
{stages.map((s) => (
<div key={s.label} className="grid gap-2">
<span className={(s.done ? "bg-primary" : "bg-surface-2") + " h-1.5 rounded-full"} />
{s.label}
</div>
))}
</div>
</Tile>
</div>
</div>
</section>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.