Skip to main content
All components are exported from @nozle-js/react and use --nozle-* CSS custom properties for theming. They work with any design system — just set the CSS variables on a parent element or :root.
Components that make API calls (CheckoutButton, UpgradeButton, CreditTopUpButton) must be wrapped in a BillingPortalProvider. Components that read subscription data (CurrentPlan, CreditBalance, CreditHistory, InvoiceList) require a BillingProvider ancestor.

Pricing Components

PricingTable

Renders plan cards in a responsive grid with a monthly/annual toggle. Auto-fetches plans from the API when no plans prop is provided, and auto-detects the current plan when customerId is set.
import { PricingTable } from '@nozle-js/react';

// Auto-fetch plans from API, auto-detect current plan
<PricingTable
  customerId="cust_123"
  highlightPlan="pro"
  onSelect={(plan) => handleUpgrade(plan)}
/>

// Or pass plans explicitly
<PricingTable
  plans={[
    { code: 'starter', name: 'Starter', amount_cents: 2900, amount_currency: 'USD', interval: 'monthly' },
    { code: 'pro', name: 'Pro', amount_cents: 9900, amount_currency: 'USD', interval: 'monthly', description: 'Most popular' },
  ]}
  features={[
    ['10K API calls', 'Email support'],
    ['100K API calls', 'Priority support', 'Analytics'],
  ]}
  currentPlanCode="starter"
  highlightPlan="pro"
  onSelect={(plan) => console.log('Selected:', plan.code)}
  showToggle={true}
  enterpriseEmail="sales@example.com"
  className="my-pricing"
/>;
PropTypeDefaultDescription
customerIdstringCustomer ID for auto-detecting current plan via API
currentPlanCodestringExplicitly set current plan (overrides auto-detect)
plansPricingPlan[]Plans to display (auto-fetched from /api/v1/plans if omitted)
featuresstring[][]Feature lists per plan (index-matched to plans array)
onSelect(plan: PricingPlan) => voidCalled when a plan’s CTA is clicked
highlightPlanstringPlan code to highlight as “Most Popular”
enterpriseEmailstringEmail for enterprise plan “Contact Sales” mailto link
showTogglebooleantrueShow monthly/annual toggle (only renders when annual plans exist)
classNamestringCSS class for the outer wrapper

PricingPlan type

FieldTypeRequiredDescription
codestringYesUnique plan identifier (matches plan code from API)
namestringYesDisplay name
amount_centsnumberYesPrice in cents
amount_currencystringYesCurrency code (USD, EUR, GBP, JPY)
intervalstringYesBilling interval (monthly or yearly)
descriptionstringNoSubtitle below the plan name

CSS Variable Theming

PricingTable uses CSS custom properties for full theming control. Component-specific variables fall back to global Nozle variables, which fall back to sensible defaults:
:root {
  /* Component-specific (highest priority) */
  --nozle-pricing-bg: #ffffff;
  --nozle-pricing-card-bg: #ffffff;
  --nozle-pricing-highlight: #6366f1;
  --nozle-pricing-border: #e5e7eb;
  --nozle-pricing-radius: 12px;

  /* Global Nozle variables (fallbacks) */
  --nozle-background: #ffffff;
  --nozle-card: #ffffff;
  --nozle-primary: #6366f1;
  --nozle-border: #e5e7eb;
  --nozle-radius: 12px;
  --nozle-foreground: #111827;
  --nozle-muted-foreground: #6b7280;
  --nozle-muted: #f3f4f6;
  --nozle-primary-foreground: #ffffff;
}

PlanCard

Individual pricing plan card. Used internally by PricingTable, but can be rendered standalone for custom layouts.
import { PlanCard } from '@nozle-js/react';

<PlanCard
  id="pro"
  name="Pro"
  monthlyPrice={99}
  annualPrice={990}
  features={['100K API calls', 'Priority support', 'Analytics']}
  isAnnual={false}
  isCurrent={false}
  onSelect={() => handleUpgrade('pro')}
