UI hooks
Hooks for application state, permissions, and UI patterns
@mdk/foundation
Hooks for managing application state, user permissions, notifications, and common UI patterns.
import {
useNotification,
useHasPerms,
useCheckPerm,
useHeaderControls,
useLocalStorage,
usePagination,
useIsFeatureEditingEnabled,
} from '@mdk/foundation'
@mdk/foundation
Show toast notifications with Redux integration. Supports success, error, info, and warning variants.
import { useNotification } from '@mdk/foundation'
| Method | Type | Description |
|---|
notifySuccess | function | Show success toast |
notifyError | function | Show error toast |
notifyInfo | function | Show info toast |
notifyWarning | function | Show warning toast |
notifySuccess(message: string, description?: string, options?: NotificationOptions)
| Option | Type | Default | Description |
|---|
duration | number | 3000 | Duration in milliseconds (0 = no autoclose) |
position | ToastPosition | 'top-left' | Toast position on screen |
dontClose | boolean | false | Prevent autoclose |
function SaveButton() {
const { notifySuccess, notifyError } = useNotification()
const handleSave = async () => {
try {
await saveData()
notifySuccess('Saved', 'Your changes have been saved.')
} catch (error) {
notifyError('Error', 'Failed to save changes.', { dontClose: true })
}
}
return <Button onClick={handleSave}>Save</Button>
}
@mdk/foundation
Check user permissions with a flexible API. Returns a function that accepts various permission formats.
import { useHasPerms } from '@mdk/foundation'
| Type | Description |
|---|
(req: PermissionRequest) => boolean | Function to check permissions |
| Format | Example | Description |
|---|
| String | 'users:read' | Check single permission |
| Array | ['users:write', 'users:read'] | Check first permission in array |
| Object | { perm: 'users:write' } | Check permission property |
| Object | { write: true } | Check write capability |
| Object | { cap: 'admin' } | Check capability |
function UserActions() {
const hasPerms = useHasPerms()
return (
<div>
{hasPerms('users:read') && <UserList />}
{hasPerms({ write: true }) && <CreateButton />}
{hasPerms({ cap: 'admin' }) && <AdminPanel />}
</div>
)
}
@mdk/foundation
Check a specific permission. Simpler API than useHasPerms for single permission checks.
import { useCheckPerm } from '@mdk/foundation'
| Parameter | Type | Description |
|---|
perm | string | Permission string to check (e.g., 'users:read') |
write | boolean | Whether write access is required |
cap | string | Capability to check (e.g., 'admin') |
| Type | Description |
|---|
boolean | true if user has the permission |
function UserManagement() {
const canRead = useCheckPerm({ perm: 'users:read' })
const canWrite = useCheckPerm({ write: true })
const isAdmin = useCheckPerm({ cap: 'admin' })
return (
<div>
{canRead && <UserList />}
{canWrite && <CreateButton />}
{isAdmin && <AdminPanel />}
</div>
)
}
@mdk/foundation
Manage header visibility preferences with localStorage persistence and notifications.
import { useHeaderControls } from '@mdk/foundation'
| Property | Type | Description |
|---|
preferences | HeaderPreferences | Current visibility state for each header item |
isLoading | boolean | Loading state |
error | Error | null | Error state |
handleToggle | function | Toggle a header item visibility |
handleReset | function | Reset to default preferences |
function HeaderSettings() {
const { preferences, handleToggle, handleReset } = useHeaderControls()
return (
<div>
{Object.entries(preferences).map(([key, visible]) => (
<Toggle
key={key}
label={key}
checked={visible}
onChange={(value) => handleToggle(key, value)}
/>
))}
<Button onClick={handleReset}>Reset to Default</Button>
</div>
)
}
@mdk/foundation
Type-safe localStorage access with cross-tab synchronization.
import { useLocalStorage } from '@mdk/foundation'
| Parameter | Type | Description |
|---|
key | string | Required: localStorage key |
defaultValue | T | Required: Fallback value when key is missing |
| Index | Type | Description |
|---|
[0] | T | Current stored value |
[1] | function | Set value (accepts value or updater function) |
[2] | function | Remove value from storage |
function ThemeToggle() {
const [theme, setTheme, removeTheme] = useLocalStorage('theme', 'dark')
return (
<div>
<p>Current theme: {theme}</p>
<Button onClick={() => setTheme('light')}>Light</Button>
<Button onClick={() => setTheme('dark')}>Dark</Button>
<Button onClick={() => setTheme((prev) => prev === 'dark' ? 'light' : 'dark')}>
Toggle
</Button>
<Button onClick={removeTheme}>Reset</Button>
</div>
)
}
@mdk/foundation
Manage pagination state with API query arguments (limit/offset pattern).
import { usePagination } from '@mdk/foundation'
| Option | Type | Default | Description |
|---|
current | number | 1 | Initial page number |
pageSize | number | 20 | Items per page |
total | number | — | Initial total count |
showSizeChanger | boolean | true | Show page size selector |
| Property | Type | Description |
|---|
pagination | object | Current pagination state |
queryArgs | { limit, offset } | Query arguments for API calls |
setPagination | function | Update pagination state |
handleChange | function | Handle page/size change |
reset | function | Reset to initial state |
setTotal | function | Update total count |
hideNextPage | function | Hide next page when data exhausted |
function MinerList() {
const { pagination, queryArgs, handleChange } = usePagination({
current: 1,
pageSize: 20,
})
const { data } = useQuery(['miners', queryArgs], () =>
api.getMiners(queryArgs.limit, queryArgs.offset)
)
return (
<div>
<Table data={data} />
<Pagination {...pagination} onChange={handleChange} />
</div>
)
}
@mdk/foundation
Check if the current user has permission to edit feature flags.
import { useIsFeatureEditingEnabled } from '@mdk/foundation'
| Type | Description |
|---|
boolean | true if user has the 'features' capability |
function FeaturePanel() {
const canEditFeatures = useIsFeatureEditingEnabled()
if (!canEditFeatures) {
return <p>You don't have permission to edit features.</p>
}
return <FeatureFlagsSettings {...props} />
}