Xzero UI
Pro library

Billing toggle

A monthly and yearly switch with a savings badge and prices that roll to the new amount.

$ pnpm dlx shadcn@4.23.0 add @xzero-ui/billing-toggle
Live · keyboard ready

When to use

When not to use

Installation

Register both Xzero UI namespaces in your project's components.json:

{
  "registries": {
    "@xzero-ui": "https://mcp.xzero.co.uk/r/{name}.json",
    "@xzero-ui-pro": "https://mcp.xzero.co.uk/r/pro/{name}.json"
  }
}
npx shadcn@4.23.0 add @xzero-ui/billing-toggle

Install xzero-foundation once, and import @/components/xzero/foundation.css in your app root. No Xzero token is used by this snapshot. For sample portraits, photos, fonts, or logos, download https://mcp.xzero.co.uk/install-assets.mjs and run node xzero-install-assets.mjs <receiving-project>.

Usage

import { useState } from "react";
import { BillingPrice, BillingToggle } from "@/components/xzero/billing-toggle/billing-toggle";

export function ProPrice() {
  const [period, setPeriod] = useState("monthly");
  const yearly = period === "yearly";
  return (
    <div>
      <BillingToggle
        value={period}
        onValueChange={setPeriod}
        options={[
          { value: "monthly", label: "Monthly" },
          { value: "yearly", label: "Yearly", badge: "Save 20%", activeBadge: "You save $48" },
        ]}
      />
      <BillingPrice amount={yearly ? 16 : 20} was={yearly ? 20 : undefined} period={yearly ? "per month, billed yearly" : "per month"} />
    </div>
  );
}

API reference

BillingToggle

A billing period switch. One thumb glides between the options, and the savings note on the cheaper period tints and rewrites itself in place once it is chosen. Set --billing-accent on any ancestor to recolor the note (defaults to --success).

PropTypeDefaultDescription
value (required)string–Value of the selected option. Controlled only.
onValueChange (required)(value: string) => void–Called with the chosen option's value on click or arrow key.
optionsBillingToggleOption[]Monthly and Yearly with a Save 20% badgeOptions in order. Each has value, label, and optional badge and activeBadge.
labelstring"Billing period"Accessible name of the radio group.
size"md" | "lg""md"md is 36px tall per option, lg is 44px with larger text.
classNamestring–Extra class on the radio group.

BillingToggleOption

One option of the toggle.

PropTypeDefaultDescription
value (required)string–Value passed to onValueChange. Also the React key.
label (required)string–Visible option text.
badgestring–Short savings note, such as Save 20%.
activeBadgestring–Badge text once this option is selected, such as You save $48. Defaults to badge.

BillingPrice

A price that rolls to its new amount when the billing period changes, with an optional struck-through old price and a period that swaps in place.

PropTypeDefaultDescription
amount (required)number–The price to show.
currencystring"$"Symbol before the amount and the old price.
periodstring–Text after the price, such as per month. Swaps with a short fade when it changes.
wasnumber–Previous price. Shown struck through only when it is higher than amount.
decimalsnumber0Decimal places for amount and was.
classNamestring–Extra class on the price.

Keyboard interactions

KeysAction
TabMoves focus to the selected option only (roving tabindex).
Arrow Right / Arrow DownSelects and focuses the next option, wrapping at the end.
Arrow Left / Arrow UpSelects and focuses the previous option, wrapping at the start.
Home / EndSelects the first or last option.

Accessibility

Motion

Responsive behavior

Performance

Notes for AI

Also in toggles

Guidance for AI tools

Billing toggle: A monthly and yearly switch with a savings badge and prices that roll to the new amount. Follow the declared prop types and do not invent props. Keep keyboard access, reduced motion support, and both light and dark themes intact when adapting it.

Full library index: https://ui.xzero.co.uk/llms.txt

Browse all components