PermDock
Concepts

Recipes

The @permdock shadcn registry - permission-gated UI built from your own shadcn/ui or React Native Reusables components on useGate, installed as code you own with npx shadcn add, while every decision stays in the permdock package.

PermDock ships no visible components. It ships the decision (useGate, useApproval, useTenant, useAssignableRoles, useAssignablePermissions) and a registry of recipes that render it with the components your app already has. A recipe is a file you own: npx shadcn add writes it into your project with your aliases and style, and you change it like any other component.

npx shadcn@latest add https://permdock.com/r/gated-button.json
npx shadcn@latest add https://permdock.com/r/approval-request-dialog.json
RecipeBuilt onRenders
gated-buttonbuttonRuns the action, is disabled with the reason as its title, hidden with mode="hide", or offers to request approval
approval-request-dialogbutton, dialog, textareaA note and a request for an approval-required action
tenant-switcherselectThe organisations the user is a member of; switching refreshes the snapshot
role-pickerselectOnly the roles the user may hand out in the active tenant
custom-role-editorcheckbox, labelOnly the permissions the editor holds, for a custom role
upgrade-promptalert, buttonThe plans that would grant the action
gated-button-nativeReact Native Reusables button, textThe gated button on React Native, with the reason as the accessibility hint
upgrade-prompt-nativeReact Native Reusables button, textThe upgrade prompt on React Native

Each recipe declares permdock as a dependency and its shadcn primitives as registryDependencies, so shadcn add installs them too. A preset installs its recipes and its generated files in one command: npx shadcn@latest add https://permdock.com/r/preset-<code>.json.

React and React Native

The web and native recipes call the same hooks from permdock/react and permdock/react-native, which share one implementation and one client store. Only the markup differs, so a fix to a decision reaches both platforms through npm update, and neither recipe needs to change.

Why

A recipe holds markup, not rules. useGate decides what the control shows; the recipe renders hidden, disabled, needsApproval and reason, and the server checks the action again. That split keeps the part that must stay correct in the package, where updates reach it, and the part every product styles differently in the application, where shadcn already puts it. Recipes avoid the props that differ between Radix and Base UI (asChild, render) and keep their own open state, so they install on either.

Last updated on

On this page