import type { ElementType } from "react"; /** Footer identity block (UserFooter); avatar falls back to initials derived from name when absent. */ export type SidebarUser = { /** Display name; initials derive from it when `initials` is absent. */ name: string; /** Muted line under the name. */ role?: string; /** Avatar image; initials are shown when absent. */ avatarUrl?: string; /** Overrides the initials derived from `name` when there is no avatar image. */ initials?: string; /** Called when the footer identity block is pressed. */ onClick?: () => void; }; /** Docked/collapsible left rail with its own responsive overlay — not NavigationBar (top bar) or WorkspaceWindow (floating panel). */ export type SidebarProps = { /** Rows in display order; items with a `group` get section labels and must be pre-sorted by it. */ menus: MenuProps[]; /** Matched against each menu's `title` first, then `id` — a title that collides with another menu's `id` wins silently. */ activeMenu: string | number; /** Called with the menu when a row is chosen; in the overlay a leaf row also closes it. */ handleMenuClick?: (menu: MenuProps) => void; /** Called with the item chosen in the SecondaryBar flyout. */ handleSecondaryNavClick?: (menu: MenuProps) => void; /** True collapses the inline rail to icons; false shows it fully expanded. */ toggle: boolean; /** Called to flip `toggle`: by the header and footer collapse controls, and automatically when `autoCollapse` is on. */ changeToggle: () => void; /** Falls back to a rendered brand mark (DefaultLogo) tinted by primary color when omitted. */ logo?: string; /** Name shown beside the logo; hidden while the rail is collapsed. */ companyName: string; /** Muted line under `companyName`. */ companySubtitle?: string; /** Footer identity block is omitted entirely (not just simplified) when this is not provided. */ user?: SidebarUser; /** true hides the Add New row completely, rather than disabling it. */ isDisableAddNew?: boolean; /** Called when the Add New row is pressed. */ onAddNewClick?: () => void; /** @deprecated Dead — threaded down to MenuItemBox but never read there; no known consumer usage. */ selectedSubMenu?: string | null; /** Id or title of the highlighted item in the SecondaryBar flyout. */ selectedSecondaryItem?: string | number | null; /** Shows skeleton rows instead of MenuItems; header and footer render normally. */ isLoading?: boolean; /** Defaults to 15 when isLoading is true; ignored otherwise. */ loadingLines?: number; /** Not a direct render switch — on change it calls `changeToggle()` once; nothing collapses unless that updates `toggle`. */ open?: boolean; /** Legacy "Switch app" grid — AppSwitcher supersedes it; avoid wiring both into one shell. */ otherApps?: OtherAppsProps['otherApps']; /** Controls the overlay's visibility below `lg`; no effect once inline at `lg`+. Wire to NavigationBar's `onSideBarToggole`. */ mobileOpen?: boolean; /** Called when the overlay is dismissed (backdrop click, Esc, close button, or swipe). */ onMobileClose?: () => void; /** Forces overlay presentation at any width — a layout switch, not a close; never hides navigation. */ mobileNav?: boolean; /** Backs the footer Hide/Show control; render it only when this is provided. */ onToggleMobileNav?: () => void; /** Shows the sidebar without pinning — closes on pointer-leave. Wire to NavigationBar's `onSideBarPeek`. */ peekOpen?: boolean; /** Called when the pointer leaves a peeked overlay, so the host can clear `peekOpen`. */ onPeekEnd?: () => void; /** Rendered above `menus` under a `pinnedLabel` heading; the whole block is omitted when empty. */ pinnedItems?: SidebarPinnedItem[]; /** Heading above the pinned block; defaults to "Pinned". */ pinnedLabel?: string; /** Shows an unpin button on row hover/focus (always visible in the overlay); omit for read-only rows. */ onUnpin?: (item: SidebarPinnedItem) => void; /** Matched against pinned ids for the active state; while it matches, the same id in `menus` is not highlighted. */ activePinnedId?: string | number | null; /** Rows shown before the rest collapse behind a "Show N more" row; defaults to 5. */ pinnedLimit?: number; /** Overrides for the pinned block's strings; `{count}` and `{title}` are substituted. */ pinnedLabels?: SidebarPinnedLabels; /** Inline (`lg`+) collapse/expand animation; defaults to `{ speed: "base" }` (200ms). Overlay slide is unaffected. */ collapseTransition?: SidebarCollapseTransition; /** Defaults to true: a menu with `secondaryItems` (and the `open` prop) call `changeToggle` for you. False: `toggle` alone decides. */ autoCollapse?: boolean; }; /** One pinned shortcut row; the same fields as a menu item, minus the lock/disabled/submenu states. */ export type SidebarPinnedItem = Pick; /** Strings for the pinned block; every key is optional and falls back to English. */ export type SidebarPinnedLabels = { /** Default "Show {count} more". */ showMore?: string; /** Default "Show less". */ showLess?: string; /** Default "Unpin {title}". */ unpin?: string; }; /** `"none"` is instant; otherwise `speed` picks 150/200/260ms and `animateShadow` (default true) toggles the panel shadow. */ export type SidebarCollapseTransition = "none" | { /** Duration of the inline collapse: "fast" 150ms, "base" 200ms, "slow" 260ms. */ speed?: "fast" | "base" | "slow"; /** Animates the panel shadow along with the width; defaults to true. */ animateShadow?: boolean; }; /** One nav item; `subMenu` renders inline (expand/collapse), `secondaryItems` opens a separate SecondaryBar instead. */ export type MenuProps = { /** Unique key; `SidebarProps.activeMenu` matches it after `title`. */ id: string | number; /** Row text, truncated with a tooltip when too long; `SidebarProps.activeMenu` matches it first. */ title: string; /** Icon component (not an element) drawn at the start of the row. */ icon?: ElementType; /** Ignored when subMenu is non-empty — the row becomes a toggle button instead of a link. */ url: string; /** Blocks the click handler and dims the row; wins over `disabled` when both are set. */ isDisabled?: boolean; /** @deprecated Use `isDisabled` — renamed to match every other field. */ disabled?: boolean; /** Blocks the click handler/submenu expand and dims the row, same as `isDisabled`; also shows a lock icon. */ locked?: boolean; /** Shown as a tooltip on hover/focus of a `locked` row (rail row, submenu row, and both flyouts). Ignored unless `locked` is true. */ lockedReason?: string; /** Runtime also accepts a bare number/string (legacy shorthand) though the type only declares the object shape. */ badge?: { /** Also triggers the small red dot on the icon when the rail is collapsed. */ count?: number; /** Chakra colorScheme name; defaults to "teal". */ color?: string; /** Chakra borderRadius value; defaults to "full". */ radius?: string | number; /** Chakra Badge variant; defaults to "subtle". */ variant?: string; }; /** Nested rows shown inline when this row is expanded; non-empty turns the row into a toggle. */ subMenu?: MenuProps[]; /** Non-empty on the active menu auto-collapses the main rail and renders a SecondaryBar, regardless of the `toggle` prop. On drawer viewports up to 23.3em (about 373px) it starts as the icon strip. */ secondaryItems?: MenuProps[]; /** First item with a new value renders a section label plus divider; items must be pre-sorted by group. */ group?: string; }; /** Props for the internal MenuItems renderer — a narrowed slice of SidebarProps. */ export type RenderMenuType = { /** Rows to render, in order. */ menus: MenuProps[]; /** Matched against each menu's `title`, then `id`, to mark the active row. */ activeMenu: string | number; /** Called with the menu when a row is chosen. */ handleMenuClick: (menu: MenuProps) => void; /** True renders the collapsed icon rail. */ toggle: boolean; /** Carried over from the unused `SidebarProps.selectedSubMenu`; not read. */ selectedSubMenu?: string | null; /** Id or title of the highlighted SecondaryBar item. */ selectedSecondaryItem?: string | number | null; /** @deprecated Dead — the drawer uses the docked row metrics; nothing reads it. */ overlay?: boolean; /** The scroll container's own id, read back by the auto-scroll-into-view effect. */ containerId: string; }; /** Secondary flyout panel props; `defaultCollapsed` only seeds initial state, then the panel self-manages it. */ export type SecondaryBarProps = { /** Flyout entries in order. */ items?: MenuProps[]; /** Defaults to true (collapsed) when omitted. */ defaultCollapsed?: boolean; /** Defaults to "3.5rem". */ collapsedWidth?: string | number; /** Defaults to "10rem". */ expandedWidth?: string | number; /** Lets the panel narrow down to `collapsedWidth` inside a width-capped parent such as the mobile drawer, instead of overflowing it. */ shrinkable?: boolean; /** Drill-down title size. Defaults to the shared sidebar row size (13px). */ headerFontSize?: string; /** Row label size. Defaults to the shared sidebar row size (13px). */ itemFontSize?: string; /** Matched by string equality against either the item's id or title, whichever matches. */ selected?: string | number | null; /** Called with the item chosen; skipped for locked or disabled items. */ onItemClick?: (item: MenuProps) => void; /** Also used as the collapsed-state tooltip label. */ title?: string; /** Shown only in the expanded header — hidden entirely while collapsed. */ icon?: ElementType; }; /** "Switch app" footer grid; becomes hover popovers when the sidebar is collapsed. */ export type OtherAppsProps = { /** True when the sidebar is collapsed; apps then show as hover popovers. */ toggle: boolean; /** Apps to list; renders nothing when empty. */ otherApps: { /** Used as the React list key — must be unique among otherApps entries. */ name: string; /** Fills the fallback dot (no icon) and its glow — ignored when `icon` is provided. */ color: string; /** Shown only in the collapsed-state hover flyout, never in the expanded grid cell. */ description?: string; /** Called when the app is pressed. */ onClick: () => void; /** A pre-rendered ReactNode, unlike MenuProps.icon (a component reference). */ icon?: React.ReactNode; }[]; };