SakaniUI

Sidebar

The app navigation rail and the nine parts it's assembled from.

It's a composition, not a config

Sidebar takes no items array. You place the parts yourself, in whatever order and grouping your app needs, which is what lets a promo sit mid-rail in one product and above the footer in another without the component growing options for each case.

Collapsing

collapsed isn't inherited — each part takes its own, because each has a different icon-only layout. Pass the same state down to all of them.

Icon rail

Collapsed items fall back to a native title tooltip. If you wrap them in the Tooltip component instead, set nativeTooltip={false} so both don't fire at once — that's exactly what the live CRM dashboard on the home page does.

Sidebar props

PropTypeDefaultDescription
collapsedbooleanfalseNarrows the rail. Pass the same value to each child that takes it.
childrenReactNodeThe parts below, in whatever order your app needs.

SidebarItem props

PropTypeDefaultDescription
labelstringItem text. Still required when collapsed, since it becomes the tooltip and accessible name.
iconIconComponentThe icon component itself, not an element.
activebooleanfalseMarks the current page.
activeIndicatorbooleantrueActive styling: true is the raised card with a left accent bar, false is a flat tint. Ignored when collapsed.
badgestringTrailing count or status pill.
hasSubmenubooleanfalseShows the disclosure chevron. You render the SidebarSubItems yourself.
disabledbooleanfalseDims the item and drops its click handler.
collapsedbooleanfalseIcon-only layout.
nativeTooltipbooleantrueTitle-attribute tooltip when collapsed. Set false if you're wrapping the item in your own Tooltip, so the two don't compete on hover.
hrefstringRenders an anchor instead of a button.
onClick() => voidClick handler.

SidebarHeader props

PropTypeDefaultDescription
type'brand' | 'workspace' | 'brand-toggle''brand'Brand is a logo and name; workspace adds a subtitle; brand-toggle adds the collapse button.
titlestringProduct or workspace name.
subtitlestringSecond line, e.g. the plan.
logoReactNodeMark beside the title.
onToggle() => voidFires from the collapse button on brand-toggle.
toggleIconIconComponentPanelLeftCloseIcon for that button.
collapsedbooleanfalseIcon-only layout.

The remaining parts

PropTypeDefaultDescription
SidebarSearchtype, placeholder, value, onChange, onClick, collapsed'field' is an inline input; 'command' is a button that opens your own command menu.
SidebarGroupLabelchildrenSmall caps heading above a group of items.
SidebarSubItemlabel, active, disabled, href, onClickNested child row, indented under an item with hasSubmenu.
SidebarDivider—A rule between groups.
SidebarPromotype, title, description, ctaLabel, onCta, onDismiss, iconUpsell or announcement card, usually pinned above the footer.
SidebarFootertype, title, subtitle, avatarSrc, avatarInitials, onMenu, onSignOut, collapsedAccount row at the bottom, as plain user, user-with-menu, or an actions set.

Why it works this way

Why

  • The container is 248px expanded and 64px collapsed with no fill or border of its own. It composes with the standalone parts rather than owning their content.

Don't

  • Don't build navigation from scratch beside it. Compose SidebarItem, SidebarGroupLabel and the rest.