Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Team Roles Dialog Block for React

A members page with its roles dialog shown open: seven members with a select-all that shows all, none or a dash, a role select with a line about each role, a Can and Cannot list that changes with it, and a guard that refuses to leave the workspace without an Owner.

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 an admin change several roles at once and read what the new role allows before applying it, with this team roles dialog for React with Base UI. It opens from the Members page of Teamfern, a project workspace: the page's header holds an outline Change roles Button, and the members table, a row of initials, a name bar and the role as text for each of seven people, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog has the seven members at the start, each with a Checkbox, initials, a name and the current role in a Badge, and a select-all that shows all, none or a dash. At the end a Native Select chooses the role, a line says what it is for, and a list reads Can or Cannot for inviting people, managing billing, deleting projects and editing content. A sentence says what will happen, and a guard refuses any change that would leave no Owner. Apply is the only Shine Button; it writes the new roles on the drawn table. For preview the dialog is drawn open in place when the page loads; the header button opens the real dialog, with the same ticks. For workspaces, admin consoles and any app that has roles.

FAQ

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

So you can see it without a click. On load the dialog 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 Change roles button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same RolesFields component and share the block's state, so a member ticked in the copy is ticked in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.

What does the last-owner guard do?

After every tick and every choice the dialog counts the Owners the workspace would have if you applied now: the ticked members get the new role, the others keep theirs. If that is zero, the select turns invalid, an alert says "A workspace needs at least one Owner", and Apply stays on the page with a quiet look. Pressing it names the problem and moves focus to the role select. Untick the Owner, or give the Owner role to someone else in the same change, and the guard lets go.

How does the select-all show three states?

It reads the number of ticked members: none is unchecked, all seven is checked, anything between is a dash, which assistive technology hears as mixed. Pressing it ticks everyone, or clears everyone when all are ticked. The rows show what would happen to each ticked member ("Becomes Editor") in place of their email, so you can check the selection without leaving the list, and a line counts "3 of 7 selected".

Is it accessible from the keyboard?

Yes. The real dialog is named by its title and described by its sentence, focus starts on the select-all box, and Escape, Cancel and the close button return focus to the Change roles button. Every box is named for its member, the role select is a native select, the permissions are a description list with the answer in words as well as an icon, and what changes is spoken once in a polite status line (inside the dialog while it is open). The trigger is passed to DialogTrigger through render, and the dialog is controlled with open and onOpenChange.

What stays local, and how do I wire it for real?

Everything. The seven members, the four roles and what each can do are typed in the file, and Apply only changes this block's state and the drawn table. In your app send the change to your API, enforce the last-owner rule on the server as well (the page's guard is a courtesy, not a lock), and show the permissions from the same table the server checks.

How does it look on a phone?

The copy shown on load docks to the foot of the page as a bottom sheet with its buttons pinned and the content scrolling above them: the members first, then the role, what it allows, the sentence and the guard in one column. The real dialog keeps the Dialog's own phone layout, a sheet stuck to the bottom of the screen.

  • Pro

    Share Permissions Dialog

    Share and invite

    A team drive with its share dialog shown open: a name or email field with suggestions under it, a role select and a Remove for each person added, a fixed owner, two inherited rows with a lock, and a general access select, with the people count said whenever it changes.

  • Pro

    Invite Members Dialog

    Share and invite

    A household calendar's Members page with its invite dialog shown open: one email field that knows the household's domain, so an outside address joins as a guest, the people who already have access, and a Send invite button that adds a pending row.

  • Pro

    Invite Team Dialog

    Share and invite

    A crew page with its bulk invite dialog shown open: a pasted list becomes one chip per address with bad ones flagged, one role for the batch, a seat meter that refuses a batch that does not fit, and a Pending tab with Resend, Revoke and Undo.

  • Pro

    Team Members Settings

    Team and roles

    A members panel with seat and two-factor meters, a native table with row selection, a role menu per person and, pinned at the foot, a bulk role change and Remove that an Undo walks back one step at a time.

  • Pro

    A roles window with a rail of five roles and a detail of grouped permissions: mixed-state group boxes, a Compare with select that marks each permission with a plus or a minus, read-only system roles and Duplicate to edit.

  • Pro

    The people who can sign in to a shared account as hairline tiles: role menu, two-factor on or off, last sign-in, those without two-factor first with a reminder button, pending invitations and an invite form.