/>;
PropTypeDefaultDescription
...PlanPlanAll fields from the Plan type (see above)
isAnnualbooleanWhether to show annual or monthly price
isCurrentbooleanHighlights card border and disables CTA
onSelect() => voidClick handler for the CTA button
childrenReactNodeCustom content below the features list

PlanComparison

Side-by-side feature comparison table. Boolean values render as check/cross icons; strings render as text.
import { PlanComparison } from '@nozle-js/react';

<PlanComparison
  plans={plans}
  features={[
    { key: 'api_calls', label: 'API Calls', values: { starter: '10K', pro: '100K' } },
    { key: 'analytics', label: 'Analytics', values: { starter: false, pro: true } },
    { key: 'support', label: 'Priority Support', values: { starter: false, pro: true } },
  ]}
/>;
PropTypeDefaultDescription
plansPlan[]Plans used as column headers
featuresComparisonFeature[]Rows in the comparison table

ComparisonFeature type

FieldTypeDescription
keystringUnique row identifier
labelstringHuman-readable feature name
valuesRecord<string, string | boolean>Map of plan.id to value. Booleans render as check/cross icons.

PlanBadge

Inline badge displaying the plan name with tier-based coloring.
import { PlanBadge } from '@nozle-js/react';

<PlanBadge plan="Pro" tier="pro" />
<PlanBadge plan="Free" tier="free" />
<PlanBadge plan="Enterprise" tier="enterprise" />
PropTypeDefaultDescription
planstringText displayed inside the badge
tier'free' | 'starter' | 'pro' | 'enterprise''free'Controls background and text color

Checkout and Billing Actions

CheckoutButton

Initiates a checkout session and routes to the appropriate payment processor. Supports Stripe (hosted redirect and embedded Elements) and Razorpay. Must be used inside a BillingPortalProvider.
import { CheckoutButton } from '@nozle-js/react';

// Stripe hosted checkout (redirect)
<CheckoutButton
  planId="pro_monthly"
  label="Subscribe"
  onError={(err) => console.error(err)}
/>

// Stripe embedded checkout
<CheckoutButton
  planId="pro_monthly"
  onStripeClientSecret={(secret) => setClientSecret(secret)}
/>

// Razorpay checkout
<CheckoutButton
  planId="pro_monthly"
  razorpayKeyId="rzp_live_xxx"
  onSuccess={(paymentId) => console.log('Paid:', paymentId)}
/>
PropTypeDefaultDescription
planIdstringPlan to check out
labelstring'Get Started'Button text
apiBaseUrlstring'https://api.nozle.app'API base URL
classNamestringCSS class for the button
styleReact.CSSPropertiesInline styles
onError(error: Error) => voidCalled on checkout failure
razorpayKeyIdstringRazorpay key_id (required for Razorpay path)
onStripeClientSecret(clientSecret: string) => voidCalled with the Stripe client secret for embedded Elements
onSuccess(paymentId: string) => voidCalled with Razorpay payment ID on success

Checkout

Stripe Elements drop-in checkout form. Mount this after receiving a clientSecret from CheckoutButton or your own backend. Requires @stripe/react-stripe-js and @stripe/stripe-js as peer dependencies.
import { Checkout } from '@nozle-js/react';

<Checkout
  clientSecret="pi_xxx_secret_xxx"
  publishableKey="pk_live_xxx"
  submitLabel="Pay now"
  onSuccess={(paymentIntentId) => router.push('/success')}
  onError={(err) => toast.error(err.message)}
  onReady={() => setLoading(false)}
/>
PropTypeDefaultDescription
clientSecretstringStripe PaymentIntent client secret
publishableKeystringStripe publishable key
stripeAccountstringStripe Connect account ID
submitLabelstring'Pay now'Text on the submit button
onSuccess(paymentIntentId: string) => voidCalled when payment succeeds without redirect
onError(error: Error) => voidCalled on payment failure
onReady() => voidCalled when the PaymentElement becomes interactive
classNamestringCSS class for the outer wrapper
styleReact.CSSPropertiesInline styles for the outer wrapper
The useCheckout hook is available inside the Checkout tree for programmatic control:
import { useCheckout } from '@nozle-js/react';

