Skip to content
All Taste components

Pricing

Pricing — usage-based with slider

A volume slider with a live estimate on one side and the per-unit rate bands on the other.

volume slider · monthly estimate · rate bands · current band highlighted

Usage pricing

Only pay for the invoices you send

No seats and no tiers. The more you send, the less each one costs.

Invoices a month2,000
Estimated monthly cost
$30.00≈ 1.5¢ per invoice
Start sending

Billed at the end of each month for what you actually sent. Nothing to buy up front.

Rate per invoice

First 250
Free
251 – 1,000
2.0¢
1,001 – 5,000
1.5¢
Over 5,000
Talk to us

Payments are charged at the card network’s rate, with nothing added by us.

"use client";
import { useId, useState } from "react";
import { cn } from "@/lib/utils";

const bands = [
  { label: "First 250", upTo: 250, cents: 0 },
  { label: "251 – 1,000", upTo: 1000, cents: 2 },
  { label: "1,001 – 5,000", upTo: 5000, cents: 1.5 },
];

function estimate(volume: number) {
  let cost = 0;
  let from = 0;
  for (const band of bands) {
    const inBand = Math.max(0, Math.min(volume, band.upTo) - from);
    cost += (inBand * band.cents) / 100;
    from = band.upTo;
  }
  return cost;
}

export function PricingUsage() {
  const [volume, setVolume] = useState(2000);
  const id = useId();
  const cost = estimate(volume);
  const active = bands.findIndex((b) => volume <= b.upTo);
  const perInvoice = volume ? (cost / volume) * 100 : 0;

  return (
    <section aria-labelledby="pricing-usage-title" className="bg-surface px-5 py-16 font-sans sm:px-10 sm:py-20">
      <div className="mx-auto max-w-6xl">
        <div className="max-w-2xl">
          <p className="text-[13px] font-medium text-primary">Usage pricing</p>
          <h2 id="pricing-usage-title" className="mt-3 text-balance text-3xl font-semibold tracking-tight text-fg sm:text-4xl">Only pay for the invoices you send</h2>
          <p className="mt-4 text-base text-fg-muted sm:text-lg">No seats and no tiers. The more you send, the less each one costs.</p>
        </div>

        <div className="mt-10 grid overflow-hidden rounded-xl border border-border bg-bg md:grid-cols-[1.45fr_1fr]">
          <div className="grid content-start gap-7 p-7 md:p-10">
            <div className="grid gap-3.5">
              <div className="flex items-baseline justify-between gap-4">
                <label htmlFor={id} className="text-[13px] font-medium text-fg">Invoices a month</label>
                <output htmlFor={id} className="text-2xl font-semibold tabular-nums text-fg">{volume.toLocaleString()}</output>
              </div>
              <input
                id={id}
                type="range"
                min={0}
                max={5000}
                step={50}
                value={volume}
                onChange={(e) => setVolume(Number(e.target.value))}
                className="h-1.5 w-full cursor-pointer appearance-none rounded-full bg-surface-2 accent-primary"
              />
              <div className="flex justify-between text-xs tabular-nums text-fg-subtle" aria-hidden>
                <span>0</span><span>1k</span><span>2.5k</span><span>5k+</span>
              </div>
            </div>
            <div className="flex flex-wrap items-center justify-between gap-4 rounded-lg bg-surface p-5">
              <div>
                <p className="text-[13px] text-fg-subtle">Estimated monthly cost</p>
                <p className="flex flex-wrap items-baseline gap-x-2">
                  <span className="text-4xl font-semibold tracking-tight tabular-nums text-fg">{"$" + cost.toFixed(2)}</span>
                  <span className="text-[13px] text-fg-subtle">{"≈ " + perInvoice.toFixed(1) + "¢ per invoice"}</span>
                </p>
              </div>
              <a href="/signup" className="inline-flex h-11 items-center rounded bg-primary px-5 text-[15px] font-medium text-primary-fg transition hover:bg-primary-hover">Start sending</a>
            </div>
            <p className="text-[13px] text-fg-subtle">Billed at the end of each month for what you actually sent. Nothing to buy up front.</p>
          </div>

          <div className="grid content-start gap-4 border-t border-border bg-surface p-7 md:border-l md:border-t-0 md:p-10">
            <h3 className="text-base font-semibold text-fg">Rate per invoice</h3>
            <dl className="divide-y divide-border">
              {bands.map((b, i) => (
                <div key={b.label} className={cn("flex justify-between gap-3 py-3 text-[13.5px]", i === active ? "font-medium text-fg" : "text-fg-muted")}>
                  <dt>{b.label}</dt>
                  <dd className="tabular-nums">{b.cents ? b.cents + "¢" : "Free"}</dd>
                </div>
              ))}
              <div className="flex justify-between gap-3 py-3 text-[13.5px] text-fg-muted">
                <dt>Over 5,000</dt>
                <dd><a href="/contact" className="font-medium text-primary hover:underline">Talk to us</a></dd>
              </div>
            </dl>
            <p className="text-[13px] text-fg-subtle">Payments are charged at the card network’s rate, with nothing added by us.</p>
          </div>
        </div>
      </div>
    </section>
  );
}

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