Sidebar
Overviewimport { Sidebar, SidebarCard, SidebarDot, SidebarFooter, SidebarGroup, SidebarHeader } from '@nili/ui';This is the library’s own overview page, rendered live. Switch the language or the theme in the header and it follows.
The panel
Header, groups of items, and a footer. It collapses itself: leave collapsed off and the panel keeps its own state, and a SidebarTrigger anywhere inside folds it. A sidebar that needs the app to write a useState before it can fold is one most apps ship unfoldable.
import {
Sidebar, SidebarHeader, SidebarGroup, SidebarItem,
SidebarFooter, SidebarUser, SidebarTrigger, Icon,
} from "@nili/ui"
import { RiHome5Line, RiFolderLine } from "@remixicon/react"
export function Example() {
return (
<Sidebar label="Main">
<SidebarHeader
logo={<PlaceholderLogo company="apex-financial" size="sm" label="" />}
title="Apex Financial"
subtitle="Pro plan"
action={<SidebarTrigger />}
collapsedAction={<SidebarTrigger />}
/>
<SidebarGroup label="Main">
<SidebarItem icon={<Icon icon={RiHome5Line} />} href="#">Home</SidebarItem>
<SidebarItem icon={<Icon icon={RiFolderLine} />} href="#" active>
Projects
</SidebarItem>
</SidebarGroup>
<SidebarFooter>
<SidebarUser
avatar={<Avatar size="sm" name="Ada Lovelace" tone="blue" />}
name="Ada Lovelace"
email="ada@nili.design"
/>
</SidebarFooter>
</Sidebar>
)
}The rail
Expanded and collapsed are one component: every row is the same row with its label faded to zero width, so a row added to one is added to both. The labels stay in the DOM rather than unmounting — a rail of unlabelled icons is the layout that needs its accessible names most.
import { Sidebar } from "@nili/ui"
export function Example() {
const [collapsed, setCollapsed] = useState(true)
return (
<Sidebar
collapsed={collapsed}
onCollapsedChange={setCollapsed}
label="Main"
>
…
</Sidebar>
)
}Sidebar
extends ComponentPropsWithoutRef<'nav'>
Variant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| collapsed | boolean | false | The rail. One boolean rather than a second component: every row is the same row with its label faded out. |
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| label | string | — | Accessible name, e.g. "Main". A page usually has more than one `<nav>`, and "navigation, navigation, navigation" is not a landmark list. |
SidebarFooter
SidebarGroup
extends ComponentPropsWithoutRef<'div'>
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| label | string | — | Figma's "MAIN" / "FAVS" caption. Becomes a rule on the rail. |
SidebarGroupLabel
internalVariant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| collapsed | 'true' | 'false' | false |
SidebarHeader
extends Omit< ComponentPropsWithoutRef<'div'>, 'title' >
Variant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| collapsed | 'true' | 'false' | false |
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| logo | ReactNode | — | The workspace mark — a `PlaceholderLogo`, an `Avatar`, an `<img>`. |
| title | ReactNode | — | |
| subtitle | ReactNode | — | |
| action | ReactNode | — | Figma's workspace switcher, on the trailing edge. Hidden on the rail. |
SidebarItem
extends Omit< ComponentPropsWithoutRef<'a'>, 'color' >
Variant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| active | boolean | false | The current page. Draws the primary marker in the gutter. |
| collapsed | 'true' | 'false' | false |
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| aria-label | string | — | |
| icon | ReactNode | — | |
| href | string | — | Makes it a link. Without it the row renders as a `<button>`. |
| shortcut | ReactNode | — | Figma's ⌘1 chip on a FAVS row. Replaces the trailing chevron. |
| trailing | ReactNode | — | Overrides the trailing chevron with anything else — a count, a badge. |
| disabled | boolean | false |
SidebarItemLabel
internalVariant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| collapsed | 'true' | 'false' | false |
SidebarItemTrailing
internalVariant axes — from the component’s cva definition
| Prop | Type | Default | Notes |
|---|---|---|---|
| collapsed | 'true' | 'false' | false |
SidebarUser
extends ComponentPropsWithoutRef<'button'>
Other props
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | — | |
| disabled | boolean | — | |
| required | boolean | — | |
| readOnly | boolean | — | |
| value | string | — | |
| defaultValue | string | — | |
| name* | string | — | |
| aria-label | string | — | |
| avatar | ReactNode | — | |
| string | — | ||
| badge | ReactNode | — | The verified tick beside the name. |