Layout & Navigation (Desktop)
Pick a primary navigation pattern — don't stack multiple
A desktop app needs exactly one primary way to move between top-level sections. Common patterns, and when each fits:
| Pattern | Best for |
|---|---|
| Sidebar | Apps with 4+ top-level sections, or sections with their own nested hierarchy (projects, folders, channels) |
| Tabs (top-level) | Apps with 2–6 flat, equally-weighted sections and no nesting |
| Tabs (document-level) | Multiple open documents/sessions within one section (browser-style) — this is a different concept from top-level tabs and can coexist with a sidebar |
Don't combine top-level tabs AND a top-level sidebar for the same job — pick the one that matches the app's actual information shape. It's fine to have a sidebar for sections and document tabs within a section (e.g. a code editor: sidebar for the file tree, tabs for open files).
Sidebar logic
- Width: give it a sensible default (200–280px is typical) and let it resize via a drag handle, with a sane minimum (
160px, below which icons-only makes more sense) and maximum (400px, beyond which it's stealing too much from content). - Collapse behavior: collapsing should shrink to an icon-only rail (48–56px), not disappear entirely — a vanished sidebar makes navigation state invisible. Persist the user's collapsed/expanded choice.
- Active item indication: background tint + a left-edge accent bar (see
desktop-ui-color-system), never color alone. - Nesting: indent child items by one spacing-scale step per level (see
desktop-ui-spacing-sizing); cap visible nesting depth at 3 levels before switching to a "reveal on click" pattern — deeper trees become unscannable. - Icons: every top-level sidebar item should have an icon (aids scanning when collapsed); nested items usually don't need one.
Tab logic
- Order and grouping matter — put the most-used section first (usually left), not alphabetically unless alphabetical genuinely helps the user.
- Active tab indicator: an underline or filled background, animated to move between tabs rather than snapping (see
desktop-ui-motion) — this single detail does a lot of work in making tab-switching feel connected rather than like separate page loads. - Overflow behavior (document-style tabs especially): once tabs would shrink below a readable minimum width (~80–100px), stop shrinking and switch to horizontal scroll with a "more tabs" overflow menu (chevron/dropdown) rather than letting tab labels truncate into illegibility or letting the tab bar overflow the window.
- Closeable tabs: show the close (×) affordance on hover/active, not permanently on every tab — a row of tabs all showing a close button at once is visually noisy.
- Cap the count: past roughly 8–10 visible document tabs, most users lose track of what's open — consider a tab-search/switcher (Cmd/Ctrl+K style) as the real solution rather than trying to cram more tabs into the bar.
Header / toolbar
- The header holds: window-level identity (and title-bar drag region on custom-chrome apps), primary contextual actions for the current view, and search/command access if the app has it. It is not a dumping ground for every action in the app.
- Keep header height consistent across all views of the app (a common value is 48–56px) — a header that changes height between screens makes the whole shell feel unstable.
- Right-align global/utility actions (settings, notifications, account); left-align navigational/contextual ones — this matches near-universal desktop convention and shouldn't be reinvented per screen.
Window chrome
- Custom title bar (Electron/Tauri): the full top strip must remain draggable except where interactive controls sit; window controls (close/minimize/maximize on Windows/Linux, or the traffic-light cluster on macOS) must be placed and sized to match platform convention, not just "somewhere in the corner."
- Resize behavior: every edge and corner should be resizable down to a sane minimum window size (define one — e.g. 800×600 — below which layout would break, and enforce it rather than letting the app become unusable).
- Responsive reflow at real desktop sizes: unlike a website, you can't assume a fixed viewport — test the layout at the minimum size, a typical size, and an ultrawide/maximized size. Sidebar-plus-content layouts should let the content pane grow while the sidebar stays fixed-width (or user-resized), not stretch everything proportionally.
Accessibility & internationalization
- Tab order should follow the visual/reading order through sidebar, header, and content in turn — not DOM or scene order that happens to differ from what's on screen.
- A true right-to-left layout mirrors the whole chrome, not just text alignment: the sidebar moves to the opposite edge and back/forward affordances flip direction.
- Expose the sidebar, header, and content regions as real, named landmarks to the platform's accessibility tree so screen reader users can jump between them directly. See
desktop-ui-accessibility-i18n.
Review format
| Before | After | Why |
|---|---|---|
| Sidebar disappears entirely when collapsed | Collapses to an icon-only 48px rail | A vanished sidebar hides navigation state entirely |
| Tab labels truncate to "Do…", "Un…" as more tabs open | Tabs stop shrinking at a floor width and overflow to a "more" menu | Illegible truncated labels are worse than an overflow affordance |
| Header height differs between the dashboard and settings screens | One consistent header height across the whole shell | Height changes between views make the app shell feel unstable |