feat: add reusable panel system with FilterPanel widget

- Update UI_LAYOUT.md with comprehensive panel taxonomy
- Document Nav Panel, Filter Panel, Detail Panel, Chat Dock specs
- Add panel header behavior (bottom-docked for left panels)
- Add responsive breakpoints with panel folding summary
- Create PanelHeader widget with dockToBottom option
- Create FilterPanel widget for data filtering sidebars
- Refactor Control Room to use FilterPanel
- Remove external links from sidebar (cleanup)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Jeroen Schweitzer
2025-12-31 14:54:14 +01:00
co-authored by Claude Opus 4.5
parent de739e8f7a
commit 948e104ce5
4 changed files with 331 additions and 144 deletions
+183 -42
View File
@@ -22,36 +22,107 @@ The UI uses a **tabbed room navigation** in the header rather than a traditional
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ HEADER (intrinsic height) │
│ [Logo] [═══════ Room Tabs (scrollable) ═══════] [Notifications] [Profile] │
│ HEADER BAR (56px, with logo bulge overlay) │
│ [◯Logo◯] [Room Icons] ─────────────────────────────────── [Profile Menu] │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────┐ ┌───────────────────┐ │
│ │ │ │ │ │
│ │ MAIN CONTENT │ │ CHAT DOCK │ │
│ │ flex: 1 │ │ flex: 0 │ │
│ │ │ │ │ │
│ │ ┌─────────────┐ ┌────────────────────────────┐ │ │ Tatlock chat │ │
│ │ │ CONTEXT │ │ PRIMARY │ │ │ assistant, │ │
│ │ │ SIDEBAR │ │ CONTENT │ │ │ persistent │ │
│ │ │ │ │ │ │ │ across rooms │ │
│ │ │ flex: 0 │ │ flex: 1 │ │ │ │ │
│ │ │ intrinsic │ │ │ │ │ │ │
│ │ └─────────────┘ └────────────────────────────┘ │ │ │ │
│ │ │ │ │ │
│ └─────────────────────────────────────────────────┘ └───────────────────┘ │
│ ┌─────────────┐ ┌─────────────────────────────────┐ ┌───────────────────┐ │
│ │ NAV PANEL │ │ PRIMARY CONTENT │ │ CHAT DOCK │ │
│ │ │ │ │ │ │ │
│ │ Room-level │ │ ┌──────────┐ ┌──────────────┐ │ │ Tatlock AI │ │
│ │ navigation │ │ │ FILTER │ │ DATA GRID │ │ │ assistant │ │
│ │ (sections) │ │ │ PANEL │ │ │ │ │ │ │
│ │ │ │ │ │ │ │ │ │ Persistent │ │
│ │ 280px fixed │ │ │ Optional │ │ flex: 1 │ │ │ across rooms │ │
│ │ │ │ │ 280px │ │ │ │ │ │ │
│ └─────────────┘ │ └──────────┘ └──────────────┘ │ │ 280px-33vw │ │
│ │ │ │ │ │
│ │ flex: 1 │ │ flex: 0 │ │
│ └─────────────────────────────────┘ └───────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
```
### Component Roles
---
## Panel Taxonomy
All panels share common styling patterns but serve different purposes.
### Panel Types
| Panel | Position | Purpose | Width | Content Alignment |
|-------|----------|---------|-------|-------------------|
| **Header Bar** | Top | Room nav, profile | 56px height | Logo in bulge, rest at bottom |
| **Nav Panel** | Left | Room-level section nav | 280px fixed | Header docked to bottom |
| **Filter Panel** | Left (inside content) | Data filtering/search | 280px fixed | Header docked to bottom |
| **Detail Panel** | Right (inside content) | Selected item details | 320-400px | Standard header |
| **Chat Dock** | Right | AI assistant | 280px-33vw | Standard header |
### Panel Header Behavior
All left-side panels (Nav Panel, Filter Panel) dock their header content to the **bottom** of the header area. This accommodates the logo bulge that overlays into their space.
```
┌─────────────────────────┐
│ │ ← Logo bulge overlays this space
│ (empty) │
│ │
│ [Icon] Title [Action]│ ← Content docked to bottom (8px margin)
├─────────────────────────┤
│ Panel content... │
```
Right-side panels (Detail Panel, Chat Dock) use standard vertically-centered headers since the logo bulge doesn't reach them.
---
## Panel Configurations by Room
### Front Hall
```
┌────────────────────────────────────────────────────────────────┬────────────┐
│ PRIMARY CONTENT (no nav panel) │ CHAT DOCK │
│ Dashboard cards, activity feed │ (expanded) │
└────────────────────────────────────────────────────────────────┴────────────┘
```
### Control Room
```
┌───────────┬──────────────────────────────────────────────────────┬──────────┐
│ NAV PANEL │ PRIMARY CONTENT │ CHAT │
│ │ ┌────────────┬────────────────────────────────────┐ │ DOCK │
│ Sections: │ │ FILTER │ DATA GRID │ │ │
│ • Contai. │ │ PANEL │ Container/Stack list │ │ (collap- │
│ • Stacks │ │ │ │ │ sed) │
│ • Network │ │ Stack list │ │ │ │
│ • Volumes │ │ + search │ │ │ │
└───────────┴──┴────────────┴────────────────────────────────────┴─┴──────────┘
```
### Parlor
```
┌───────────┬────────────────────────────────────────────────────┬────────────┐
│ NAV PANEL │ PRIMARY CONTENT │ CHAT DOCK │
│ │ Device controls, scenes │ (collapsed)│
│ Areas: │ │ │
│ • Living │ │ │
│ • Bedroom │ │ │
│ • Kitchen │ │ │
└───────────┴────────────────────────────────────────────────────┴────────────┘
```
---
## Component Roles
| Component | Flex | Description |
|-----------|------|-------------|
| **Header** | intrinsic | Logo, room tabs, action icons |
| **Main Content** | `flex: 1` | Fills remaining horizontal space |
| **Context Sidebar** | `flex: 0`, intrinsic | Room-specific navigation (Control Room, Parlor) |
| **Primary Content** | `flex: 1` | Room's main working area |
| **Header Bar** | intrinsic (56px) | Logo bulge, room icons, profile menu |
| **Nav Panel** | `flex: 0`, 280px | Room-level section navigation |
| **Filter Panel** | `flex: 0`, 280px | Data filtering within a section |
| **Primary Content** | `flex: 1` | Main working area |
| **Detail Panel** | `flex: 0`, 320-400px | Selected item details (optional) |
| **Chat Dock** | `flex: 0`, intrinsic | Tatlock assistant, collapsible |
---
@@ -61,55 +132,76 @@ The UI uses a **tabbed room navigation** in the header rather than a traditional
### Wide (>= 1200px)
```
┌────────────────────────────────────────────────────────┬────────────────────┐
│ [Sidebar] [══════════ Content ══════════] │ Chat (expanded) │
└────────────────────────────────────────────────────────┴────────────────────┘
┌───────────┬─────────────────────────────────────────────┬────────────────────┐
│ NAV PANEL │ [Filter Panel] [═══ Data Grid ═══] │ CHAT DOCK │
│ (280px) │ (280px) (flex: 1) │ (expanded, 320px) │
└───────────┴─────────────────────────────────────────────┴────────────────────┘
```
- All panels visible
- Chat dock expanded by default on Front Hall
- Context sidebar visible with labels
- Nav panel visible with full labels
- Filter panel visible (where applicable)
- Full data grid columns
### Medium (>= 800px, < 1200px)
```
┌────────────────────────────────────────────────────────────────────────┬────┐
│ [Sidebar] [══════════════════ Content ══════════════════] │ 💬 │
└────────────────────────────────────────────────────────────────────────┴────┘
┌───────────┬───────────────────────────────────────────────────────────┬────┐
│ NAV PANEL │ [Filter Panel] [═══════════ Data Grid ═══════════] │ 💬 │
│ (280px) │ (280px) (flex: 1) │48px│
└───────────┴───────────────────────────────────────────────────────────┴────┘
```
- Chat dock collapsed to icon rail
- Click to expand as overlay
- Context sidebar still visible
- Chat dock collapsed to icon rail (48px)
- Click chat icon to expand as overlay
- Nav panel still visible
- Filter panel still visible
- Data grid may hide some columns
### Compact (>= 600px, < 800px)
```
┌────────────────────────────────────────────────────────────────────────┬────┐
│ [≡] [════════════════════ Content ════════════════════] │ 💬 │
└────────────────────────────────────────────────────────────────────────┴────┘
┌────┬───────────────────────────────────────────────────────────────────┬────┐
│ ≡ │ [═══════════════════════ Content ═══════════════════════] │ 💬 │
│48px│ Filter panel becomes top bar or collapsible │48px│
└────┴───────────────────────────────────────────────────────────────────┴────┘
```
- Context sidebar becomes drawer (hamburger menu)
- Chat dock collapsed
- Reduced data grid columns
- Nav panel collapses to icon rail (48px), expands as drawer on tap
- Filter panel moves to top of content or becomes collapsible
- Chat dock remains collapsed (48px)
- Data grid shows essential columns only
### Mobile (< 600px)
```
┌────────────────────────────────────────────────────────────────────────┐
│ [≡] [Tabs scroll horizontally] [💬] │
│ HEADER: [≡] [Room Icons scroll] ─────────────────────────────── [💬] │
├────────────────────────────────────────────────────────────────────────┤
│ │
│ [══════════════════════ Content ══════════════════════] │
│ [═══════════════════════ Content ══════════════════════] │
│ Filter as expandable section at top │
│ │
└────────────────────────────────────────────────────────────────────────┘
```
- Single column layout
- Room tabs scroll horizontally
- Chat opens as bottom sheet
- Context sidebar as full-screen drawer
- Nav panel opens as full-screen drawer (hamburger menu)
- Filter panel becomes expandable section at top of content
- Chat opens as bottom sheet (60vh max)
- Data grid becomes card list or single-column table
---
## Panel Folding Summary
| Panel | Wide (≥1200) | Medium (≥800) | Compact (≥600) | Mobile (<600) |
|-------|--------------|---------------|----------------|---------------|
| **Nav Panel** | 280px visible | 280px visible | 48px rail → drawer | Hidden → drawer |
| **Filter Panel** | 280px visible | 280px visible | Collapsed/top bar | Expandable section |
| **Chat Dock** | 320px expanded | 48px rail → overlay | 48px rail → overlay | Icon → bottom sheet |
| **Detail Panel** | 320-400px slide-in | 320px slide-in | Full-width overlay | Full-screen |
---
@@ -275,6 +367,42 @@ The Tatlock chat assistant is **omnipresent** - accessible from any room.
## Flutter Implementation Notes
### Panel Widget Library
All panels are built from shared components in `lib/shared/layouts/widgets/`:
| Widget | File | Purpose |
|--------|------|---------|
| `PanelContainer` | `panel_container.dart` | Base container for all panels |
| `PanelHeader` | `panel_header.dart` | Configurable header (bottom-docked or centered) |
| `NavPanel` | `nav_panel.dart` | Left-side room navigation |
| `FilterPanel` | `filter_panel.dart` | Left-side data filtering |
| `DetailPanel` | `detail_panel.dart` | Right-side item details |
| `ChatDock` | `chat_dock.dart` | Right-side AI assistant |
### PanelHeader Configuration
```dart
/// Panel header with configurable content alignment.
class PanelHeader extends StatelessWidget {
const PanelHeader({
required this.title,
required this.icon,
this.actions,
this.dockToBottom = false, // true for left-side panels
});
}
```
**Left-side panels** (Nav, Filter) use `dockToBottom: true` to accommodate the logo bulge:
- Header height: 56px (matches app header)
- Content aligned to bottom with 8px margin
- Empty space at top allows logo bulge overlay
**Right-side panels** (Detail, Chat) use `dockToBottom: false`:
- Standard vertically-centered content
- No accommodation needed for logo bulge
### Recommended Widgets
| Concept | Flutter Widget |
@@ -296,6 +424,19 @@ abstract class Breakpoints {
}
```
### Panel Width Constants
```dart
abstract class PanelWidths {
static const double navPanel = 280;
static const double filterPanel = 280;
static const double detailPanel = 360;
static const double chatDockExpanded = 320;
static const double chatDockCollapsed = 48;
static const double railWidth = 48;
}
```
### Layout Builder Pattern
```dart