shadcn.io is not affiliated with official shadcn/ui
Memberships Account Block for React Aria
The organisations in an account as two tabs, Memberships and Invitations, with counts: leave asks first, an invitation is accepted into the other tab or declined, a managed membership says why it stays, and Undo.
Installation
Overview
Show people where they belong and what is waiting for them, with this memberships panel for React with React Aria. A hairline frame with a plus mark on each corner holds Tabs with their counts, Memberships and Invitations, over ruled rows of fixed height. A membership is the organisation's tile, its name, your role and the day you joined; one is managed by your admin, says so in a Badge and can't be left from here, with the reason written out. Leave asks first in an Alert Dialog that says what stays with the organisation. An invitation shows who sent it, the role it offers and when it expires, with Accept, which moves the row to Memberships and updates both counts, and Decline. A line at the foot says what happened and Undo walks back the last change. When a tab is empty an Empty state fills the same space, so the panel keeps its height whichever tab you are on. It's built from Tabs, Alert Dialog, Badge, Empty, Button and Guides, with a CSS entrance only. For the account page of any app where people can belong to several groups.
FAQ
How do I fill it with my organisations?
Edit ORGS (an id, two typed initials for the tile and the name), MEMBERSHIPS (the organisation's id, your role, the ISO day you joined since and whether an admin managed it) and INVITATIONS (the organisation, who it is from, the role it offers and the ISO day it expires). "Expires 21 Oct, in 7 days" is worked out from the one AS_OF constant, never the clock, so replace it with today's date when you wire it up.
What stays local, and how do I make it real?
Everything. Accepting, declining and leaving change this page's state and say so in the foot; nothing is sent and nobody is told. Undo walks the changes back, which a real server can't always do. To make it real, call your endpoints in accept, decline and leave, move the row only when they answer, and put a failure in the same status line.
What does Accept do?
It moves the invitation to Memberships with the role it offered and today as the day you joined, and both tab counts change. You stay on the Invitations tab, so you can answer the next one; focus moves to its Accept button, or to Undo when it was the last. The status line says the row is under Memberships now. Declining removes the invitation the same way.
How does leaving work?
Leave opens an alert dialog: your role ends and what you made there stays with the organisation, which can invite you again. Focus starts on Stay, Escape closes it and focus returns to the Leave button. A membership managed by an admin has a Leave button that stays quiet and answers in words ("Brindle & Finch manages this membership. Ask your admin to remove you."), because removing it isn't up to you. On React Aria focus is set on Stay a moment after the dialog opens.
Do the tabs change the height?
No. Both tabs hold the height of three rows, and each row has a fixed height, so switching tabs, accepting or leaving never moves the panel's foot until a list grows past three. On a phone each row is a card with its actions under the words. The tabs are real tabs: arrow keys move between them and each controls its list.
Is it accessible?
The lists are real lists with names, every button says which organisation it acts on ("Leave Fennbrook Choir", "Accept the invitation from Northfield Swim Club"), the managed state is words and an icon, never colour alone, and the tile is hidden from assistive technology because the name is beside it. The status line is a polite live region present from the start. Dates are time elements and keep their order in a right-to-left page.