PermissionModeSwitcher
StableA button that always shows how much freedom the assistant has, and lets you change it.
Also known as permission mode, auto approve setting
Install with npm install @tattva/ui (setup), or copy the code from the kit in Downloads.
The five modes
const [mode, setMode] = useState("manual");
<PermissionModeSwitcher value={mode} onChange={setMode} shortcut="Shift+Tab" />The five default modes. The riskiest one shows a warning.
When to use it
Keeps the assistant's level of freedom in view at all times, on a button below the box where people type. Opening it lists every mode with what it allows and how risky it is, so nobody changes it by guesswork.
Made of: Button (risk icon, name, mode) · Pop-up list · Mode choice (check, name, risk, description, warning or lock reason) · Shortcut hint (optional) · Spoken update
Use it for
- Below a chat or task input, to show and change how much the assistant may do without asking.
- Products where an admin may lock some modes and people need to see why.
- Offering a risky mode with a warning written next to it.
Not for
- Asking about one specific action: use PermissionPrompt.
- Choosing which model answers: use ModelPicker.
- Switching between two or three equal views: use SegmentedControl.
Do and avoid
Do
- Keep the button on screen the whole time, so the mode is never hidden.
- Describe each mode as what the assistant may do without asking.
- Add a warning to the riskiest mode.
- Tell people why a mode is locked and what they can do.
- Pass shortcut only if your app really binds that key.
Avoid
- Don't show risk with only an icon or color. Keep the words.
- Don't hide locked modes. Showing them with a reason explains the limit.
- Don't show a shortcut the app does not have.
On a phone
- The trigger is a pill that keeps its size and has a 44px tap area on a touch screen.
- On a phone the panel opens as a bottom sheet with a backdrop. On wider screens it floats above the trigger and is at most the screen width minus 32px.
- Each mode row is a button with its description visible, so nothing needs hover.
- The keyboard shortcut line is shown on a phone too, so leave the shortcut prop out of phone-only layouts.
Seen in products
- Claude Code has the modes Manual (default), acceptEdits, plan (read-only exploration), auto (a classifier reviews actions instead of the user) and bypassPermissions.
- Claude Code describes bypassPermissions as skipping prompts, including for .git and .claude paths, and says to use it only in isolated environments.
- Claude Code admins can disable auto and bypass through managed settings.
- Claude Code switches mode with Shift+Tab and also offers a switch inside a prompt ("Yes, and switch to auto mode").
- Replit Agent has autonomy levels (Free, Power, Max) plus Plan mode, and asks for confirmation before paid actions.
Properties
| Prop | Type | Default | Description |
|---|---|---|---|
| modes | PermissionMode[] | defaultPermissionModes | Modes in display order. Each has id, label, description, risk (low, medium or high), and optional warning and lockedReason. |
| value | string | none | Selected mode id, for controlled use. |
| defaultValue | string | none | Initial mode id when uncontrolled. Defaults to the first mode. |
| onChange | (id: string) => void | none | Called when the person picks an unlocked mode. |
| label | string | "Permission mode" | Name for the trigger text, the popover and the radio group. |
| shortcut | string | none | Shortcut shown at the foot of the panel. Pass it only if the app binds it. |
| shortcutLabel | string | "to cycle modes" | Text beside the shortcut. |
| announcePrefix | string | "Mode changed to" | Start of the polite announcement made after a change. |
| className | string | none | Extra classes on the wrapper. |
"Show code under the preview gives the code for the example on the stage."
In Figma
In Figma, one PermissionModeSwitcher switches all of this from its properties panel, across 4 variants. Each property sets the React prop beside it, so design and code use the same names.
| Figma property | React | Values |
|---|---|---|
| State | Hover, Pressed and Focus come from the browser. | Default, Hover, Pressed, Focus |
States
States this part has beyond its default look. Build each one your screen can reach. States set by a property are in the Code tab.
- open
- Pressing the trigger opens a list of modes, each with a risk label.
- locked
- Set lockedReason on a mode to dim it, explain why it is locked and make it unselectable.
- high risk
- A mode with risk high shows its risk label in the danger colour, plus its warning text if set.
- keyboard
- Up and down arrows move between modes and the chosen one is announced to screen readers.
- shortcut hint
- Pass shortcut to show a key hint at the bottom of the list.
Tokens
Change one of these and every part that uses it follows.
--surface-raised--border--danger-fg--fg-muted--radius-control
Built in
- The button says whether the list is open, and names the current mode and its risk.
- The modes work as one set of options: Tab lands on the chosen one and the up and down arrow keys move between them.
- Locked modes are marked unavailable and show the reason in words.
- Screen readers hear the new mode after a change.
- Escape closes the list and returns you to the button.
What you need to do
- Write each lockedReason so it says who locked the mode and why.
Built toward WCAG 2.2 AA and checked automatically; no independent audit yet. Read the accessibility guide