Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Role Ladder Permission Denied Error Block for React Aria

A full-screen permission page for a design-system manager: a role ladder of four rising steps with you at Viewer and Admin marked as needed, 'Two roles up' in words, and a Request access dialog that records a note and an owner in local state.

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

Show people exactly how far they are from access, with this permission denied page for React with React Aria. It's the error screen of Stylekeep, a design-system manager: a whole screen with the page's rails and one band across it. Under the heading, a role ladder runs across the band, ruled by Guides: four steps that rise from Viewer to Owner, "You are here" under Viewer, Admin drawn with a dashed outline, marked Needed and carrying its workspace:admin scope in a code chip, and the gap in words ("Two roles up"), counted from the ladder itself. On a phone the steps lie down as rows. A Shine Button Request access opens a Dialog with a note in a Textarea and an owner in a Select; sending records the request, closes the dialog, gives focus back to the button and shows a pending line with Withdraw. It's built from Dialog, Select, Textarea, Field, Shine Button, Button and Guides, with a CSS entrance only. For any app with roles and owners.

FAQ

What does Send request do, and what stays in the page?

It checks that the note says something, then keeps the request in the page's state: the dialog closes, a line under the ladder says "Pending with Rhea Castellan. Recorded in this demo; nothing was sent." and Withdraw takes it back. Nothing leaves the page. To wire it for real, create the access request on your server where the code says so, show the pending state from the response, and let Withdraw cancel it.

Where do the ladder and 'Two roles up' come from?

From three typed values: the list of roles from lowest to highest, the role the visitor has (YOU) and the role the page needs (NEEDED). The gap is the difference between their positions, so "Two roles up" and the sentence under it change with the data. The state is a shape and a word, never only a colour: a solid step for yours, a dashed outline and the word Needed for the one the page wants. The scope in the code chip is a typed constant; show the one your policy engine checks.

How do focus and the keyboard work in the dialog?

It is the real Dialog: it traps focus while open, Escape and Cancel close it, and focus goes back to the Request access button, also after a successful send. When it opens, focus lands in the note field. React Aria focuses the dialog itself when it opens, so this version moves focus to the note in a frame of its own. An empty note keeps the dialog open, says what is missing under the field and focuses it.

Where do the two owners in the Select come from?

From the typed list OWNER_LIST: a label and a value for each. In your app, list the people who can change roles in this workspace; with one owner, drop the Select and name them in the dialog's sentence.

Does this return a 403 status?

No: a component can't. Send the real HTTP status from your server or framework, so monitors and API clients see a 403 and not a 200 with an error drawn on it. Use 401 when the visitor isn't signed in.

Why is Request access pinned on a phone?

Because the ladder stacks into rows and is tall on a small screen. The button sits in a foot that is sticky at the bottom of the screen below the small breakpoint and falls back into the flow from there up, so there is one coloured button in both layouts.