function CustomSubmit() {
  const { confirmPayment, isProcessing, error } = useCheckout();
  return <button onClick={confirmPayment} disabled={isProcessing}>Pay</button>;
}

UpgradeButton

Opens an UpgradeModal with a live proration preview. Must be used inside a BillingPortalProvider.
import { UpgradeButton } from '@nozle-js/react';

<UpgradeButton
  targetPlanId="pro_monthly"
  label="Upgrade to Pro"
  onUpgraded={() => router.refresh()}
/>
PropTypeDefaultDescription
targetPlanIdstringPlan the customer is upgrading to
labelstring'Upgrade'Button text
apiBaseUrlstring'https://api.nozle.app'API base URL
classNamestringCSS class for the button
styleReact.CSSPropertiesInline styles
onUpgraded() => voidCalled after the upgrade is confirmed

UpgradeModal

Modal dialog showing a proration preview before confirming a plan change. Fetches preview from POST /api/v1/subscriptions/preview and confirms via POST /api/v1/subscriptions/change. Displays: credit from current plan, new plan charge, net amount due today, and next billing date.
import { UpgradeModal } from '@nozle-js/react';

<UpgradeModal
  isOpen={showModal}
  targetPlanId="pro_monthly"
  customerId="cus_xxx"
  apiBaseUrl="https://api.nozle.app"
  apiKey="pk_xxx"
  onConfirm={() => setShowModal(false)}
  onCancel={() => setShowModal(false)}
/>
PropTypeDefaultDescription
isOpenbooleanControls modal visibility
targetPlanIdstringPlan the customer is upgrading to
customerIdstringCustomer identifier
apiBaseUrlstring'https://api.nozle.app'API base URL
apiKeystring''API key for authorization
onConfirm() => voidCalled after successful upgrade
onCancel() => voidCalled when the user dismisses the modal

ProrationPreview type

FieldTypeDescription
creditnumberCredit from the remaining time on the current plan
debitnumberCharge for the new plan
netnumberAmount due today (debit - credit)
nextBillingDatestringISO date string of the next billing cycle

CreditTopUpButton

Opens a dialog for purchasing credits. Displays preset amounts (10,10, 25, 50,50, 100, $250) with an optional custom amount input. Must be used inside a BillingPortalProvider.
import { CreditTopUpButton } from '@nozle-js/react';

<CreditTopUpButton
  label="Add Credits"
  onSuccess={(amount) => toast.success(`Added $${amount} in credits`)}
  onError={(err) => toast.error(err.message)}
/>
PropTypeDefaultDescription
labelstring'Add Credits'Button text
apiBaseUrlstring'https://api.nozle.app'API base URL
classNamestringCSS class for the button
styleReact.CSSPropertiesInline styles
onSuccess(amount: number) => voidCalled with the purchased amount
onError(error: Error) => voidCalled on purchase failure

CancelSubscriptionButton

Two-step cancellation flow. Step 1 shows a confirmation dialog. Step 2 presents a reason survey with five options: Too expensive, Missing features, Switching to competitor, Not using it enough, and Other (with free-text input). Submits DELETE /api/v1/subscriptions/{id} with the selected reason.
import { CancelSubscriptionButton } from '@nozle-js/react';

<CancelSubscriptionButton
  subscriptionId="sub_xxx"
  onCancelled={() => router.push('/goodbye')}
/>
PropTypeDefaultDescription
subscriptionIdstringSubscription to cancel
onCancelled() => voidCalled after the cancellation completes
The exported CANCEL_REASONS constant contains the five reason strings if you need them elsewhere:
import { CANCEL_REASONS } from '@nozle-js/react';
// ["Too expensive", "Missing features", "Switching to competitor", "Not using it enough", "Other"]

Billing Portal Components

BillingPortalProvider

