ComplianceCalendar
Filing deadlines by jurisdiction, with the owner and the date penalties start.
npx shadcn add @lopifi/compliance-calendarExamples
The same component, case by case. Each stage is the shipped code with the props it shows; switch to Code for the usage.
How it behaves
What it renders, what it refuses to render, and why. The same paragraphs as the family spec, so the two can’t disagree.
Every filing the entity owes: obligation, form, jurisdiction and agency, the period covered, the due date, the owner, the status, and the date penalties start. Two views: upcoming puts open filings soonest first, so past-due ones sit at the top and filed ones go last, and month groups every filing under the month its governing date falls in.
Filing calendar Northwind Ltd · as of 18 Oct 2026
1 past due · 1 due soon · 1 without an owner
─ Open ───────────────────────────────────────────────────── 5 filings
15 Oct Payroll tax deposit [Late]
3 days Federal · IRS · September 2026 · A. Whitfield Penalties from 16 Oct 2026
past due
Status is supplied, not derived. upcoming | due-soon | filed | late | extended. Whether a return is "due soon" depends on business days, holidays and the team's own lead time, and the consumer knows those; the component does not. It does compute the day count from asOf, by calendar date, so a clock time never makes a return late.
An extension moves the filing date, and only that. The row then shows the extended date, the original date beneath it, and, when the consumer supplies a separate paymentDueDate, the payment date too, because an extension to file isn't always an extension to pay.
Refuses to render: a penalty date nobody stated as "no penalty". A null penalty date prints "Penalty date not stated". A null owner prints "Unassigned" in the warning tone and is counted in the header. It's an action, not a blank.
Edge cases: no obligations at all says so and asks whether the registrations behind it are complete, because an empty calendar is a claim. A filing with no form name shows the obligation alone. A filed row shows the filing date and the agency's confirmation number.
Accessibility: each group is a labeled section holding an ordered list. Status is an icon plus a word. The past-due day count carries weight as well as color, so it reads in grayscale.
The accounting it encodes
The concepts this component renders, each defined once in the lexicon.
More in Tax & compliance
See also
Where this component is specified, defined and running.
Elsewhere in the system
The live section ComplianceCalendar renders in, the calculators behind its figures, and the ledger payloads that feed it.
- ComplianceCalendar, runningThe compliance showcase — live, with theme, density, grayscale and reduced-motion switches.
- Tax & complianceControlTestResult sits beside them and speaks their idiom. Every component in this family takes an explicit asOf. "Today" is never the client clock, so a server render, a printed copy and a screenshot agree on what is late. Shared types live in src/ledger/lib/compliance.types.ts; the tax-ID checks l
Components are copied into your repository and meant to be edited. Rounding policy, fiscal calendar and compliance copy differ per company.
Release notes
Get an email when Tax & compliance changes
Your copy doesn’t update itself when we fix something here.
- One email when a Tax & compliance component needs a migration
- Nothing when nothing changes
Or install it now
npx shadcn add @lopifi/compliance-calendar