Interactive preview, sandboxed: nothing you type leaves this page.
import { useId, useState } from "react";const MAX_UNITS = 2500;const START_UNITS = 800;const STEP_EVENTS = 10_000;function money(amount: number) { return new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", minimumFractionDigits: 2, maximumFractionDigits: 2, }).format(amount);}function count(value: number) { return new Intl.NumberFormat("en-US").format(value);}export default function Block() { const [units, setUnits] = useState(START_UNITS); const inputId = useId(); const events = units * STEP_EVENTS; const overageUnits = Math.max(0, units - 100); const meteredBill = overageUnits * 0.4; const committedRate = events < 5_000_000 ? 0.36 : events < 20_000_000 ? 0.32 : 0.28; const committedBill = overageUnits * committedRate; const annualTotal = committedBill * 12; const marker = (units / MAX_UNITS) * 100; return ( <section className="bg-white text-neutral-950 dark:bg-neutral-950 dark:text-neutral-50"> <div className="mx-auto max-w-6xl px-5 py-12 sm:px-8 sm:py-16 lg:px-10 lg:py-20"> <header className="mb-9 max-w-3xl sm:mb-12"> <p className="mb-3 text-xs font-bold uppercase tracking-[0.16em] text-emerald-700 dark:text-emerald-400"> Tollgate / usage pricing </p> <h1 className="text-3xl font-semibold tracking-tight sm:text-4xl"> One scale. Rates that reward volume. </h1> <p className="mt-4 max-w-2xl text-base leading-7 text-neutral-700 dark:text-neutral-300"> Compare plans against the same monthly event run rate. Move the marker to see the bill at your volume. </p> </header> <div className="overflow-hidden rounded-xl border border-neutral-200 bg-neutral-50 dark:border-neutral-800 dark:bg-neutral-900"> <div className="flex flex-wrap items-end justify-between gap-3 border-b border-neutral-200 px-5 py-4 sm:px-7 dark:border-neutral-800"> <div> <h2 className="text-sm font-semibold">Monthly event volume</h2> <p className="mt-1 text-sm text-neutral-600 dark:text-neutral-400">One shared scale ยท events per month</p> </div> <p className="text-sm font-medium tabular-nums text-neutral-700 dark:text-neutral-300">0 to 25,000,000 events</p> </div> <div className="px-5 pt-5 sm:px-7 sm:pt-6"> <div className="relative h-[214px] sm:h-[230px]" aria-label="Committed overage price schedule on a shared 0 to 25 million event scale"> <svg className="absolute inset-0 h-full w-full overflow-visible" viewBox="0 0 1000 214" preserveAspectRatio="none" role="img" aria-labelledby="schedule-title schedule-desc"> <title id="schedule-title">Committed overage rate by monthly event volume</title> <desc id="schedule-desc">The rate is 36 cents per 10,000 events below 5 million, 32 cents from 5 million to below 20 million, and 28 cents from 20 million onward. The first million events are included.</desc> <line x1="2" y1="37" x2="2" y2="174" stroke="currentColor" strokeDasharray="3 5" className="text-neutral-400 dark:text-neutral-600" /> <line x1="40" y1="65" x2="40" y2="174" stroke="currentColor" strokeDasharray="3 5" className="text-neutral-400 dark:text-neutral-600" /> <line x1="200" y1="37" x2="200" y2="174" stroke="currentColor" strokeDasharray="3 5" className="text-neutral-400 dark:text-neutral-600" /> <line x1="800" y1="37" x2="800" y2="174" stroke="currentColor" strokeDasharray="3 5" className="text-neutral-400 dark:text-neutral-600" /> <line x1="0" y1="174" x2="1000" y2="174" stroke="currentColor" className="text-neutral-400 dark:text-neutral-600" /> <path d="M40 105 H200 V137 H800 V169 H1000" fill="none" stroke="currentColor" strokeWidth="3" vectorEffect="non-scaling-stroke" className="text-emerald-700 dark:text-emerald-400" /> <line x1={marker * 10} y1="36" x2={marker * 10} y2="176" stroke="currentColor" strokeWidth="2" vectorEffect="non-scaling-stroke" className="text-emerald-700 dark:text-emerald-400" /> <circle cx={marker * 10} cy="174" r="5" fill="currentColor" className="text-emerald-700 dark:text-emerald-400" /> </svg> <div className="absolute left-0 top-0 max-w-[104px] rounded-md border border-neutral-300 bg-white px-2 py-1 text-[11px] leading-tight dark:border-neutral-700 dark:bg-neutral-950 sm:max-w-none sm:text-xs"> <span className="font-semibold">50,000</span><span className="block text-neutral-600 dark:text-neutral-400">Hobby free limit</span> </div> <div className="absolute left-[4%] top-[34px] max-w-[130px] rounded-md border border-neutral-300 bg-white px-2 py-1 text-[11px] leading-tight dark:border-neutral-700 dark:bg-neutral-950 sm:max-w-none sm:text-xs"> <span className="font-semibold">1,000,000</span><span className="block text-neutral-600 dark:text-neutral-400">Included on both paid plans</span> </div> <div className="absolute left-[46%] top-0 -translate-x-1/2 rounded-md border border-neutral-300 bg-white px-2 py-1 text-[11px] leading-tight dark:border-neutral-700 dark:bg-neutral-950 sm:left-[20%] sm:text-xs"> <span className="font-semibold">5,000,000</span><span className="block text-neutral-600 dark:text-neutral-400">Committed discount</span> </div> <div className="absolute left-[80%] top-0 -translate-x-1/2 rounded-md border border-neutral-300 bg-white px-2 py-1 text-[11px] leading-tight dark:border-neutral-700 dark:bg-neutral-950 sm:text-xs"> <span className="font-semibold">20,000,000</span><span className="block text-neutral-600 dark:text-neutral-400">Next rate break</span> </div> <div className="absolute left-[5%] top-[95px] text-xs font-semibold text-neutral-800 dark:text-neutral-200 sm:text-sm">$0.36</div> <div className="absolute left-[40%] top-[127px] text-xs font-semibold text-neutral-800 dark:text-neutral-200 sm:text-sm">$0.32</div> <div className="absolute left-[83%] top-[158px] text-xs font-semibold text-neutral-800 dark:text-neutral-200 sm:text-sm">$0.28</div> <div className="absolute bottom-0 left-0 text-[11px] text-neutral-600 dark:text-neutral-400">0</div> <div className="absolute bottom-0 left-[20%] -translate-x-1/2 text-[11px] text-neutral-600 dark:text-neutral-400">5m</div> <div className="absolute bottom-0 left-[80%] -translate-x-1/2 text-[11px] text-neutral-600 dark:text-neutral-400">20m</div> <div className="absolute bottom-0 right-0 text-[11px] text-neutral-600 dark:text-neutral-400">25m</div> </div> <div className="border-t border-neutral-200 py-5 dark:border-neutral-800"> <label htmlFor={inputId} className="flex flex-wrap items-baseline justify-between gap-x-4 gap-y-1 text-sm font-medium"> <span>Choose monthly volume</span> <span className="text-base font-semibold tabular-nums text-emerald-700 dark:text-emerald-400">{count(events)} events</span> </label> <input id={inputId} type="range" min="0" max={MAX_UNITS} step="1" value={units} onChange={(event) => setUnits(Number(event.target.value))} aria-describedby={`${inputId}-help`} className="mt-4 h-8 w-full cursor-pointer accent-emerald-700 focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-emerald-700 dark:accent-emerald-400 dark:focus-visible:outline-emerald-400" /> <div id={`${inputId}-help`} className="flex justify-between text-xs tabular-nums text-neutral-600 dark:text-neutral-400"> <span>0</span><span>25,000,000 events</span> </div> </div> </div> <div className="grid border-t border-neutral-200 dark:border-neutral-800 md:grid-cols-[1fr_1fr_1.2fr]"> <article className="border-b border-neutral-200 p-5 sm:p-7 md:border-b-0 md:border-r dark:border-neutral-800"> <p className="text-xs font-bold uppercase tracking-wider text-neutral-600 dark:text-neutral-400">Hobby</p> <p className="mt-3 text-lg font-semibold">$0 through 50,000</p> <p className="mt-2 text-sm leading-6 text-neutral-700 dark:text-neutral-300">A free monthly allowance for getting started.</p> </article> <article className="border-b border-neutral-200 p-5 sm:p-7 md:border-b-0 md:border-r dark:border-neutral-800"> <p className="text-xs font-bold uppercase tracking-wider text-neutral-600 dark:text-neutral-400">Metered</p> <p className="mt-3 text-lg font-semibold tabular-nums" aria-live="polite">{money(meteredBill)}<span className="text-sm font-normal text-neutral-600 dark:text-neutral-400"> / month</span></p> <p className="mt-2 text-sm leading-6 text-neutral-700 dark:text-neutral-300">First 1,000,000 included, then $0.40 per additional 10,000 events.</p> </article> <article className="p-5 sm:p-7"> <p className="text-xs font-bold uppercase tracking-wider text-neutral-600 dark:text-neutral-400">Committed <span className="normal-case tracking-normal">ยท annual, billed monthly</span></p> <p className="mt-3 text-lg font-semibold tabular-nums" aria-live="polite">{money(committedBill)}<span className="text-sm font-normal text-neutral-600 dark:text-neutral-400"> / month</span></p> <p className="mt-1 text-sm text-neutral-700 dark:text-neutral-300">{money(annualTotal)} over 12 months at this monthly run rate.</p> <p className="mt-3 text-sm leading-6 text-neutral-700 dark:text-neutral-300">First 1,000,000 included. Overage: <span className="font-semibold tabular-nums text-neutral-950 dark:text-neutral-50">$0.36</span> below 5m, <span className="font-semibold tabular-nums text-neutral-950 dark:text-neutral-50">$0.32</span> from 5m, and <span className="font-semibold tabular-nums text-neutral-950 dark:text-neutral-50">$0.28</span> from 20m per 10,000 events.</p> </article> </div> </div> <p className="mt-4 max-w-4xl text-xs leading-5 text-neutral-600 dark:text-neutral-400"> Estimates use 10,000-event billing increments. The Committed rate is selected by monthly run rate and applies to all overage units; the selected volume is held constant for the 12-month term. Hobby is free through its stated limit; no Hobby overage rate is shown. </p> </div> </section> );}