Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Family Plan Members Billing Block for Radix UI

Six seats on a family plan with a swap allowance: replace a member to free a seat (two swaps a month), add an email to an open seat for free, and the counter shows the swaps remaining and when they reset.

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

Keep a shared plan honest without a seat manager, with this family plan for React with Radix UI. A compact header states the rule, and one hairline frame with a plus mark on each corner holds six seat cells on shared hairlines, three by two. A member is an Avatar with initials, a name, an address, a badge (Organiser, Member or Invited) and an outline Replace button. Replacing frees the seat into "Swap in progress" and uses one of two swaps a month; an open seat or a seat in swap has an email Input that is checked for shape and for a duplicate, with the message in a slot that is always there. Adding to an open seat is free. The heading row counts the swaps remaining and the day they reset, "1 of 2 swaps remaining this month, resets 1 Nov". The only Shine Button, "Invite", fills every seat you typed an address into. It's built from Avatar, Input, Field, Badge, Shine Button and Guides, with a CSS entrance only. For family and household plans, shared licences and team seats without roles.

FAQ

How do I change the seats and the allowance?

Edit SEATS (a name, an address and a kind for each: member, open or swap) at the top of the file, SWAP_LIMIT for the swaps a month, SWAPS_USED for those already used and RESETS for the day the counter resets. The counter, the labels and every message are derived from the seats.

What counts as a swap?

Only Replace. It removes a member and frees the seat into swap; the swap is used then, not when you add the new address. Adding an address to an open seat, or to a seat already in swap, uses none. When no swaps remain, Replace stays focusable and says so, and open seats can still be filled.

What does Invite do, and what stays local?

It turns every seat with a valid address into an invited member and says that nothing was sent. A bad address keeps its seat, shows its message and takes focus. In your app, send the invitations from invite, keep the pending ones with their status and show the provider's answer in the same status line.

What does the address check do?

It checks the shape (something, an at sign, a domain with a dot) and that the address does not already have a seat. It does not check that the mailbox exists: only an invitation can. The message appears under the field and the field is marked invalid.

Is it accessible?

Every Replace button is named for the member, every field is labelled by its seat and swap ("Replacing Wren Hale"), and a message is tied to its field. The people are initials, not photos. The status line is a polite live region that is present from the start.

How does it look on a phone?

The seat cells stack one across and keep their height, the counter wraps under the heading, and the status line and the Invite button stay pinned in a foot at the bottom of the screen.