Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Manage Subscription Dialog Block for React

A design tool's account page with its subscription sheet shown open: the plan, billing cycle and seats editable in place, a next-invoice foot worked out from the controls, and a plan card behind it that changes when you save.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Let people edit what they pay for without leaving the page, with this subscription sheet for React with Base UI. It opens from the Subscription page of Studiofold, a design tool: the page's header holds an outline Manage subscription Button, and the page itself, a plan card with its price and a project meter, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Sheet slides in from the end edge and lists the subscription as rows, each editable where it can be: the plan in a Select, monthly or yearly in a Segment Group, and the seats in a Number Input that only the Team plan has. The card and the renewal date are read-only. The foot works out the next invoice from the controls as you change them, counts the changes and holds the only Shine Button, Save changes, beside a quiet Discard. Saving updates the plan card behind the sheet: its name, its price and how much of the project limit is used. For preview the sheet is drawn open in place when the page loads; the header's button opens the real sheet, with the same rows and the same state. For account pages, billing settings and any app with plans and seats.

FAQ

Why is the sheet already open, and what do I keep?

So you can see it without a click. On load the sheet is a copy drawn in place over the page: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Manage subscription button opens the real Sheet, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same SubscriptionFields and SubscriptionFoot components and share the block's state, so a plan chosen in the copy is there in the real sheet. In your app keep the Sheet and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.

How is the next invoice worked out?

One small function, periodOf, takes the plan, the cycle and the seats and returns cents: the plan's monthly price, plus each seat past the ones it includes on Team, times 10 for a yearly cycle (ten months for twelve). Every figure on screen comes from it, so the foot, the sentence under the heading and the card behind the sheet always agree. It doesn't prorate: a change that takes effect mid-period needs an invoice preview from your billing provider, which you show in the same foot instead of the local sum.

Why are seats only on one plan?

Solo and Studio are a single seat, so the row says so and has no control; Team includes three seats and charges for each one after that, up to 25. What you type is kept between those limits, and the text is read the same in an Arabic page, where the number field prints Arabic-Indic digits. The field and the row keep their size when the plan changes, so nothing under them moves.

What stays local, and what happens to changes I don't save?

Everything. The prices and the Visa line are typed in the file (a real app takes cards with its payment provider's hosted fields, never in fields of its own), and Save changes only updates the plan card and the page's sentence and says, in the polite status, that nothing was charged. In your app send the draft to your billing API, show its result in the foot, and update the card from what it returns. There is no cancel here and no retention offer: those belong in a cancel flow of their own. Changes you don't save are dropped: Discard puts the controls back to what is saved and says so, and so do the close button and Escape. Save changes with nothing changed doesn't close anything: it says "No changes to save." Both buttons are always on screen and quiet when there is nothing to do, so the foot never changes size.

Is it accessible from the keyboard?

Yes. The real sheet is named by its title and described by its sentence, focus starts on the plan select and stays inside until it closes, and Escape and the close button return focus to Manage subscription. Each row's control is named by its label, the select and the segments by aria-labelledby. What is said while the sheet is open is said again inside it, because a modal hides the page's own status. The trigger is passed to SheetTrigger through render, and the sheet is controlled with open and onOpenChange.

Which edge does the sheet come from, and what about phones?

The end edge, in either direction: the sheet's sides are physical, so the block reads the page's direction when it opens and picks the matching edge. On a phone the copy shown on load docks to the foot of the page as a bottom sheet with its actions pinned, and the real sheet takes the full width.

  • Pro

    Select Plan Dialog

    Payments and plans

    A static-site host's Sites page with its plan chooser shown open: three plans as rows that unfold to their features, a yearly switch that rewrites the prices and what is due today, and a comparison table behind a disclosure.

  • Pro

    Upgrade Plan Dialog

    Payments and plans

    A product-analytics usage page with its upgrade dialog shown open: your plan and the next joined by an arrow, a yearly switch, and a table of limits with what you have now and what you would have after.

  • Pro

    Cancel Subscription Dialog

    Destructive confirms

    A backup service's plan page with its exit flow shown open: an alert dialog in three steps, why you are leaving, an offer matched to the reason, and what ends and when, with a destructive final button and a thin progress bar.

  • Pro

    Payment Method Dialog

    Payments and plans

    A ticket shop's order summary with its payment-method dialog shown open: a saved card, a bank transfer and an invoice as rows, each asking only for the one detail it needs, and a Pay with row behind the dialog that changes when you choose.

  • Pro

    Current Plan Billing

    Plan and usage

    The account's current plan in app settings: plan, price, renewal date and card, a change-plan action, every quota's usage this period on shared hairlines, and the next invoice.

  • Pro

    Seats on a team plan: members with a role each (viewers are free), a stepper for the seats you pay for, and the monthly and prorated cost worked out before you save.