User management modals
Modal dialogs for user CRUD operations
These modal components handle user creation, editing, and confirmation dialogs. While they are designed to be used within
RBACControlSettings the three modal components can stand alone:
AddUserModal: create new users with form validation.ManageUserModal: edit users and view effective permissions.ChangeConfirmationModal: confirm destructive or important actions.
AddUserModal
Create new users with form validation.
import { AddUserModal } from '@mdk/foundation'Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Required: Whether the modal is visible |
roles | array | — | Required: Available roles for selection |
onSubmit | function | — | Required: Called with form data on submit |
onClose | function | — | Required: Called when modal should close |
isSubmitting | boolean | false | Shows loading state on submit button |
RoleOption structure
| Property | Type | Description |
|---|---|---|
value | string | Role identifier |
label | string | Display name |
Callbacks
The onSubmit callback receives the validated form data:
const handleSubmit = async (data) => {
// data: { name: string, email: string, role: string }
await api.createUser(data) // persist to backend
refetchUsers() // refresh list
}The modal resets its form after successful submission.
Example
function UserActions() {
const [isOpen, setIsOpen] = useState(false)
const handleSubmit = async (data) => {
await api.createUser(data)
setIsOpen(false)
}
return (
<>
<Button onClick={() => setIsOpen(true)}>Add User</Button>
<AddUserModal
open={isOpen}
onClose={() => setIsOpen(false)}
roles={[
{ value: 'admin', label: 'Admin' },
{ value: 'operator', label: 'Operator' },
]}
onSubmit={handleSubmit}
/>
</>
)
}Form fields
- Name: required, trimmed
- Email: required, must be valid email
- Role: required, select from available roles
Validation uses Zod schema with react-hook-form. The modal displays Add User and Cancel buttons.
ManageUserModal
Edit existing user details and view their effective permissions.
import { ManageUserModal } from '@mdk/foundation'Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Required: Whether the modal is visible |
user | SettingsUser | — | Required: User being edited |
roles | array | — | Required: Available roles |
rolePermissions | object | — | Required: Permissions by role |
permissionLabels | object | — | Required: Permission display names |
onSubmit | function | — | Required: Called with updated data on submit |
onClose | function | — | Required: Called when modal should close |
isSubmitting | boolean | false | Shows loading state on submit button |
Data structures
The rolePermissions object maps role IDs to their permissions:
const rolePermissions = {
admin: { users: 'rw', settings: 'rw', reports: 'r' },
operator: { users: 'r', settings: 'none', reports: 'r' }
}The permissionLabels object provides display names:
const permissionLabels = {
users: 'User Management',
settings: 'System Settings',
reports: 'Reports'
}Callbacks
The onSubmit callback receives the updated user data:
const handleSubmit = async (data) => {
// data: { id: string, name: string, email: string, role: string }
await api.updateUser(data) // persist to backend
refetchUsers() // refresh list
}Example
function UserRow({ user }) {
const [isEditing, setIsEditing] = useState(false)
const handleSubmit = async (data) => {
await api.updateUser(data)
setIsEditing(false)
}
return (
<>
<Button onClick={() => setIsEditing(true)}>Manage</Button>
<ManageUserModal
open={isEditing}
onClose={() => setIsEditing(false)}
user={user}
roles={roles}
rolePermissions={rolePermissions}
permissionLabels={permissionLabels}
onSubmit={handleSubmit}
/>
</>
)
}Sections
The modal is divided into three sections:
- User Information: edit name and email.
- Assigned Role: select role from dropdown.
- Effective Permissions: read-only table showing what the selected role can do.
Permission icons
Permissions display icons based on level:
rw: Read/Write (full access)r: Read (view only)none: No access
The modal displays Save Changes and Cancel buttons.
ChangeConfirmationModal
A reusable confirmation dialog for destructive or important actions.
import { ChangeConfirmationModal } from '@mdk/foundation'Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Required: Whether the modal is visible |
title | string | — | Required: Modal title |
children | ReactNode | — | Modal body content |
onConfirm | function | — | Required: Called when end user confirms |
onClose | function | — | Required: Called when end user cancels or closes |
confirmText | string | 'Confirm' | Text for confirm button |
destructive | boolean | false | Use danger styling (red button) |
Example
function DeleteButton({ user }) {
const [showConfirm, setShowConfirm] = useState(false)
const handleDelete = async () => {
await api.deleteUser(user.id)
setShowConfirm(false)
}
return (
<>
<Button onClick={() => setShowConfirm(true)}>Delete</Button>
<ChangeConfirmationModal
open={showConfirm}
title={`Delete ${user.email}?`}
onClose={() => setShowConfirm(false)}
onConfirm={handleDelete}
confirmText="Delete"
destructive
>
Are you sure you want to delete this user? This action is permanent
and cannot be undone.
</ChangeConfirmationModal>
</>
)
}Variants
Standard confirmation
<ChangeConfirmationModal
title="Save Changes?"
confirmText="Save"
destructive={false}
>
Your changes will be applied immediately.
</ChangeConfirmationModal>Destructive confirmation
<ChangeConfirmationModal
title="Delete Item?"
confirmText="Delete"
destructive
>
This action cannot be undone.
</ChangeConfirmationModal>The modal displays a Cancel button alongside the configurable confirm button.
Dependencies
All user management modals depend on @mdk/core components:
Dialog,DialogContent,DialogFooterButtonForm,FormInput,FormSelect
They also use:
react-hook-formfor form statezodfor validation@hookform/resolversfor Zod integration