Context wrapper that provides { customerId, apiKey } to all nested SDK components. Required by CheckoutButton, UpgradeButton, and CreditTopUpButton.
import { BillingPortalProvider } from '@nozle-js/react';

<BillingPortalProvider customerId="cus_xxx" apiKey="pk_xxx">
  <PricingTable plans={plans} />
  <CheckoutButton planId="pro" />
</BillingPortalProvider>
PropTypeDefaultDescription
customerIdstringCustomer identifier passed to all child components
apiKeystringPublishable API key (pk_ prefix)
childrenReactNodeChild components
Access the context directly with the useBillingPortal hook:
import { useBillingPortal } from '@nozle-js/react';

const { customerId, apiKey } = useBillingPortal();

BillingPortal

Aggregated portal view that composes CurrentPlan, UsageDashboard, InvoiceList, and CreditBalance into a single vertical layout.
import { BillingPortal } from '@nozle-js/react';

<BillingPortal
  customerId="cus_xxx"
  usageFeatures={[
    { key: 'api_calls', label: 'API Calls', used: 8200, limit: 10000 },
    { key: 'storage', label: 'Storage (GB)', used: 3, limit: 10 },
  ]}
  onChangePlan={() => router.push('/plans')}
/>
PropTypeDefaultDescription
customerIdstringCustomer identifier
usageFeaturesUsageDashboardFeature[]Usage data passed to the embedded UsageDashboard
usageLoadingbooleanfalseShows skeleton placeholders for the usage section
onChangePlan() => voidCalled when the “Change Plan” button is clicked
subscriptionIdstringSubscription ID for the cancel button
onCancelled() => voidCalled after subscription cancellation

CurrentPlan

Displays the customer’s active subscription: plan name (with PlanBadge), billing interval, status, and next billing date. Fetches from GET /api/v1/subscriptions/current.
import { CurrentPlan } from '@nozle-js/react';

<CurrentPlan
  customerId="cus_xxx"
  onChangePlan={() => router.push('/plans')}
/>
PropTypeDefaultDescription
customerIdstringCustomer identifier
onChangePlan() => voidCallback for the “Change Plan” button. If omitted, navigates to changePlanHref.
changePlanHrefstring'/plans'Fallback URL when onChangePlan is not provided

CurrentPlanData type

FieldTypeDescription
idstringSubscription ID
planNamestringDisplay name of the plan
intervalstringBilling interval (e.g., “monthly”, “annual”)
statusstringSubscription status (e.g., “active”, “canceled”)
nextBillingDatestringISO date of next charge
tier'free' | 'starter' | 'pro' | 'enterprise'Controls badge styling

CreditBalance

Displays the customer’s current credit balance. Uses the useCredits hook internally.
import { CreditBalance } from '@nozle-js/react';

<CreditBalance customerId="cus_xxx" currency="USD" />
PropTypeDefaultDescription
customerIdstringCustomer identifier
currencystring'USD'Currency code for formatting (e.g., 'EUR', 'GBP')

CreditHistory

Renders a table of credit transactions sorted newest-first. Shows up to 20 rows with a “View all” link when there are more.
import { CreditHistory } from '@nozle-js/react';

<CreditHistory
  customerId="cus_xxx"
  viewAllHref="/billing/credits"
/>
PropTypeDefaultDescription
customerIdstringCustomer identifier
viewAllHrefstring'/billing/credits'Link target for “View all” when there are more than 20 transactions

CreditTransaction type

FieldTypeDescription
idstringTransaction ID
amountnumberCredit amount
typestringOne of 'grant', 'deduct', 'purchase', 'application'
descriptionstringHuman-readable description
createdAtstringISO timestamp

InvoiceList

Displays customer invoices in a table with status badges and PDF download links. Fetches from GET /api/v1/invoices.
import { InvoiceList } from '@nozle-js/react';

<InvoiceList customerId="cus_xxx" />
PropTypeDefaultDescription
customerIdstringCustomer identifier

Invoice type

