Skip to main content

Header & Sidebar

Header and Sidebar are consumed via the Layout component — you do not render them directly. Pass their configuration through Layout's headerProps and sidebarProps.

The top navigation bar. It contains the application switcher, breadcrumbs, organization context switcher, and the user account menu (profile, theme customisation, logout).

Key headerProps fields

FieldTypeDescription
userInfo{ email, username }Shown in the account menu
onLogout() => voidCalled when the user clicks Logout
onViewProfileClick() => voidCalled when the user clicks View Profile
appsQuery{ isLoading, error, data }Applications list for the app-switcher
breadcrumbsPropsBreadcrumbsPropsMenu items, active path, and navigate handler for breadcrumb generation
organizationContextPropsOrgContextPropsOrganization list, current org, and change handler
textOverridesobjectTranslatable labels for all header UI strings
onDrawerToggle() => voidInternal — wired by Layout. Pass () => {} when composing manually

Example

src/layout/AppLayout.tsx
headerProps={{
userInfo: {
email: profileQuery.data?.body?.email || "",
username: profileQuery.data?.body?.userName || "",
},
onLogout: handleLogout,
onViewProfileClick: () => navigate("/profile"),
appsQuery: {
isLoading: appsQuery.isLoading,
error: appsQuery.error,
data: (appsQuery.data?.body as any) || [],
},
breadcrumbsProps: {
menuItems: mappedMenuItems,
onNavigate: (path) => navigate(path),
currentPathname: pathname,
initBreadcrumbs: [
{ label: t("common.dashboard"), path: "/dashboard", icon: <DashboardIcon /> },
],
actionsLabel: {
edit: t("common.edit"),
view: t("common.view"),
new: t("common.new"),
},
},
organizationContextProps: {
organizations: orgsQuery.data?.body?.map((org) => ({
id: org.id || 0,
name: language === "en" ? org.englishName || "" : org.arabicName || "",
})) || [],
currentOrganization: currentOrg
? { id: currentOrg.id || 0, name: language === "en" ? currentOrg.englishName : currentOrg.arabicName }
: null,
isLoading: orgsQuery.isLoading,
error: orgsQuery.error,
onOrganizationChange: handleOrganizationChange,
textOverrides: {
switchOrganization: t("authorization.organization"),
currentOrganization: t("authorization.currentOrganization"),
noOrganizations: t("authorization.noOrganizations"),
},
},
textOverrides: {
accountInfo: t("appLayout.accountInfo"),
themeCustomization: t("appLayout.themeCustomization.title"),
accountMenuTextOverrides: {
profile: t("appLayout.profile"),
logout: t("common.logout"),
darkMode: t("appLayout.darkMode"),
lightMode: t("appLayout.lightMode"),
},
},
onDrawerToggle: () => {},
}}

The collapsible side navigation drawer. Reads menu items from a menuQuery (RTK Query result) and a local menuItems map, then renders labelled nav entries with icons. Highlights the active route automatically from currentPath.

Key sidebarProps fields

FieldTypeDescription
currentPathstringActive route pathname — used to highlight the current nav item
languagestringCurrent language ("en" or "ar") for label lookup
onNavigate(path) => voidCalled when a nav item is clicked
menuQuery{ isLoading, error, data }Remote menu from your API
menuItemsRecord<string, any>Local icon + translation-key map keyed by route path
sidebarLogoProps{ appName, appIcon }App name and icon shown at the top of the sidebar
openbooleanControlled open/closed (managed by Layout internally)
onClose() => voidCalled when the sidebar requests to close (managed by Layout)
contextSwitcherPropsContextSwitcherPropsApp-context switcher (shows available apps, handles switching)
appsQuery{ isLoading, error, data }Applications list for the context switcher
textOverridesobject{ appName, appVersion, mainMenuHeader }

Example

src/layout/AppLayout.tsx
sidebarProps={{
currentPath: pathname,
language: language,
onNavigate: (path) => navigate(path),
menuQuery: {
isLoading: menuQuery.isLoading,
error: menuQuery.error,
data: menuQuery.data?.body || [],
},
menuItems: menuItems as Record<string, any>,
sidebarLogoProps: {
appName: "MyApp",
appIcon: <DnsIcon fontSize="small" />,
},
open: true,
onClose: () => {},
textOverrides: {
appName: "MyApp",
appVersion: "1.0.0",
mainMenuHeader: t("common.mainMenu"),
},
contextSwitcherProps: {
contexts: appsQuery.data?.body?.map((app) => ({
id: app.id || 0,
name: app.name || "Unknown",
icon: <AppIcon />,
})) || [],
initialContext: {
id: currentApp?.id || 0,
name: currentApp?.name || "Unknown",
icon: <AppIcon />,
},
universalContext: {
id: config.applicationClientId,
name: t("common.allApps"),
icon: <AppsIcon sx={{ fill: "#fff" }} />,
},
menuLevel: 2,
onMenuLevelChange: handleMenuLevelChange,
onContextLevelChange: handleContextLevelChange,
textOverrides: {
contextDropdown: t("common.currentApp"),
},
},
appsQuery: {
isLoading: appsQuery.isLoading,
error: appsQuery.error,
data: (appsQuery.data?.body as any) || [],
},
}}

See also