Sidebar
Live Preview
The sidebar is the primary navigation element for all web portals. It follows a consistent structure across apps while allowing per-app navigation groups.
Anatomy
+--- Sidebar (240px) ---+
| |
| [Logo] RetailOS | <- Brand
| SUDIRMAN · JKT-003 | <- Store label (monospace)
| |
| ───────────────── | <- Divider
| |
| PENJUALAN | <- Group label (uppercase)
| ● Dashboard | <- Active item (green border)
| Transaksi | <- Inactive item
| Retur |
| |
| OPERASIONAL |
| Stok |
| Penerimaan |
| Opname (3) | <- Badge counter
| |
| ANALITIK |
| Laporan |
| |
| ───────────────── |
| |
| ⚙ Pengaturan | <- Settings (bottom)
| 🌙 Dark Mode | <- Theme toggle
| « Collapse | <- Collapse button
| |
| ┌─────────────────┐ |
| │ (●) Ahmad Kasir │ | <- User profile
| │ Kasir Sr. │ |
| └─────────────────┘ |
+------------------------+Brand Section
<div className="flex items-center gap-3 px-5 py-4">
<Logo className="w-8 h-8 text-brand" />
<span className="font-jakarta font-bold text-[15px] text-brand">
RetailOS
</span>
</div>Store Label
Displayed in monospace, uppercase. Shows the store name and code for context.
<div className="px-5 pb-3">
<span className="font-mono text-[11px] font-medium tracking-[0.08em] uppercase text-text-3">
SUDIRMAN · JKT-003
</span>
</div>Navigation Groups
Each group has an uppercase label and a list of nav items.
Group Label
.nav-group-label {
font-family: 'Plus Jakarta Sans', system-ui, sans-serif;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.08em;
text-transform: uppercase;
color: var(--text-3);
padding: 16px 20px 8px;
}Nav Item
| State | Left Border | Text Color | Font Weight | Background |
|---|---|---|---|---|
| Default | none | text-2 | 400 | transparent |
| Hover | none | text-1 | 400 | transparent (or very subtle bg-hover) |
| Active | 3px solid brand | text-1 | 600 | bg-inset |
.nav-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 20px;
font-family: 'Plus Jakarta Sans', system-ui, sans-serif;
font-size: 13px;
font-weight: 400;
color: var(--text-2);
border-left: 3px solid transparent;
transition: color 100ms ease-out;
cursor: pointer;
}
.nav-item:hover {
color: var(--text-1);
}
.nav-item.active {
color: var(--text-1);
font-weight: 600;
border-left-color: var(--color-brand);
background-color: var(--bg-inset);
}
.nav-item .icon {
width: 16px;
height: 16px;
stroke-width: 1.5;
opacity: 0.5;
}
.nav-item.active .icon {
opacity: 0.8;
}Active state
The active nav item uses a 3px left border in brand green + bold text + inset background. It does NOT use a full green fill background. The green should be restrained.
Badge Counter
Small rounded pill for notification counts.
<span className="ml-auto bg-danger text-white text-[10px] font-semibold rounded-full px-[6px] py-[1px] min-w-[18px] text-center">
3
</span>Bottom Section
Settings, dark mode toggle, and collapse button are pinned to the bottom of the sidebar.
<div className="mt-auto border-t border-border pt-2 pb-4">
<NavItem icon={<Settings size={16} />} label="Pengaturan" />
<button className="nav-item w-full" onClick={toggleDarkMode}>
<Moon size={16} strokeWidth={1.5} />
<span>Dark Mode</span>
<Toggle checked={isDark} className="ml-auto" />
</button>
<button className="nav-item w-full" onClick={toggleCollapse}>
<ChevronsLeft size={16} strokeWidth={1.5} />
<span>Collapse</span>
</button>
</div>User Profile
Pinned to the very bottom. Shows avatar, name, and role.
<div className="px-4 pb-4 pt-2 border-t border-border">
<div className="flex items-center gap-3">
<div className="w-8 h-8 rounded-full bg-brand/10 text-brand flex items-center justify-center text-xs font-semibold">
AK
</div>
<div>
<div className="text-[13px] font-medium text-text-1">Ahmad Kasir</div>
<div className="text-[11px] text-text-3">Kasir Senior</div>
</div>
</div>
</div>Collapsed State
When collapsed, the sidebar shrinks to 64px and shows only icons. Hovering an icon shows a tooltip with the label.
| Property | Expanded | Collapsed |
|---|---|---|
| Width | 240px | 64px |
| Labels | Visible | Hidden (tooltip on hover) |
| Group labels | Visible | Hidden |
| Store label | Visible | Hidden |
| User name | Visible | Avatar only |
DO and DON'T
DO
- Keep navigation groups organized by workflow area
- Use the 3px left border pattern for active state
- Show the store label so users always know which store context they are in
- Pin settings and user profile to the bottom
DON'T
- Don't use a full green background fill for active items
- Don't add more than 6 navigation groups --- consolidate or use sub-pages
- Don't nest navigation items more than one level deep in the sidebar
- Don't hide the sidebar on desktop --- it should always be visible (collapsible, not removable)