A collapsible group for organizing navigation items in the sidebar. Supports nested groups, clickable headers, and internationalization.
Import
import { SidebarGroup } from "@tailor-platform/app-shell";
Usage
Basic group
import { SidebarGroup, SidebarItem } from "@tailor-platform/app-shell";
import { Package } from "lucide-react";
<SidebarGroup title="Products" icon={<Package />}>
<SidebarItem to="/products/all" />
<SidebarItem to="/products/categories" />
</SidebarGroup>
When you specify a to prop, the group title becomes a clickable link:
import { Settings } from "lucide-react";
<SidebarGroup title="Settings" icon={<Settings />} to="/settings">
<SidebarItem to="/settings/profile" />
<SidebarItem to="/settings/security" />
</SidebarGroup>
Initially collapsed
Control the initial expanded state with defaultOpen:
<SidebarGroup title="Archives" defaultOpen={false}>
<SidebarItem to="/archives/2024" />
<SidebarItem to="/archives/2023" />
</SidebarGroup>
Nested groups
You can nest SidebarGroup components for hierarchical navigation:
import { Package } from "lucide-react";
<SidebarGroup title="Products" icon={<Package />}>
<SidebarItem to="/products/all" />
<SidebarGroup title="Archives" defaultOpen={false}>
<SidebarItem to="/products/archives/2024" />
<SidebarItem to="/products/archives/2023" />
</SidebarGroup>
</SidebarGroup>
Props
Group title. Supports internationalization via LocalizedString.
Group icon displayed next to the title.
When specified, the title becomes a clickable link to this URL.
Initial expanded state. Set to false to render the group collapsed by default.
Child items - typically SidebarItem, nested SidebarGroup, or SidebarSeparator components.
Internationalization
Group titles support localized strings using defineI18nLabels:
import { defineI18nLabels, SidebarGroup } from "@tailor-platform/app-shell";
import { Package } from "lucide-react";
const labels = defineI18nLabels({
en: { products: "Products" },
ja: { products: "製品" },
});
<SidebarGroup title={labels.t("products")} icon={<Package />}>
<SidebarItem to="/products/all" />
</SidebarGroup>
You can also pass a plain string:
<SidebarGroup title="Products" icon={<Package />}>
<SidebarItem to="/products/all" />
</SidebarGroup>
Examples
Multi-level navigation
import {
DefaultSidebar,
SidebarGroup,
SidebarItem,
SidebarSeparator,
} from "@tailor-platform/app-shell";
import { Package, Settings, Shield } from "lucide-react";
const CustomSidebar = () => (
<DefaultSidebar>
<SidebarItem to="/dashboard" />
<SidebarSeparator />
<SidebarGroup title="Products" icon={<Package />}>
<SidebarItem to="/products/all" />
<SidebarItem to="/products/categories" />
<SidebarGroup title="Archives" defaultOpen={false}>
<SidebarItem to="/products/archives/2024" />
<SidebarItem to="/products/archives/2023" />
</SidebarGroup>
</SidebarGroup>
<SidebarGroup title="Settings" icon={<Settings />} to="/settings">
<SidebarItem to="/settings/profile" />
<SidebarItem to="/settings/security" />
</SidebarGroup>
</DefaultSidebar>
);
With access control
Combine with WithGuard to conditionally show groups based on permissions:
import { WithGuard, pass, hidden } from "@tailor-platform/app-shell";
import { Shield } from "lucide-react";
const isAdminGuard = ({ context }) =>
context.currentUser.role === "admin" ? pass() : hidden();
<DefaultSidebar>
<SidebarItem to="/dashboard" />
<WithGuard guards={[isAdminGuard]}>
<SidebarGroup title="Admin" icon={<Shield />}>
<SidebarItem to="/admin/users" />
<SidebarItem to="/admin/settings" />
</SidebarGroup>
</WithGuard>
</DefaultSidebar>
Internationalized navigation
import { defineI18nLabels } from "@tailor-platform/app-shell";
const labels = defineI18nLabels({
en: {
products: "Products",
allProducts: "All Products",
categories: "Categories",
settings: "Settings",
profile: "Profile",
security: "Security",
},
ja: {
products: "製品",
allProducts: "すべての製品",
categories: "カテゴリ",
settings: "設定",
profile: "プロフィール",
security: "セキュリティ",
},
});
<DefaultSidebar>
<SidebarGroup title={labels.t("products")} icon={<Package />}>
<SidebarItem to="/products/all" title={labels.t("allProducts")} />
<SidebarItem to="/products/categories" title={labels.t("categories")} />
</SidebarGroup>
<SidebarGroup
title={labels.t("settings")}
icon={<Settings />}
to="/settings"
>
<SidebarItem to="/settings/profile" title={labels.t("profile")} />
<SidebarItem to="/settings/security" title={labels.t("security")} />
</SidebarGroup>
</DefaultSidebar>