FieldTypeDescription
idstringInvoice ID
numberstringInvoice number (e.g., INV-001)
datestringISO date string
amountnumberAmount in cents
currencystringCurrency code
status'draft' | 'open' | 'paid' | 'void' | 'uncollectible'Invoice status
pdf_urlstringURL to download the invoice PDF

PaymentMethodDisplay

Shows the customer’s saved payment method (card brand, last 4 digits, expiry) with an “Update Payment Method” button.
import { PaymentMethodDisplay } from '@nozle-js/react';

<PaymentMethodDisplay
  paymentMethod={{
    brand: 'visa',
    last4: '4242',
    expMonth: 12,
    expYear: 2027,
  }}
  onUpdatePaymentMethod={() => setShowCheckout(true)}
/>
PropTypeDefaultDescription
paymentMethodPaymentMethodCard details to display. Shows “No payment method on file.” when undefined.
onUpdatePaymentMethod() => voidClick handler for the update button. If omitted, navigates to updateHref.
updateHrefstring'/billing/update-payment'Fallback URL when onUpdatePaymentMethod is not provided

PaymentMethod type

FieldTypeDescription
last4stringLast 4 digits of the card
brandstringCard brand (visa, mastercard, amex, discover, jcb, diners, unionpay)
expMonthnumberExpiration month (1-12)
expYearnumberExpiration year (4-digit)

Usage Components

UsageMeter

Progress bar with automatic color thresholds based on usage percentage.
PercentageColor zone
< 80%Primary (normal)
80 — 94%Warning (amber)
>= 95%Destructive (red)
import { UsageMeter } from '@nozle-js/react';

<UsageMeter used={8200} limit={10000} label="API Calls" />
<UsageMeter used={9800} limit={10000} label="API Calls" showText={false} />
PropTypeDefaultDescription
usednumberCurrent usage count
limitnumberMaximum allowed usage
labelstringLabel shown above the progress bar
showTextbooleantrueWhether to display the “used / limit” text
The getUsageMeterColor helper is also exported for use in custom components:
import { getUsageMeterColor } from '@nozle-js/react';

const color = getUsageMeterColor(92); // returns the warning CSS variable

UsageDashboard

Renders multiple UsageMeter bars for all tracked features. Shows skeleton placeholders when loading.
import { UsageDashboard } from '@nozle-js/react';

<UsageDashboard
  features={[
    { key: 'api_calls', label: 'API Calls', used: 8200, limit: 10000 },
    { key: 'storage', label: 'Storage (GB)', used: 3, limit: 10 },
    { key: 'seats', label: 'Team Seats', used: 4, limit: 5 },
  ]}
/>
PropTypeDefaultDescription
featuresUsageDashboardFeature[][]Array of usage features to display
loadingbooleanfalseShows skeleton placeholders when true

UsageDashboardFeature type

FieldTypeDescription
keystringUnique feature identifier
labelstringHuman-readable feature name
usednumberCurrent usage count
limitnumberMaximum allowed usage

UsageAlert

Dismissible warning banner shown when any feature’s usage percentage meets or exceeds the threshold. Includes an upgrade link.
import { UsageAlert } from '@nozle-js/react';

<UsageAlert
  features={[
    { key: 'api_calls', label: 'API Calls', percentage: 92 },
    { key: 'storage', label: 'Storage', percentage: 45 },
  ]}
  threshold={80}
  upgradeHref="/plans"
/>
Only features at or above the threshold are shown. In the example above, only the “API Calls” alert would render (92% >= 80%). The “Storage” alert would not appear (45% < 80%).
PropTypeDefaultDescription
featuresUsageAlertFeature[]Array of features with their current usage percentage
thresholdnumber80Minimum percentage to trigger a warning
upgradeHrefstring'/plans'URL for the “Upgrade” link in each alert

UsageAlertFeature type

FieldTypeDescription
keystringUnique feature identifier
labelstringHuman-readable feature name
percentagenumberCurrent usage percentage (0-100)