Skip to main content
Clever Ops

Toggle Reveal Pane

A labelled two-option toggle that swaps panes with a height-aware morph, monthly/annual, personal/business, using aria-pressed buttons and a crossfade that never jumps the layout.

Preview & code

Loading Toggle Reveal Pane preview

Installation

pnpm dlx shadcn@latest add @cleverui/toggle-reveal-pane

Requires the @cleverui registry in your components.json, a one-off, two-line setup.

Usage

tsx
import { ToggleRevealPane } from '@/components/ui/toggle-reveal-pane'
Exampletsx
import { ToggleRevealPane } from '@/components/ui/toggle-reveal-pane'

function MonthlySummary() {
  return (
    <div className="mx-auto max-w-md">
      <dl className="divide-y divide-border/60 border-y border-border/60">
        <div className="flex items-baseline justify-between gap-4 py-3">
          <dt className="text-sm text-muted-foreground">Pro seat</dt>
          <dd className="font-mono text-sm tabular-nums text-foreground">
            $58 / mo
          </dd>
        </div>
        <div className="flex items-baseline justify-between gap-4 py-3">
          <dt className="text-sm text-muted-foreground">Query minutes</dt>
          <dd className="font-mono text-sm tabular-nums text-foreground">
            40,000 included
          </dd>
        </div>
        <div className="flex items-baseline justify-between gap-4 py-3">
          <dt className="text-sm text-muted-foreground">Billed</dt>
          <dd className="font-mono text-sm tabular-nums text-foreground">
            Monthly · cancel anytime
          </dd>
        </div>
      </dl>
    </div>
  )
}

function AnnualDetail() {
  return (
    <div className="mx-auto max-w-md space-y-5">
      <dl className="divide-y divide-border/60 border-y border-border/60">
        <div className="flex items-baseline justify-between gap-4 py-3">
          <dt className="text-sm text-muted-foreground">Pro seat</dt>
          <dd className="font-mono text-sm tabular-nums text-foreground">
            $48 / mo
          </dd>
        </div>
        <div className="flex items-baseline justify-between gap-4 py-3">
          <dt className="text-sm text-muted-foreground">Billed annually</dt>
          <dd className="font-mono text-sm tabular-nums text-foreground">
            $576 / seat
          </dd>
        </div>
        <div className="flex items-baseline justify-between gap-4 py-3">
          <dt className="text-sm text-muted-foreground">Query minutes</dt>
          <dd className="font-mono text-sm tabular-nums text-foreground">
            40,000 / mo included
          </dd>
        </div>
        <div className="flex items-baseline justify-between gap-4 py-3">
          <dt className="text-sm text-muted-foreground">Overage</dt>
          <dd className="font-mono text-sm tabular-nums text-foreground">
            $0.012 / minute
          </dd>
        </div>
        <div className="flex items-baseline justify-between gap-4 py-3">
          <dt className="text-sm text-muted-foreground">Viewer seats</dt>
          <dd className="font-mono text-sm tabular-nums text-foreground">
            Unlimited · free
          </dd>
        </div>
      </dl>
      <p className="text-sm leading-relaxed text-muted-foreground">
        Annual billing locks the seat rate for 12 months and unlocks priority
        warehouse connectors. You can add seats mid-term at the same unit price;
        unused months do not roll over after renewal.
      </p>
    </div>
  )
}

export default function ToggleRevealPaneDemo() {
  return (
    <div className="mx-auto w-full max-w-lg px-4 py-10 sm:px-6 sm:py-14">
      <p className="mb-6 text-center font-mono text-[11px] uppercase tracking-[0.2em] text-muted-foreground sm:text-xs">
        Billing · Northline Pro
      </p>
      <ToggleRevealPane
        defaultIndex={0}
        ariaLabel="Billing period"
        options={[
          {
            label: 'Monthly',
            content: <MonthlySummary />,
          },
          {
            label: 'Annual',
            badge: 'Save 17%',
            content: <AnnualDetail />,
          },
        ]}
      />
    </div>
  )
}

API reference

ToggleRevealPane accepts the following props.

PropTypeDefaultDescription
options*ToggleRevealPaneOption[]exactly two options; badge is a mono chip like 'Save 20%'; extras beyond two are ignored
defaultIndexnumber0option active on first render (SSR-rendered active)
ariaLabelstring'View toggle'accessible name for the toggle group

…plus everything from React.HTMLAttributes<HTMLDivElement>: className, event handlers, aria attributes and the rest pass straight through.

Referenced types

Typestsx
export interface ToggleRevealPaneOption {
  label: string
  /** mono chip beside the label, e.g. 'Save 20%', the single accent moment */
  badge?: string
  content: React.ReactNode
}

Frequently asked questions

How do I install the Toggle Reveal Pane component?

Register the @cleverui registry in your components.json ("@cleverui": "https://cleverops.com.au/r/{name}.json"), then run `npx shadcn@latest add @cleverui/toggle-reveal-pane`. The shadcn CLI copies the source into your project, you own the code from that point. You can also copy the source directly from this page.

What dependencies does Toggle Reveal Pane require?

Toggle Reveal Pane uses motion on top of React and Tailwind CSS. You don't need to install it manually, the shadcn CLI resolves and installs npm dependencies automatically when you add the component.

Can I theme Toggle Reveal Pane to match my brand?

Yes. The component is styled entirely with Tailwind utilities over standard design tokens (primary, background, muted, border), so it inherits your existing shadcn/ui theme automatically. Change your CSS variables and the component follows, no source edits needed for palette, radius, or fonts.

Want this built for you?

CleverUI is built by the Clever Ops web team. If you'd rather ship a hand-coded, fast, custom website than assemble one, we build them for Australian businesses every week.

Explore web development services