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

Data table
TypeDescription
aria-describedbystringID reference to one or more elements that describe the sidebar navigation landmark.
aria-labelstringAccessible label for the navigation landmark. Prefer the kebab-case ARIA prop for consistency with other React ARIA props.
aria-labelledbystringID reference to one or more elements that label the sidebar navigation landmark. Takes precedence over aria-label when both are provided.
classNamestringAdditional class name(s) for applying custom styles.
data-testidstringOptional test ID for testing frameworks like Jest and React Testing Library.
footerAriaLabelstringOptional label for the footer landmark when footer content is rendered. Example: "Sidebar footer links"
footerAriaLabelledBystringOptional ID reference to label the footer landmark.
footerLinksSidebarFooterLink[]Array of footer links to render when `showFooter` is `true`.
footerVersionstringOptional 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.
linksSidebarLink[]Array of navigation links to render in the sidebar. Each link may optionally include a nested submenu.
outlinebooleanIf true, the sidebar is styled with an outline variant. Defaults to `false`.
roundingRoundingTypeRounding style for the sidebar container. - "none" | "small" | "medium" | "large" | "full"
shadowShadowTypeShadow style for the sidebar container. - "none" | "light" | "medium" | "strong" | "intense"
showFooterbooleanWhether to display a footer section at the bottom of the sidebar. Defaults to `false`.
stateStateTypeState variant for styling. Typically used to apply semantic states to the component. - "success" | "error" | "warning" | "disabled" | ""
themeThemeTypeTheme for styling. Determines the base color scheme for the sidebar. - "primary" | "secondary" | "tertiary" | "quaternary" | "clear"