From cbf6ca5338823677ee2124337400fa7fb4a49fd8 Mon Sep 17 00:00:00 2001 From: Jeroen Schweitzer Date: Wed, 31 Dec 2025 16:38:29 +0100 Subject: [PATCH] docs: add Nav Panel section headers mockup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Document conditional section headers for grouping nav items: - Single section: headers hidden - Multiple sections: headers visible with left accent bar - Route configuration driven data model - Updated Control Room wireframes with current/future state ๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- docs/UI_LAYOUT.md | 153 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 143 insertions(+), 10 deletions(-) diff --git a/docs/UI_LAYOUT.md b/docs/UI_LAYOUT.md index 93aa0b5..5a5ff16 100644 --- a/docs/UI_LAYOUT.md +++ b/docs/UI_LAYOUT.md @@ -75,6 +75,117 @@ All left-side panels (Nav Panel, Filter Panel) dock their header content to the Right-side panels (Detail Panel, Chat Dock) use standard vertically-centered headers since the logo bulge doesn't reach them. +### Nav Panel Sections + +Nav items can be organized into **sections**. Section headers are **conditionally visible** - they only appear when multiple sections exist. + +#### Single Section (headers hidden) + +When all items belong to one section, no headers are shown: + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ [โ‰ก] Sections [ยทยทยท] โ”‚ โ† Panel header +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ โ–ธ Containers โ”‚ +โ”‚ Networks โ”‚ +โ”‚ Volumes โ”‚ +โ”‚ Images โ”‚ +โ”‚ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +#### Multiple Sections (headers visible) + +When items span multiple sections, section headers appear: + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ [โ‰ก] Sections [ยทยทยท] โ”‚ โ† Panel header +โ”œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค +โ”‚ โ–ŒPortainer โ”‚ โ† Section header (subtle bg, left accent) +โ”‚ โ–ธ Containers โ”‚ +โ”‚ Networks โ”‚ +โ”‚ Volumes โ”‚ +โ”‚ Images โ”‚ +โ”‚ โ”‚ +โ”‚ โ–ŒNPM โ”‚ โ† Section header +โ”‚ Proxy Hosts โ”‚ +โ”‚ Redirections โ”‚ +โ”‚ Streams โ”‚ +โ”‚ โ”‚ +โ”‚ โ–ŒAuthentik โ”‚ โ† Section header +โ”‚ Users โ”‚ +โ”‚ Groups โ”‚ +โ”‚ Applications โ”‚ +โ”‚ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +#### Section Header Styling + +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚โ–ŒSECTION NAME โ”‚ โ† Left accent bar (2px, primary color) +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ† Background: surfaceContainerHigh + โ† Text: labelSmall, onSurfaceVariant + โ† Padding: 8px horizontal, 6px vertical + โ† All caps, letter-spacing: 0.5 +``` + +#### Data Model + +```dart +/// NavItem model (in nav_panel.dart) +class NavItem { + final String id; + final String label; + final IconData icon; + final String? section; // null = ungrouped +} + +// Section headers auto-generate from unique section values +// Visibility: items.map((i) => i.section).toSet().length > 1 +``` + +#### Route Configuration Driven + +Sections are defined in the feature's route configuration, not the widget: + +```dart +/// In lib/features/control_room/router.dart + +enum ControlRoomNav { + // Portainer section + containers('containers', 'Containers', Icons.dns, 'Portainer'), + networks('networks', 'Networks', Icons.hub, 'Portainer'), + volumes('volumes', 'Volumes', Icons.storage, 'Portainer'), + images('images', 'Images', Icons.photo_library, 'Portainer'), + // NPM section (future) + proxyHosts('proxy-hosts', 'Proxy Hosts', Icons.public, 'NPM'), + redirections('redirections', 'Redirections', Icons.alt_route, 'NPM'), + // Authentik section (future) + users('users', 'Users', Icons.people, 'Authentik'), + groups('groups', 'Groups', Icons.group_work, 'Authentik'); + + const ControlRoomNav(this.id, this.label, this.icon, this.section); + + final String id; + final String label; + final IconData icon; + final String section; + + NavItem toNavItem() => NavItem( + id: id, + label: label, + icon: icon, + section: section, + ); +} +``` + +The NavPanel widget receives items and auto-generates section headers based on unique section values in the list. No section logic lives in the widget - it just renders what the route config provides. + --- ## Panel Configurations by Room @@ -260,29 +371,51 @@ Primary landing page. Chat dock expanded by default. ### Control Room (Infrastructure) -Context sidebar with section navigation. Chat collapsed. +Nav panel with grouped section navigation. Chat collapsed. +**Current state** (single grouper - headers hidden): ``` โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ” โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ SECTIONS โ”‚ CONTAINERS [Search] [+ New] โ”‚ ๐Ÿ’ฌ โ”‚ โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ โ”‚ โ–ธ Containers โ”‚ โ˜‘ NAME STATUS CPU MEM IMAGE โ‹ฎ โ”‚ โ”‚ -โ”‚ Stacks โ”‚ โ˜ jellyfin โ— Run 2.3% 1.2GB latest โ‹ฎ โ”‚ โ”‚ +โ”‚ Networks โ”‚ โ˜ jellyfin โ— Run 2.3% 1.2GB latest โ‹ฎ โ”‚ โ”‚ +โ”‚ Volumes โ”‚ โ˜ ollama โ— Run 45% 8.0GB 0.1.32 โ‹ฎ โ”‚ โ”‚ +โ”‚ Images โ”‚ โ˜ postgres โ— Run 1.1% 512MB 16-alp โ‹ฎ โ”‚ โ”‚ +โ”‚ โ”‚ โ˜ redis โ— Run 0.2% 128MB 7-alp โ‹ฎ โ”‚ โ”‚ +โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ +โ”‚ โ”‚ Showing 5 of 40 < 1 2 3 4 5 > โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ +โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ +``` + +**Future state** (multiple groupers - headers visible): +``` +โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ” +โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ SECTIONS โ”‚ CONTAINERS [Search] [+ New] โ”‚ ๐Ÿ’ฌ โ”‚ +โ”‚ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ +โ”‚ โ–ŒPORTAINER โ”‚ โ˜‘ NAME STATUS CPU MEM IMAGE โ‹ฎ โ”‚ โ”‚ +โ”‚ โ–ธ Containers โ”‚ โ˜ jellyfin โ— Run 2.3% 1.2GB latest โ‹ฎ โ”‚ โ”‚ โ”‚ Networks โ”‚ โ˜ ollama โ— Run 45% 8.0GB 0.1.32 โ‹ฎ โ”‚ โ”‚ -โ”‚ Volumes โ”‚ โ˜ postgres โ— Run 1.1% 512MB 16-alp โ‹ฎ โ”‚ โ”‚ -โ”‚ Images โ”‚ โ˜ redis โ— Run 0.2% 128MB 7-alp โ‹ฎ โ”‚ โ”‚ -โ”‚ โ”‚ โ˜ authentik โ—‹ Stop - - 2024.2 โ‹ฎ โ”‚ โ”‚ -โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ -โ”‚ Netdata โ†— โ”‚ Showing 5 of 40 < 1 2 3 4 5 > โ”‚ โ”‚ -โ”‚ Portainerโ†— โ”‚ โ”‚ โ”‚ -โ”‚ NPM โ†— โ”‚ โ”‚ โ”‚ +โ”‚ Volumes โ”‚ โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ โ”‚ โ”‚ +โ”‚ Images โ”‚ Showing 3 of 40 < 1 2 3 4 5 > โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ–ŒNPM โ”‚ โ”‚ โ”‚ +โ”‚ Proxy Hostsโ”‚ โ”‚ โ”‚ +โ”‚ Redirects โ”‚ โ”‚ โ”‚ +โ”‚ โ”‚ โ”‚ โ”‚ +โ”‚ โ–ŒAUTHENTIK โ”‚ โ”‚ โ”‚ +โ”‚ Users โ”‚ โ”‚ โ”‚ +โ”‚ Groups โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ”‚ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”˜ ``` **Components:** -- Context Sidebar: Section nav + external links +- Nav Panel: Grouped section navigation (grouper headers conditional) +- Filter Panel: Stack/item filtering within section - DataGrid: Container list with bulk actions - Detail Panel: Opens on row selection (replaces grid or slides in)