affectUI › Components › Inputs
Billing Schedule
Build a billing phase – start date, duration, products with repeats and timing, discount, minimum and live totals.
Part of affectUI Pro. Install: npx shadcn@latest add https://www.affectui.com/r/billing-schedule.json · Import from @/components/ui/billing-schedule
When to use
- Quoting and contract tools where a phase of billing is put together – set-up fees, licences, support
- Admin screens for subscriptions with one-off and recurring charges, discounts and minimum commitments
When not to use
- A simple plan picker – use the Pricing Plans block
- Usage-based pricing with tiers per unit – this works with fixed prices per line
Usage
import { BillingSchedule } from "@/components/ui/billing-schedule";
export function NewContract() {
return (
<BillingSchedule
phase="Build-out phase"
defaultStart="2026-01-01"
onChange={(schedule) => save(schedule)}
/>
);
}Props
| Name | Type | Default | Description |
|---|---|---|---|
title | string | "Create a billing schedule" | Heading on the tray |
phase | string | "Build-out phase" | Starting phase name – editable in the summary |
currency | string | "$" | Currency symbol for prices and totals |
catalog | CatalogItem[] | Products under Add product – { name, repeat, price } | |
defaultLines | ScheduleLine[] | Lines to start with – products, a discount or a minimum | |
defaultStart | string | "2026-01-01" | Start date as yyyy-mm-dd |
onChange | (schedule) => void | Called with { phase, start, duration, lines } after every change | |
className | string | Extra class on the root |
Keyboard
- Tab: Moves through the phase name, the fields, every line and the buttons
- Enter: Confirms a price; Esc closes an open menu
Accessibility
- The lines are a table with column headers; every input and select has a label naming its line
- Duration and Add product are buttons that open listboxes; totals are announced politely
Responsive
- Fills its container up to 560px; on narrow screens the fields stack and the Repeats column hides
- Dark mode built in: switches when an ancestor (usually <html>) has the class dark or data-theme="dark"
Requirements
- React 19