-
Notifications
You must be signed in to change notification settings - Fork 1.6k
docs: add Sistent Permission component documentation #7933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dhruveshmishra
wants to merge
11
commits into
layer5io:master
Choose a base branch
from
dhruveshmishra:docs/sistent-permission-shield-docs
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+350
−0
Open
Changes from all commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
d9769ea
docs: add Sistent Permission component documentation
dhruveshmishra 7188796
Merge branch 'master' into docs/sistent-permission-shield-docs
rishiraj38 efa7921
Merge branch 'master' into docs/sistent-permission-shield-docs
rishiraj38 e6bd037
docs: update PermissionShield examples to use correct Key schema
dhruveshmishra c49e326
Merge branch 'master' into docs/sistent-permission-shield-docs
dhruveshmishra 1b4a9da
Merge branch 'master' into docs/sistent-permission-shield-docs
dhruveshmishra 0f24092
Merge branch 'master' into docs/sistent-permission-shield-docs
dhruveshmishra 19c1d8d
docs: update Sistent Permission component documentation to reflect re…
dhruveshmishra a77cfa8
Merge remote-tracking branch 'upstream/master' into docs/sistent-perm…
dhruveshmishra fe6cc4e
docs: update Permission component documentation for variants and Perm…
dhruveshmishra 343d552
docs: use h1 header in ForbiddenPage code example
dhruveshmishra File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,173 @@ | ||
| --- | ||
| title: Permission Code | ||
| component: permission | ||
| description: Integration details, code examples, and API references for the PermissionShield component. | ||
| --- | ||
|
|
||
| import { PermissionShield, Button, PermissionSessionContext } from "@sistent/sistent"; | ||
|
|
||
| The `PermissionShield` component acts as a high-level wrapper to restrict and decorate interactive components. | ||
|
|
||
| > **Important Security Note:** UI gating is a presentation-layer control only. Client-side checks must not decide access. The backend server and API routes must always enforce authorization on every request. | ||
|
|
||
| <a id="installation"> | ||
| <h2>Installation</h2> | ||
| </a> | ||
|
|
||
| ```bash | ||
| npm install @sistent/sistent | ||
| ``` | ||
|
|
||
| <a id="basic-usage"> | ||
| <h2>Basic Usage</h2> | ||
| </a> | ||
|
|
||
| Wrap any standard component (e.g., a `Button`) inside the `PermissionShield` to automatically overlay the lock badge when permissions are restricted. | ||
|
|
||
| <div className="showcase"> | ||
| <div className="items"> | ||
| <ThemeWrapper> | ||
| <PermissionShield | ||
| permissionKey={{ | ||
| id: "create_design", | ||
| category: "Catalog Management", | ||
| subcategory: "Designs", | ||
| function: "Create new design", | ||
| description: "Create new Meshery design" | ||
| }} | ||
| > | ||
| <Button variant="contained" color="primary"> | ||
| Create New Design | ||
| </Button> | ||
| </PermissionShield> | ||
| </ThemeWrapper> | ||
| </div> | ||
| <CodeBlock name="basic-permission-shield" collapsible code={`import { PermissionShield, Button } from "@sistent/sistent"; | ||
|
|
||
| export const CreateDesignButton = () => ( | ||
| <PermissionShield | ||
| permissionKey={{ | ||
| id: "create_design", | ||
| category: "Catalog Management", | ||
| subcategory: "Designs", | ||
| function: "Create new design", | ||
| description: "Create new Meshery design" | ||
| }} | ||
| > | ||
| <Button variant="contained" color="primary"> | ||
| Create New Design | ||
| </Button> | ||
| </PermissionShield> | ||
| );`} /> | ||
| </div> | ||
|
|
||
| <a id="custom-boundary-padding"> | ||
| <h2>Custom Boundary Padding</h2> | ||
| </a> | ||
|
|
||
| Use the `boundaryPadding` prop to configure custom offsets if the tooltip overlaps fixed elements (like headers, sidebars, or navbar sections) during scrolling. | ||
|
|
||
| <div className="showcase"> | ||
| <div className="items"> | ||
| <ThemeWrapper> | ||
| <PermissionShield | ||
| permissionKey={{ | ||
| id: "view_connections", | ||
| category: "Workspace Management", | ||
| subcategory: "Connections", | ||
| function: "View Connections", | ||
| description: "View all connections within an environment" | ||
| }} | ||
| boundaryPadding={{ top: 85, left: 270 }} | ||
| > | ||
| <Button variant="outlined"> | ||
| Connections | ||
| </Button> | ||
| </PermissionShield> | ||
| </ThemeWrapper> | ||
| </div> | ||
| <CodeBlock name="custom-boundary-padding" collapsible code={`import { PermissionShield, Button } from "@sistent/sistent"; | ||
|
|
||
| export const GatedConnectionsButton = () => ( | ||
| <PermissionShield | ||
| permissionKey={{ | ||
| id: "view_connections", | ||
| category: "Workspace Management", | ||
| subcategory: "Connections", | ||
| function: "View Connections", | ||
| description: "View all connections within an environment" | ||
| }} | ||
| boundaryPadding={{ top: 85, left: 270 }} | ||
| > | ||
| <Button variant="outlined"> | ||
| Connections | ||
| </Button> | ||
| </PermissionShield> | ||
| );`} /> | ||
| </div> | ||
|
|
||
| <a id="permission-session-context-usage"> | ||
| <h2>Permission Session Context</h2> | ||
| </a> | ||
|
|
||
| Use `PermissionSessionContext` to embed permission details directly inside custom components or full-page 403 authorization layouts without utilizing tooltips. | ||
|
|
||
| <div className="showcase"> | ||
| <div className="items"> | ||
| <ThemeWrapper> | ||
| <div style={{ width: "100%", maxWidth: "450px" }}> | ||
| <PermissionSessionContext | ||
| variant="card" | ||
| permissionKey={{ | ||
| id: "delete_connection", | ||
| category: "Lifecycle Management", | ||
| subcategory: "Connections", | ||
| function: "Delete a connection", | ||
| description: "Delete a connection" | ||
| }} | ||
| /> | ||
| </div> | ||
| </ThemeWrapper> | ||
| </div> | ||
| <CodeBlock name="permission-session-context-card" collapsible code={`import { PermissionSessionContext } from "@sistent/sistent"; | ||
|
|
||
| export const ForbiddenPage = () => ( | ||
| <div style={{ padding: "24px" }}> | ||
| <h1>Access Denied</h1> | ||
| <PermissionSessionContext | ||
| variant="card" | ||
| permissionKey={{ | ||
| id: "delete_connection", | ||
| category: "Lifecycle Management", | ||
| subcategory: "Connections", | ||
| function: "Delete a connection", | ||
| description: "Delete a connection" | ||
| }} | ||
| /> | ||
| </div> | ||
| );`} /> | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| </div> | ||
|
|
||
| <a id="api-reference"> | ||
| <h2>API Reference</h2> | ||
| </a> | ||
|
|
||
| <h3>PermissionShield Props</h3> | ||
|
|
||
| | Name | Type | Default | Description | | ||
| | :--- | :--- | :--- | :--- | | ||
| | `permissionKey` | `PermissionKeySpec` | - | The unique key specification that the gated action requires. | | ||
| | `children` | `React.ReactNode` | - | The gated component (e.g., Button, IconButton) to be wrapped. | | ||
| | `variant` | `'inline' \| 'badge'` | `'inline'` | The display format of the lock badge. `'inline'` renders the lock icon at the center-right (end adornment), `'badge'` renders it overlaying the bottom-left corner. | | ||
| | `boundaryPadding` | `object` | `{ top: 85, left: 16, right: 8, bottom: 8 }` | Optional offsets to prevent tooltips from overlapping headers/menus. The default is responsive: `{ top: 64, left: 8, right: 8, bottom: 8 }` on mobile and `{ top: 85, left: 16, right: 8, bottom: 8 }` on desktop. | | ||
|
|
||
| <h3>PermissionSessionContext Props</h3> | ||
|
|
||
| | Name | Type | Default | Description | | ||
| | :--- | :--- | :--- | :--- | | ||
| | `variant` | `'tooltip' \| 'card'` | `'tooltip'` | The layout style for the session context. `'tooltip'` uses compact dark-themed styling, while `'card'` provides theme-aware, scaled-up styling for full-page or card display. | | ||
| | `permissionKey` | `PermissionKeySpec` | - | Optional. When supplied, the component resolves the unmet keys, subcategories, and description automatically. | | ||
| | `displayedKeys` | `Key[]` | - | Optional. Pre-resolved array of permission keys to display details for when manual key resolution is preferred. | | ||
| | `subtitle` | `string` | - | Optional. Pre-resolved subtitle (e.g. "Needs any of: ...") to display below the title. | | ||
| | `categories` | `string[]` | - | Optional. Pre-resolved category labels to display as chips. | | ||
| | `subcategories` | `string[]` | - | Optional. Pre-resolved subcategory labels to display as chips. | | ||
65 changes: 65 additions & 0 deletions
65
src/collections/sistent/components/permission/guidance.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| --- | ||
| title: Permission Guidance | ||
| component: permission | ||
| description: Guidance on using the Sistent Permission component and best practices for design system gating. | ||
| --- | ||
|
|
||
| <a id="usage"> | ||
| <h2>Usage</h2> | ||
| </a> | ||
|
|
||
| The `PermissionShield` component should be used to protect actions or affordances that require specific roles, permission keys, or capabilities. | ||
|
|
||
| > **Important Security Note:** UI gating is a presentation-layer control only. Client-side checks must not decide access. The backend server and API routes must always enforce authorization on every request. | ||
|
|
||
| <ul> | ||
| <li>Wrap gated interactive components (Buttons, IconButtons, Tabs) to provide visual feedback to users when they are restricted.</li> | ||
| <li>Ensure the locked state clearly informs the user which permissions are missing, reducing frustration and confusion.</li> | ||
| <li>Use responsive layouts or custom boundary paddings where the tooltips might get clipped by sidebars or sticky headers.</li> | ||
| </ul> | ||
|
|
||
| <a id="when-to-use"> | ||
| <h2>When to Use</h2> | ||
| </a> | ||
|
|
||
| <h3>Disable versus Hide</h3> | ||
|
|
||
| When deciding whether to restrict a feature, follow these design system guidelines: | ||
|
|
||
| <ul> | ||
| <li> | ||
| <strong>Disable (Keep Visible with PermissionShield):</strong> Use this when the action is part of a standard page flow (like a "Delete Connection" button). Keeping it visible helps users understand that the feature exists, and the lock badge tells them exactly why they cannot click it and who to contact. | ||
| </li> | ||
| <li> | ||
| <strong>Hide (Remove from Layout):</strong> Use this when the user has absolutely no access to the entire page or section (e.g. an "Admin Console" menu link or a full tab panel that they do not have clearance to view). | ||
| </li> | ||
| </ul> | ||
|
|
||
| <h3>Tooltip versus Card Layouts</h3> | ||
|
|
||
| When displaying permission details using `PermissionSessionContext`, choose the variant based on the integration context: | ||
|
|
||
| <ul> | ||
| <li> | ||
| <strong>Tooltip Layout (default):</strong> Use this inside popovers, hover tooltips, and overlay badges (e.g., within `PermissionShield`) to display compact, dark-background metadata without displacing layout elements. | ||
| </li> | ||
| <li> | ||
| <strong>Card Layout:</strong> Use this when embedding permission details directly into the page layout, such as full-page 403 authorization error layouts, settings sidebars, or container panels. | ||
| </li> | ||
| </ul> | ||
|
|
||
| <a id="best-practices"> | ||
| <h2>Best Practices</h2> | ||
| </a> | ||
|
|
||
| <ul> | ||
| <li> | ||
| <strong>Consistent Badge Placement:</strong> Use `'inline'` (default) to place the lock badge at the center-right of the component (common for text fields, buttons, and inline controls). Use the `'badge'` variant to overlay the badge at the bottom-left corner of the parent component when appropriate (e.g., custom cards, list items, or standalone elements). | ||
| </li> | ||
| <li> | ||
| <strong>Accurate Tooltips:</strong> Ensure the `permissionKey` prop is fully populated with accurate names so the tooltip can display the exact missing keys. | ||
| </li> | ||
| <li> | ||
| <strong>Nested Disabled Controls:</strong> Do not rely solely on the wrapper to block interactions. Set the nested control (e.g. Button) to `disabled` (or `aria-disabled` for custom controls) and handle `preventDefault()` where needed so that default actions, keyboard accessibility, and screen readers behave correctly. | ||
| </li> | ||
| </ul> |
112 changes: 112 additions & 0 deletions
112
src/collections/sistent/components/permission/index.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| --- | ||
| name: "Permission" | ||
| title: "Permission" | ||
| published: true | ||
| component: permission | ||
| description: The PermissionShield component gates and protects interactive actions, buttons, and navigation elements. It displays a visual lock icon overlay or inline badge when a user lacks the necessary permission keys or capabilities. | ||
| --- | ||
|
|
||
| import { PermissionShield, Button, PermissionSessionContext } from "@sistent/sistent"; | ||
|
|
||
| The `PermissionShield` component provides a standard design pattern for feature-level permission gating across applications. Rather than silently hiding disabled elements, it keeps them visible (preserving layout continuity) and overlays a visual lock indicator to explain to users why the action is restricted. | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
| > **Important Security Note:** UI gating is a presentation-layer control only. Client-side checks must not decide access. The backend server and API routes must always enforce authorization on every request. | ||
|
|
||
| <a id="inline-shield-overlay"> | ||
| <h2>Inline Shield Overlay</h2> | ||
| </a> | ||
|
|
||
| The default variant (`'inline'`) wraps any standard action component (like a `Button` or `IconButton`) and places a lock icon badge at the center-right of the target element (serving as an end adornment). When clicked, it shows a detailed explanation of the missing permission. | ||
|
|
||
| <Row className="image-container"> | ||
| <ThemeWrapper> | ||
| <div style={{ display: "flex", gap: "16px", alignItems: "center" }}> | ||
| <PermissionShield | ||
| permissionKey={{ | ||
| id: "delete_connection", | ||
| category: "Lifecycle Management", | ||
| subcategory: "Connections", | ||
| function: "Delete a connection", | ||
| description: "Delete a connection" | ||
| }} | ||
| > | ||
| <Button variant="contained" color="error"> | ||
| Delete Resource | ||
| </Button> | ||
| </PermissionShield> | ||
| </div> | ||
| </ThemeWrapper> | ||
| </Row> | ||
|
|
||
| <a id="badge-variant"> | ||
| <h2>Badge Variant</h2> | ||
| </a> | ||
|
|
||
| The badge variant (`'badge'`) renders the permission badge overlaying the bottom-left corner of the target element. This is useful for list items, settings tables, or static text where placing the shield as an end-adornment on the right is not suitable. | ||
|
|
||
| <Row className="image-container"> | ||
| <ThemeWrapper> | ||
| <div style={{ display: "flex", gap: "16px", alignItems: "center" }}> | ||
| <PermissionShield | ||
| variant="badge" | ||
| permissionKey={{ | ||
| id: "view_audit_logs", | ||
| category: "Events Management", | ||
| subcategory: "Audit", | ||
| function: "View Audit", | ||
| description: "View Audit Logs" | ||
| }} | ||
| > | ||
| <span>Audit Logs</span> | ||
| </PermissionShield> | ||
| </div> | ||
| </ThemeWrapper> | ||
| </Row> | ||
|
|
||
| <a id="permission-session-context"> | ||
| <h2>Permission Session Context</h2> | ||
| </a> | ||
|
|
||
| The `PermissionSessionContext` component renders the detailed authorization metadata (user identity, organization, assigned roles, and missing keys) that is displayed inside tooltips or cards. It supports two layout variants: | ||
|
|
||
| - **Tooltip Variant (`'tooltip'`):** A compact layout designed to fit inside standard hover/click tooltips (used by default inside `PermissionShield`). | ||
| - **Card Variant (`'card'`):** A theme-aware, scaled-up layout designed to be embedded directly into custom cards, sidebars, or full-page 403/Forbidden error screens. | ||
|
|
||
| ### Tooltip Layout | ||
|
|
||
| <Row className="image-container"> | ||
| <ThemeWrapper> | ||
| <div style={{ padding: "16px", background: "#1A1A1A", borderRadius: "8px", maxWidth: "360px", width: "100%" }}> | ||
| <PermissionSessionContext | ||
| variant="tooltip" | ||
| permissionKey={{ | ||
| id: "delete_connection", | ||
| category: "Lifecycle Management", | ||
| subcategory: "Connections", | ||
| function: "Delete a connection", | ||
| description: "Delete a connection" | ||
| }} | ||
| /> | ||
| </div> | ||
| </ThemeWrapper> | ||
| </Row> | ||
|
|
||
| ### Card Layout | ||
|
|
||
| <Row className="image-container"> | ||
| <ThemeWrapper> | ||
| <div style={{ width: "100%", maxWidth: "450px" }}> | ||
| <PermissionSessionContext | ||
| variant="card" | ||
| permissionKey={{ | ||
| id: "delete_connection", | ||
| category: "Lifecycle Management", | ||
| subcategory: "Connections", | ||
| function: "Delete a connection", | ||
| description: "Delete a connection" | ||
| }} | ||
| /> | ||
| </div> | ||
| </ThemeWrapper> | ||
| </Row> | ||
|
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think
boundaryPaddingdoes not exist in the codebase. Can you check again in the layer5io/sistent repo?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The boundaryPadding prop is currently on the fixing-tools branch of the sistent repository introduced in the tooltip responsiveness fixes and will be available once that branch is merged into master