Skip to content
Neon UI
Esc
navigateopen⌘Jpreview
On this page

UpgradeDialog

Pricing dialog with a drawn-check feature list and processing state.

UpgradeDialog is the platform’s paywall moment, played in the house voice: the price answers first (large tabular number, mono cadence), the feature checklist introduces itself one line at a time with drawn primary checks, and the CTA arrives already charged — neon fill and the house glow, because this is the one place the color was always going. Upgrading a tenant is a real flight (a cross-org Neon project transfer), so isProcessing locks the dialog under a shimmering label, and failures speak through the description slot in destructive — same row, zero shift.

Install

npx shadcn@latest add https://ui.neon.com/r/upgrade-dialog.json

Usage

import { UpgradeDialog } from "@/components/neon-ui/upgrade-dialog";

<UpgradeDialog
  open={open}
  onOpenChange={setOpen}
  onUpgrade={() => upgradeApp(app.id)}
  isProcessing={isUpgrading}
  error={upgradeError}
  plan={{
    name: "Launch",
    price: 19,
    features: [
      "Dedicated Neon project",
      "Always-on compute",
      "Branching and snapshots",
    ],
    note: "billing starts today · cancel anytime",
  }}
/>;

Keep isProcessing honest — the upgrade moves the tenant’s Neon project between orgs, and the dialog refuses to dismiss mid-flight. Surface failures through error instead of closing.

Props

PropType
openboolean
Typeboolean
onOpenChange(open: boolean) => void
Type(open: boolean) => void
onUpgrade() => void

Starts the upgrade; drive isProcessing while it flies.

Type() => void
planUpgradePlan

{ name, price, features, note? }

TypeUpgradePlan
isProcessing?boolean

Locks the dialog and shimmers the action label.

Typeboolean
Defaultfalse
error?string | null

Failure spoken through the description slot.

Typestring | null
title?string
Typestring
Default"Upgrade to {plan.name}"
description?ReactNode

Override the default pitch line.

TypeReactNode

Accessibility

  • Base UI dialog semantics: focus trap, labelled by the title, described by the description slot.
  • Errors take over the description with role="alert".
  • While processing, every action is disabled and dismissal is refused — state can’t desync mid-transfer.
  • Checklist stagger and the drawn checks are static under prefers-reduced-motion.