sidebar
The Sidebar component provides a vertical navigation menu with support for nested links, expandable groups, optional footer content, and consumer-controlled active state matching.
Usage
Default
const links = [
{ label: "Dashboard", href: "/dashboard", icon: <FaBook /> },
{
label: "Reports",
href: "/reports",
children: [
{ label: "Monthly", href: "/reports/monthly", icon: <FaCalendar /> },
{ label: "Annual", href: "/reports/annual", icon: <FaCalendar /> },
],
icon: <FaPaperclip />,
},
{ label: "Settings", href: "/settings", icon: <FaCogs /> },
];
const currentPath = "/settings";
const normalizePath = (p: string) =>
p.endsWith("/") && p.length > 1 ? p.slice(0, -1) : p;
const isDescendantPath = (parentPath: string, currentPath: string) => {
const parent = normalizePath(parentPath);
const current = normalizePath(currentPath);
if (parent === "/") return current === "/";
return current === parent || current.startsWith(`${parent}/`);
};
const isActiveRecursive = (link, matcher) => {
if (matcher(link)) return true;
return !!link.children?.some((child) => isActiveRecursive(child, matcher));
};
const isLinkActive = (link) => {
if (!link.href) return false;
if (link.children?.length) {
return isDescendantPath(link.href, currentPath);
}
return normalizePath(link.href) === normalizePath(currentPath);
};
const hasActiveChild = (link) =>
!!link.children?.some((child) => isActiveRecursive(child, isLinkActive));
<Sidebar
links={links}
isLinkActive={isLinkActive}
hasActiveChild={hasActiveChild}
/>
Props
| Type | Description | |
|---|---|---|
| aria-describedby | string | ID reference to one or more elements that describe the sidebar navigation landmark. |
| aria-label | string | Accessible label for the navigation landmark. Prefer the kebab-case ARIA prop for consistency with other React ARIA props. |
| aria-labelledby | string | ID reference to one or more elements that label the sidebar navigation landmark. Takes precedence over aria-label when both are provided. |
| className | string | Additional class name(s) for applying custom styles. |
| data-testid | string | Optional test ID for testing frameworks like Jest and React Testing Library. |
| footerAriaLabel | string | Optional label for the footer landmark when footer content is rendered. Example: "Sidebar footer links" |
| footerAriaLabelledBy | string | Optional ID reference to label the footer landmark. |
| footerLinks | SidebarFooterLink[] | Array of footer links to render when `showFooter` is `true`. |
| footerVersion | string | Optional version string displayed in the sidebar footer. Example: "v1.2.3" |
| getExpandButtonAriaDescription | ((link: SidebarLink, isOpen: boolean) => string) | Optional accessible description generator for expandable parent items. |
| getExpandButtonAriaLabel | ((link: SidebarLink, isOpen: boolean) => string) | Optional accessible label generator for expandable parent items. Useful when you want screen readers to hear something more descriptive than the visible text alone. |
| hasActiveChild | ((link: SidebarLink) => boolean) | Optional callback used to determine whether a link contains an active child. |
| isLinkActive | ((link: SidebarLink) => boolean) | Optional callback used to determine whether a link should be styled as active. |
| links | SidebarLink[] | Array of navigation links to render in the sidebar. Each link may optionally include a nested submenu. |
| outline | boolean | If true, the sidebar is styled with an outline variant. Defaults to `false`. |
| rounding | RoundingType | Rounding style for the sidebar container. - "none" | "small" | "medium" | "large" | "full" |
| shadow | ShadowType | Shadow style for the sidebar container. - "none" | "light" | "medium" | "strong" | "intense" |
| showFooter | boolean | Whether to display a footer section at the bottom of the sidebar. Defaults to `false`. |
| state | StateType | State variant for styling. Typically used to apply semantic states to the component. - "success" | "error" | "warning" | "disabled" | "" |
| theme | ThemeType | Theme for styling. Determines the base color scheme for the sidebar. - "primary" | "secondary" | "tertiary" | "quaternary" | "clear" |