Library of headless React components and low-level hooks for building accessible user interfaces
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
Components for displaying data including table pagination controls, badges for status indicators, and notification systems.
Comprehensive pagination controls for data tables with customizable page size options and navigation.
/**
* Pagination controls for data tables with customizable options
* @param props - Table pagination properties including count and page handlers
* @returns Pagination element with navigation controls and page size selector
*/
function TablePagination<RootComponentType extends React.ElementType = "div">(
props: TablePaginationProps<RootComponentType>
): JSX.Element;
interface TablePaginationProps<RootComponentType extends React.ElementType = "div">
extends PolymorphicProps<TablePaginationTypeMap, RootComponentType> {
/** Total number of rows */
count: number;
/** Function to get ARIA label for navigation buttons */
getItemAriaLabel?: (type: 'first' | 'last' | 'next' | 'previous') => string;
/** Function to customize displayed rows text */
labelDisplayedRows?: (paginationInfo: { from: number; to: number; count: number }) => React.ReactNode;
/** Label for rows per page selector */
labelRowsPerPage?: React.ReactNode;
/** Page change callback */
onPageChange: (event: React.MouseEvent<HTMLButtonElement> | null, page: number) => void;
/** Rows per page change callback */
onRowsPerPageChange?: (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
/** Current page number (0-indexed) */
page: number;
/** Number of rows per page */
rowsPerPage: number;
/** Available rows per page options */
rowsPerPageOptions?: ReadonlyArray<number | { value: number; label: string }>;
/** Whether to show first page button */
showFirstButton?: boolean;
/** Whether to show last page button */
showLastButton?: boolean;
/** Props for customizing table pagination slots */
slotProps?: {
root?: SlotComponentProps<TablePaginationSlots["root"], {}, TablePaginationOwnerState>;
toolbar?: SlotComponentProps<TablePaginationSlots["toolbar"], {}, TablePaginationOwnerState>;
spacer?: SlotComponentProps<TablePaginationSlots["spacer"], {}, TablePaginationOwnerState>;
selectLabel?: SlotComponentProps<TablePaginationSlots["selectLabel"], {}, TablePaginationOwnerState>;
selectRoot?: SlotComponentProps<TablePaginationSlots["selectRoot"], {}, TablePaginationOwnerState>;
select?: SlotComponentProps<TablePaginationSlots["select"], {}, TablePaginationOwnerState>;
selectIcon?: SlotComponentProps<TablePaginationSlots["selectIcon"], {}, TablePaginationOwnerState>;
input?: SlotComponentProps<TablePaginationSlots["input"], {}, TablePaginationOwnerState>;
menuItem?: SlotComponentProps<TablePaginationSlots["menuItem"], {}, TablePaginationOwnerState>;
displayedRows?: SlotComponentProps<TablePaginationSlots["displayedRows"], {}, TablePaginationOwnerState>;
actions?: SlotComponentProps<TablePaginationSlots["actions"], {}, TablePaginationOwnerState>;
firstButton?: SlotComponentProps<TablePaginationSlots["firstButton"], {}, TablePaginationOwnerState>;
lastButton?: SlotComponentProps<TablePaginationSlots["lastButton"], {}, TablePaginationOwnerState>;
nextButton?: SlotComponentProps<TablePaginationSlots["nextButton"], {}, TablePaginationOwnerState>;
previousButton?: SlotComponentProps<TablePaginationSlots["previousButton"], {}, TablePaginationOwnerState>;
};
/** Components used for table pagination slots */
slots?: TablePaginationSlots;
}
interface TablePaginationSlots {
/** Root container element */
root?: React.ElementType;
/** Toolbar container element */
toolbar?: React.ElementType;
/** Spacer element for layout */
spacer?: React.ElementType;
/** Label for rows per page selector */
selectLabel?: React.ElementType;
/** Root element for rows per page selector */
selectRoot?: React.ElementType;
/** Select element for rows per page */
select?: React.ElementType;
/** Icon for rows per page selector */
selectIcon?: React.ElementType;
/** Input element for rows per page selector */
input?: React.ElementType;
/** Menu item for rows per page options */
menuItem?: React.ElementType;
/** Element displaying current page info */
displayedRows?: React.ElementType;
/** Container for navigation actions */
actions?: React.ElementType;
/** First page button */
firstButton?: React.ElementType;
/** Last page button */
lastButton?: React.ElementType;
/** Next page button */
nextButton?: React.ElementType;
/** Previous page button */
previousButton?: React.ElementType;
}
interface TablePaginationOwnerState {
count: number;
page: number;
rowsPerPage: number;
showFirstButton: boolean;
showLastButton: boolean;
}Usage Examples:
import { TablePagination } from "@mui/base/TablePagination";
// Basic table pagination
<TablePagination
count={totalRows}
page={currentPage}
rowsPerPage={pageSize}
onPageChange={(event, newPage) => setCurrentPage(newPage)}
onRowsPerPageChange={(event) => setPageSize(parseInt(event.target.value))}
/>
// Customized table pagination
<TablePagination
count={1000}
page={page}
rowsPerPage={rowsPerPage}
rowsPerPageOptions={[10, 25, 50, { value: 100, label: '100 rows' }]}
onPageChange={handlePageChange}
onRowsPerPageChange={handleRowsPerPageChange}
showFirstButton
showLastButton
labelRowsPerPage="Items per page:"
labelDisplayedRows={({ from, to, count }) =>
`${from}–${to} of ${count !== -1 ? count : `more than ${to}`}`
}
getItemAriaLabel={(type) => {
switch (type) {
case 'first': return 'Go to first page';
case 'last': return 'Go to last page';
case 'next': return 'Go to next page';
case 'previous': return 'Go to previous page';
default: return '';
}
}}
/>Badge component for displaying status indicators, counts, and notifications.
/**
* Badge component for status indicators and counts
* @param props - Badge properties including content and visibility options
* @returns Badge element positioned relative to children
*/
function Badge<RootComponentType extends React.ElementType = "span">(
props: BadgeProps<RootComponentType>
): JSX.Element;
interface BadgeProps<RootComponentType extends React.ElementType = "span">
extends PolymorphicProps<BadgeTypeMap, RootComponentType> {
/** Content rendered within the badge */
badgeContent?: React.ReactNode;
/** The badge will be added relative to this node */
children?: React.ReactNode;
/** If true, the badge is invisible */
invisible?: boolean;
/** Max count to show (default: 99) */
max?: number;
/** Controls whether badge is hidden when badgeContent is zero */
showZero?: boolean;
/** Props for customizing badge slots */
slotProps?: {
root?: SlotComponentProps<BadgeSlots["root"], {}, BadgeOwnerState>;
badge?: SlotComponentProps<BadgeSlots["badge"], {}, BadgeOwnerState>;
};
/** Components used for badge slots */
slots?: BadgeSlots;
}
interface BadgeSlots {
/** Root container element */
root?: React.ElementType;
/** Badge indicator element */
badge?: React.ElementType;
}
interface BadgeOwnerState {
badgeContent: React.ReactNode;
invisible: boolean;
max: number;
showZero: boolean;
}Usage Examples:
import { Badge } from "@mui/base/Badge";
// Basic badge with count
<Badge badgeContent={4}>
<MailIcon />
</Badge>
// Badge with maximum count
<Badge badgeContent={100} max={99}>
<NotificationIcon />
</Badge>
// Badge that shows zero
<Badge badgeContent={0} showZero>
<ShoppingCartIcon />
</Badge>
// Custom styled badge
<Badge
badgeContent="NEW"
slotProps={{
root: { className: "badge-root" },
badge: { className: "badge-indicator" }
}}
>
<ProductItem />
</Badge>
// Invisible badge (hidden)
<Badge badgeContent={5} invisible>
<MessageIcon />
</Badge>Toast notification component with automatic dismissal and positioning.
/**
* Toast notification component with auto-hide functionality
* @param props - Snackbar properties including content and timing
* @returns Snackbar element with notification display
*/
function Snackbar<RootComponentType extends React.ElementType = "div">(
props: SnackbarProps<RootComponentType>
): JSX.Element;
interface SnackbarProps<RootComponentType extends React.ElementType = "div">
extends PolymorphicProps<SnackbarTypeMap, RootComponentType> {
/** Time in milliseconds to auto-hide (default: null) */
autoHideDuration?: number | null;
/** Snackbar content */
children?: React.ReactNode;
/** Whether snackbar is fully exited from view */
exited?: boolean;
/** Close event handler */
onClose?: (event: Event | React.SyntheticEvent<any> | null, reason: SnackbarCloseReason) => void;
/** Whether snackbar is visible */
open?: boolean;
/** Time left before auto-hide when resuming */
resumeHideDuration?: number;
}
type SnackbarCloseReason = 'timeout' | 'clickaway' | 'escapeKeyDown';Usage Examples:
import { Snackbar } from "@mui/base/Snackbar";
// Basic success notification
<Snackbar
open={showSuccess}
autoHideDuration={4000}
onClose={() => setShowSuccess(false)}
>
<div className="snackbar-success">
Operation completed successfully!
</div>
</Snackbar>
// Error notification that doesn't auto-hide
<Snackbar
open={showError}
onClose={(event, reason) => {
console.log('Closed due to:', reason);
setShowError(false);
}}
>
<div className="snackbar-error">
<span>Error: Something went wrong!</span>
<button onClick={() => setShowError(false)}>×</button>
</div>
</Snackbar>
// Notification with pause/resume on hover
function SnackbarWithHover() {
const [open, setOpen] = useState(true);
const [resumeDuration, setResumeDuration] = useState<number | undefined>();
return (
<Snackbar
open={open}
autoHideDuration={5000}
resumeHideDuration={resumeDuration}
onClose={() => setOpen(false)}
onMouseEnter={() => setResumeDuration(0)} // Pause auto-hide
onMouseLeave={() => setResumeDuration(undefined)} // Resume auto-hide
>
<div className="snackbar-content">
Hover to pause auto-hide
</div>
</Snackbar>
);
}// Example pattern for managing multiple notifications
interface Notification {
id: string;
message: string;
type: 'success' | 'error' | 'warning' | 'info';
duration?: number;
}
function NotificationSystem() {
const [notifications, setNotifications] = useState<Notification[]>([]);
const addNotification = (notification: Omit<Notification, 'id'>) => {
const id = Math.random().toString(36);
setNotifications(prev => [...prev, { ...notification, id }]);
};
const removeNotification = (id: string) => {
setNotifications(prev => prev.filter(n => n.id !== id));
};
return (
<>
{notifications.map(notification => (
<Snackbar
key={notification.id}
open={true}
autoHideDuration={notification.duration || 4000}
onClose={() => removeNotification(notification.id)}
>
<div className={`snackbar-${notification.type}`}>
{notification.message}
</div>
</Snackbar>
))}
</>
);
}// Example pattern for dynamic badge content
function NotificationBadge({ notifications }: { notifications: any[] }) {
const unreadCount = notifications.filter(n => !n.read).length;
const hasHighPriority = notifications.some(n => n.priority === 'high' && !n.read);
return (
<Badge
badgeContent={hasHighPriority ? '!' : unreadCount}
invisible={unreadCount === 0}
showZero={false}
max={99}
slotProps={{
badge: {
className: hasHighPriority ? 'badge-urgent' : 'badge-normal'
}
}}
>
<BellIcon />
</Badge>
);
}// Badge display logic hook
function useBadge(parameters: UseBadgeParameters): UseBadgeReturnValue;
interface UseBadgeParameters {
badgeContent?: React.ReactNode;
invisible?: boolean;
max?: number;
showZero?: boolean;
}
interface UseBadgeReturnValue {
badgeContent: React.ReactNode;
invisible: boolean;
max: number;
displayValue: React.ReactNode;
}
// Snackbar lifecycle management hook
function useSnackbar(parameters: UseSnackbarParameters): UseSnackbarReturnValue;
interface UseSnackbarParameters {
autoHideDuration?: number | null;
disableWindowBlurListener?: boolean;
exited?: boolean;
onClose?: (event: Event | React.SyntheticEvent<any> | null, reason: SnackbarCloseReason) => void;
open?: boolean;
resumeHideDuration?: number;
}
interface UseSnackbarReturnValue {
getRootProps: () => {
onBlur: React.FocusEventHandler;
onFocus: React.FocusEventHandler;
onMouseEnter: React.MouseEventHandler;
onMouseLeave: React.MouseEventHandler;
};
}