| Field | Value |
|---|
| ID | FRD-044 |
| Owner | David Holmes |
| Status | Draft |
| Priority | P1 — Recipes |
| Size | M (Recipe) |
| Target Release | v2.0.0 |
| Last Updated | 2026-05-26 |
| Related | ADR-027 (Default Tech Stack) |
Document Summary
Create an MDX recipe in Storybook that teaches developers how to compose a Billing page using design system components. The recipe references existing components (usage-meter-panel.tsx, billing-history-table.tsx) alongside plan-picker and payment-form patterns, and covers renewal warnings, failed-payment states, usage tracking, and billing history. It provides copy-pasteable code for a realistic SaaS billing page.
Introduction
Overview
Billing pages are critical SaaS infrastructure — they handle plan selection, usage visibility, payment management, and invoice history. These pages have unique state complexity: renewal warnings, failed payment recovery flows, usage limit thresholds, and plan comparison. Without a canonical recipe, developers either build incomplete billing experiences or spend excessive time figuring out the correct component composition and state handling.
Goals
- Provide a single MDX recipe showing the complete Billing page composition pattern.
- Reference and integrate existing components:
usage-meter-panel.tsx and billing-history-table.tsx.
- Show plan-picker composition with current plan highlight, upgrade/downgrade flows, and feature comparison.
- Show payment form integration points (card on file, update payment method).
- Cover renewal warning states (upcoming renewal, payment method expiring, grace period).
- Cover failed-payment states (past due, payment retry, account suspension warning).
- Include usage meter visualization with threshold warnings.
Non-Goals
- Implementing Stripe or other payment provider integration.
- Building a pricing page (public-facing plan comparison is a different pattern).
- Handling proration calculation logic.
- Multi-currency support details.
Scope
In Scope
| Item | Description |
|---|
| MDX recipe page | src/docs/recipes/billing-page.mdx with Storybook sidebar entry |
| Plan picker section | Current plan display, available plans comparison, upgrade/downgrade CTAs |
| Usage meter section | Integration with usage-meter-panel.tsx, threshold warnings, overage indicators |
| Billing history section | Integration with billing-history-table.tsx, invoice download links, status badges |
| Payment method section | Card on file display, update payment method dialog |
| Renewal warnings | Upcoming renewal banner, expiring card warning, grace period alert |
| Failed payment states | Past due alert, retry payment CTA, account suspension warning |
| Overview page update | Add Billing recipe to src/docs/recipes/00-overview.mdx |
Out of Scope
| Item | Reason |
|---|
| Payment provider SDK integration | Vendor-specific; recipe shows the UI composition only |
| Tax calculation and display | Backend concern; recipe shows placeholder tax line items |
| Plan creation/management admin UI | Admin-side billing is a different pattern |
| Subscription lifecycle webhooks | Backend infrastructure, not frontend composition |
Users and Pain Points
| User | Pain Point |
|---|
| Application developer | No reference for how to compose a billing page from design system components |
| Application developer | Unclear how to show failed payment recovery flow — what states exist and what actions to offer |
| Application developer | Usage meters need threshold warnings but no pattern shows how to wire them |
| Application developer | Renewal warnings have multiple severity levels — no guidance on which alert variant to use |
| Product manager | Inconsistent billing UX across products leads to support tickets |
Definitions
| Term | Definition |
|---|
| Plan picker | A UI section showing available subscription plans with comparison and selection |
| Usage meter | A visual indicator of resource consumption against a plan limit |
| Renewal warning | An alert shown before a subscription renews, especially when action is needed |
| Failed payment | A state where the most recent payment attempt was declined or errored |
| Grace period | A time window after a failed payment before service is suspended |
Current State
usage-meter-panel.tsx and billing-history-table.tsx are referenced in the roadmap as existing components to integrate.
- The recipes overview lists billing-related patterns as planned.
- Components available for composition: Alert, Badge, Button, Card, DataGrid (for billing history), Dialog, ProgressBar (for usage meters), Toast.
- No recipe MDX file exists yet.
Proposed Solution
Create src/docs/recipes/billing-page.mdx with the following structure:
- Introduction — What this recipe builds, when to use it, when not to use it.
- Component inventory — Table listing all components with links, noting
usage-meter-panel and billing-history-table as primary compositions.
- Page layout — Overall billing page structure with sections.
- Current plan and plan picker — Display current plan details, show available plans in a comparison layout, upgrade/downgrade CTAs with confirmation dialog.
- Usage meters —
usage-meter-panel integration showing current usage, limits, threshold warnings (80%, 90%, 100%), and overage state.
- Payment method — Card on file display (masked number, expiry), update payment method CTA opening a dialog.
- Billing history —
billing-history-table integration showing invoices, status badges (Paid, Pending, Failed, Refunded), download links.
- Renewal warnings — Alert variants for upcoming renewal (info), expiring payment method (warning), grace period (destructive).
- Failed payment recovery — Alert with retry CTA, update payment method link, account status messaging.
- Full composition — Complete code block.
Requirements
| ID | Requirement | Priority |
|---|
| REQ-01 | Recipe is a single MDX file in src/docs/recipes/ | Must |
| REQ-02 | Recipe integrates usage-meter-panel.tsx | Must |
| REQ-03 | Recipe integrates billing-history-table.tsx | Must |
| REQ-04 | Recipe shows plan picker with current plan and upgrade flow | Must |
| REQ-05 | Recipe shows renewal warning states (info, warning, destructive) | Must |
| REQ-06 | Recipe shows failed payment recovery flow | Must |
| REQ-07 | All code blocks are copy-pasteable and self-contained | Must |
| REQ-08 | Recipe shows payment method display and update flow | Should |
| REQ-09 | Recipe documents usage threshold warning levels | Should |
Functional Requirements
| ID | Description | Acceptance |
|---|
| FR-01 | MDX file renders in Storybook without errors | pnpm build-storybook succeeds |
| FR-02 | All code blocks compile when extracted | Manual verification |
| FR-03 | Renewal warning shows correct Alert variant per severity | Code example demonstrates info/warning/destructive |
| FR-04 | Failed payment state shows retry and update-payment actions | Code example includes both CTAs |
| FR-05 | Usage meter shows threshold-based color changes | Code example demonstrates 80/90/100% thresholds |
Non-Functional Requirements
| ID | Description | Target |
|---|
| NFR-01 | Recipe page load time | Under 2 seconds |
| NFR-02 | Individual code block line count | Under 80 lines per block |
| NFR-03 | Recipe covers the most common billing states without being exhaustive | 80/20 rule — cover 80% of use cases |
API/Interface Requirements
| Interface | Requirement |
|---|
| MDX file | Must use “ |
usage-meter-panel | Recipe must show its props interface and usage pattern |
billing-history-table | Recipe must show its data shape and column configuration |
| Payment form | Recipe shows the integration point (dialog shell) without provider-specific code |
Accessibility Requirements
| ID | Requirement |
|---|
| A11Y-01 | Usage meters must have text alternatives — screen readers must hear the percentage and limit, not just see the visual bar |
| A11Y-02 | Renewal and failed payment alerts must use role="alert" for screen reader announcement |
| A11Y-03 | Plan picker must be keyboard-navigable with clear focus indicators |
| A11Y-04 | Invoice download links must include the invoice date/number in their accessible name |
Content and Documentation Requirements
| ID | Requirement |
|---|
| DOC-01 | Update src/docs/recipes/00-overview.mdx to add Billing recipe |
| DOC-02 | Document the state machine for payment status (Active, Past Due, Grace Period, Suspended) |
| DOC-03 | Include a “Which alert variant to use” decision table for billing states |
Dependencies
| Dependency | Type | Risk |
|---|
usage-meter-panel.tsx | Internal | Must exist and be stable before recipe references it |
billing-history-table.tsx | Internal | Must exist and be stable before recipe references it |
| Alert component | Internal | Must support info, warning, and destructive variants |
| Card component | Internal | Used for plan picker cards |
| ProgressBar component | Internal | Used within usage meter for visual fill |
Risks and Tradeoffs
| Risk | Impact | Mitigation |
|---|
usage-meter-panel and billing-history-table may not exist yet | Recipe references non-existent components | Verify component existence before authoring; create stubs if needed |
| Payment form integration is provider-specific | Recipe cannot show a working payment form | Show the dialog shell and note where provider SDK integration goes |
| Billing state complexity is high | Recipe may be too long | Focus on the 4 most common states; link to a “Billing States Reference” for edge cases |
Open Questions
| # | Question | Status |
|---|
| 1 | Do usage-meter-panel.tsx and billing-history-table.tsx currently exist in the codebase? | Open — need to verify or create |
| 2 | Should the recipe show a Stripe Elements integration example as an optional section? | Open |
| 3 | Should plan comparison use a ComparisonTable or custom Card layout? | Open |
| 4 | Should the recipe cover annual vs. monthly billing toggle? | Open |
Acceptance Criteria
LLM Handoff Instructions
When an LLM agent picks up this FRD:
- Read
src/docs/recipes/00-overview.mdx for recipe conventions.
- Search for
usage-meter-panel.tsx and billing-history-table.tsx in the codebase. If they exist, read their props interfaces. If not, check if they need to be created first (separate FRD).
- Read component source for: Alert, Badge, Button, Card, Dialog, ProgressBar, Toast, ComparisonTable.
- Create
src/docs/recipes/billing-page.mdx with the section structure from the Proposed Solution.
- Sample data: “Pro Plan” subscription at $49/month, usage of API calls (8,500/10,000), storage (7.2GB/10GB), team members (4/5). Billing history with 6 months of invoices.
- State scenarios to cover: Active + healthy, Renewal upcoming (7 days), Payment method expiring, Failed payment (past due), Grace period, Usage at 90%.
- All code blocks must use public package import paths.
- After creating, run
pnpm build-storybook to verify.
- Update
src/docs/recipes/00-overview.mdx.
Decision Log
| Date | Decision | Rationale |
|---|
| 2026-05-26 | Reference existing usage-meter-panel and billing-history-table rather than inlining | These are reusable compositions that belong as components, not recipe-only code |
| 2026-05-26 | Show payment form as a dialog shell without provider SDK code | Provider integration varies; recipe focuses on the UI composition |
Document History
| Date | Version | Author | Changes |
|---|
| 2026-05-26 | 0.1 | David Holmes | Initial draft |