- 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>
71 lines
1.9 KiB
Dart
71 lines
1.9 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// Panel header with configurable content alignment.
|
|
///
|
|
/// Left-side panels (Nav, Filter) should use [dockToBottom: true] to
|
|
/// accommodate the logo bulge overlay. Right-side panels use default centering.
|
|
///
|
|
/// See UI_LAYOUT.md for panel taxonomy and layout specifications.
|
|
class PanelHeader extends StatelessWidget {
|
|
const PanelHeader({
|
|
super.key,
|
|
required this.title,
|
|
required this.icon,
|
|
this.actions,
|
|
this.dockToBottom = false,
|
|
this.height = 56.0,
|
|
});
|
|
|
|
/// Panel title text.
|
|
final String title;
|
|
|
|
/// Leading icon for the panel.
|
|
final IconData icon;
|
|
|
|
/// Optional action widgets (e.g., refresh button).
|
|
final List<Widget>? actions;
|
|
|
|
/// Whether to dock content to bottom (for left-side panels under logo bulge).
|
|
final bool dockToBottom;
|
|
|
|
/// Header height (should match app header height).
|
|
final double height;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final colorScheme = Theme.of(context).colorScheme;
|
|
|
|
return Container(
|
|
height: height,
|
|
padding: EdgeInsets.only(
|
|
left: 16,
|
|
right: 8,
|
|
bottom: dockToBottom ? 8 : 0,
|
|
),
|
|
alignment: dockToBottom ? Alignment.bottomCenter : Alignment.center,
|
|
decoration: BoxDecoration(
|
|
color: colorScheme.surfaceContainerHighest,
|
|
border: Border(
|
|
bottom: BorderSide(color: colorScheme.outlineVariant),
|
|
),
|
|
),
|
|
child: Row(
|
|
crossAxisAlignment:
|
|
dockToBottom ? CrossAxisAlignment.end : CrossAxisAlignment.center,
|
|
children: [
|
|
Icon(icon, color: colorScheme.primary),
|
|
const SizedBox(width: 12),
|
|
Text(
|
|
title,
|
|
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
|
fontWeight: FontWeight.w600,
|
|
),
|
|
),
|
|
const Spacer(),
|
|
if (actions != null) ...actions!,
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|