Staaarter

Billing Email Preferences

A settings panel for billing email notifications. Each notification type gets its own working toggle switch, and any marked as locked (like failed-payment alerts) render disabled and always on with a short note explaining why. An optional accounting email field lets a second recipient receive invoices, and the save button shows a loading state followed by a brief confirmation. Built for SaaS account settings and enterprise billing portals.

By Staaarter Team
Billing
Updated August 4, 2026
Docs
Live preview

Docs

Installation

A real shadcn registry command, not a copy-paste stand-in: it fetches this block plus its button, input, label dependencies and any missing npm packages, and installs them straight into your project.

npx shadcn add https://staaarter.com/r/billing-email-preferences.json

Prefer not to use the CLI? Copy the source from the Code toggle above into src/components/blocks/billing/billing53.tsx instead.

Usage

The file also exports billing53Demo, the exact props behind the preview above. Spread it to get a working section in one line, then replace it with your own data.

import { Billing53, billing53Demo } from "@/components/blocks/billing/billing53";

export default function Page() {
  return <Billing53 {...billing53Demo} />;
}

Props

PropTypeDefaultDescription
headingstring"Email preferences"Panel heading.
descriptionstring"Choose which billing emails you want to receive."Supporting line under the heading.
preferencesEmailPreferenceItem[]noneNotification rows rendered in order, each with its own toggle state.
accountingEmailLabelstring"Also send invoices to"Label above the accounting email field.
defaultAccountingEmailstring""Starting value of the accounting email field.
saveLabelstring"Save preferences"Label on the save button in its idle state.
classNamestringnoneExtra classes for the outer container.

Types

interface EmailPreferenceItem {
  id: string;
  label: string;
  description?: string;
  defaultEnabled?: boolean;
  locked?: boolean;
  lockedNote?: string;
}

Behavior notes

  • Each preference's toggle state is local, seeded from defaultEnabled (true if omitted), and locked items are always forced on regardless of defaultEnabled.
  • A locked preference's switch is a real disabled button, it renders visibly on but can't be clicked, and lockedNote (if set) explains why underneath the description.
  • Saving is a local simulation: clicking Save preferences disables the button, shows a spinner for about 700ms, then a checkmark and 'Preferences saved' for 2 seconds before resetting. Nothing is persisted, wire your own API call into a wrapper if you fork this.
  • The accounting email field has no format validation built in, it's a plain controlled input, add your own check before submitting if the format matters.
  • Every toggle is a real button with role="switch" and aria-checked, so preferences work with keyboard navigation and screen readers, not just pointer clicks.

Frequently asked questions