# Startup UI Flow Refresh Status: IMPLEMENTED Owner: imgui-frontend-engineer Created: 2025-12-07 Last Reviewed: 2025-12-06 Implemented: 2025-12-06 Board Link: [Coordination Board – 2025-12-05 imgui-frontend-engineer – Panel launch/log filtering UX](../agents/coordination-board.md) ## Implementation Summary (2025-12-06) ### Completed: 1. **StartupSurface enum** (`ui_coordinator.h`) - Single source of truth for startup state: `kWelcome`, `kDashboard`, `kEditor` 2. **Centralized visibility logic** (`ui_coordinator.cc`) - `ShouldShowWelcome()`, `ShouldShowDashboard()`, `ShouldShowActivityBar()` methods 3. **Activity Bar hidden until ROM load** - Modified `EditorManager::Update()` and `LayoutCoordinator::GetLeftLayoutOffset()` 4. **Category-specific expressive colors** (`panel_manager.cc`) - Each category has unique vibrant color (gold for Dungeon, green for Overworld, etc.) 5. **Enhanced icon rendering** (`activity_bar.cc`) - 4px accent border, 30% glow background, outer glow shadow for active categories 6. **Updated TransparentIconButton** (`themed_widgets.cc`) - Added `active_color` parameter for custom icon colors 7. **Side panel starts collapsed** (`panel_manager.h`) - Changed `panel_expanded_` default to `false` 8. **Dashboard dismisses on category selection** - Added `TriggerCategorySelected()` callback, wired to `SetStartupSurface(kEditor)` ### Key Files Modified: - `src/app/editor/ui/ui_coordinator.h` - Added `StartupSurface` enum and methods - `src/app/editor/ui/ui_coordinator.cc` - Centralized startup logic - `src/app/editor/menu/activity_bar.cc` - Expressive icon theming, category selection callback - `src/app/editor/system/panel_manager.h/cc` - Category theme colors, `on_category_selected_` callback - `src/app/gui/widgets/themed_widgets.h/cc` - Active color parameter - `src/app/editor/editor_manager.cc` - Activity Bar visibility gating, category selection handler - `src/app/editor/layout/layout_coordinator.cc` - Layout offset calculation ### Current Behavior: | State | Welcome | Dashboard | Activity Bar | Side Panel | |-------|---------|-----------|--------------|------------| | Cold start (no ROM) | Visible | Hidden | Hidden | Hidden | | ROM loaded | Hidden | Visible | Icons shown | Collapsed | | Category icon clicked | Hidden | Hidden | Icons (active glow) | Expanded | | Same icon clicked again | Hidden | Hidden | Icons | Collapsed (toggle) | --- ## Summary The current startup surface (Welcome, Dashboard, Activity Bar/Panel Sidebar, Status Bar) overlaps and produces inconsistent state: welcome + sidebar visible, dashboard sticking when opening editors, status bar obscured by the Activity Bar, and panels (emulator/memory/agent) registered before ROM load but not actually usable. This plan proposes a single source of truth for startup/state gates, VSCode-style welcome behavior (only when empty), and clear rules for sidebar/dashboard/status visibility—respecting user overrides and CLI-driven flows for agents/tests. ## Problems Observed - Welcome screen shows alongside Activity Bar/Panel tree, causing clutter; welcome sometimes “wins” focus and blocks panels opened via sidebar/presets. - Dashboard occasionally remains visible after switching editors/categories. - Status bar is covered by Activity Bar in some layouts. - Panels for emulator/memory/agent are registered and “visible” before ROM load but cannot open, creating confusion. - Startup flags/CLI (`--open_panels`, `--editor`) need to bypass stickiness to enable automation (e.g., MusicEditor for audio debugging). ## Goals - Single gatekeeper for startup surface; welcome only when no ROM/project and no explicit editor/panel request. - Deterministic sidebar/panel sidebar behavior on startup and editor switch; status bar always visible (no overlap). - Hide or defer unusable panels until prerequisites (ROM/project) are met; provide inline messaging when blocked. - Respect explicit user intent (CLI flags, last-session settings) over defaults. - Make flows testable and scriptable for AI agents/CLI. ## Proposed Behavior ### Welcome Screen - Show only when **no ROM/project loaded** and **no explicit startup editor/panel flags**. - Auto-hide on first successful ROM/project load or when user explicitly opens an editor/category. - If a user/flag forces show (`--welcome` or pref), keep visible but collapse sidebars to reduce clutter. - When welcome is visible, panel/sidebar buttons should surface a toast “Load a ROM/project to open panels” instead of silently failing. ### Dashboard Panel - Dashboard is a lightweight chooser: show only when welcome is hidden **and** no editor is active. - Hide immediately when switching to an editor or when any panel/category is activated via Activity Bar. - On return to “no editor” state (e.g., close session with no ROM), re-show dashboard unless suppressed by CLI. ### Activity Bar & Panel Sidebar - Cold start (no ROM/project, no CLI intent): **no Activity Bar, no category panel/sidebar**, only the welcome screen. - On ROM load: show **icon-only Activity Bar** by default (no persisted expanded state, no category preselected). Dashboard remains until user picks a category. - No auto-selection of categories/panels. Selecting a category from the icon bar or dashboard activates that category, shows its defaults, dismisses dashboard/welcome. Pinned items remain cross-category. - User can reopen the dashboard from the Activity Bar (dashboard icon) to deselect the current category; category panels collapse when leaving the category. ### Status Bar - Always visible when app is running; compute offsets so Activity Bar/side panels never overlap it. If dockspace margin math is incorrect, fix via LayoutCoordinator offsets. ### Panel Availability & Prereqs - Panels with hard dependencies (ROM) advertise `IsEnabled()` and return a tooltip “Load a ROM to use this panel.” Activity Bar selection opens a toast and does not flip visibility flags until enabled. - On ROM load, auto-reenable last requested-but-blocked panels (e.g., emulator/memory) and focus them if they were in the request queue. ### CLI / Agent Overrides - Flags `--editor`, `--open_panels`, `--welcome`, `--dashboard`, `--sidebar` define initial intent; intent beats persisted settings. - If `--open_panels` includes panels needing ROM and ROM is absent, queue them and show a status toast; auto-open after load. - Provide a small “startup state” summary in logs for reproducibility (welcome? dashboard? sidebar? active editor? queued panels?). ## Implementation Steps (high level) 1) **State owner**: Centralize startup/welcome/dashboard/sidebar decisions in UICoordinator + PanelManager callbacks; remove competing logic elsewhere. Emit a structured log of the chosen state on startup. 2) **Welcome rules**: Gate welcome on “no ROM/project and no explicit intent”; collapse sidebars while welcome is shown; hide on any editor/panel activation or ROM/project load. 3) **Dashboard rules**: Show only when welcome is hidden and no active editor; hide on category/editor switch; reopen when back to empty. 4) **Sidebar/Activity Bar**: Apply CLI/user overrides once; default to hidden when welcome is active, shown otherwise; clicking categories hides welcome/dashboard and activates layout defaults. 5) **Prereq-aware panels**: Implement `IsEnabled`/tooltip on emulator/memory/agent panels; queue panel requests until ROM loaded; on load, auto-show queued panels and focus first. 6) **Status bar spacing**: Ensure LayoutCoordinator offsets account for Activity Bar + side panel width so status bar is never obscured. 7) **Tests/telemetry**: Add a lightweight sanity check (e.g., headless mode) asserting startup state matrix for combinations of flags (welcome/dashboard/sidebar/editor/panels with/without ROM). ## Defaults (proposed) - First launch, no ROM: Welcome shown; no Activity Bar/sidebar; dashboard hidden. - After ROM load: Welcome hidden; Activity Bar icons shown; dashboard shown until a category is chosen; no category selected by default. - CLI `--editor music --open_panels=music.piano_roll`: Welcome/dashboard skipped, Activity Bar icons shown, Music defaults + piano roll visible; if ROM missing, queue + toast. ### Activity Bar affordances - Fix the collapse/expand icon inversion so the glyph reflects the actual state. - Standardize the sidebar toggle shortcut and audit related Window/shortcut-manager entries so labels match behavior; ensure consistency across menu, tooltip, and shortcut display. ## Additional UX Ideas (Future Work) These enhancements would improve the startup experience further. Each includes implementation guidance for future agents. --- ### 1. Empty State Checklist on Welcome/Dashboard **Goal**: Guide new users through initial setup with actionable steps. **Implementation**: - **File**: `src/app/editor/ui/welcome_screen.cc` - **Location**: Add to main content area, below recent projects section - **Components**: ```cpp struct ChecklistItem { const char* icon; const char* label; const char* description; std::function is_completed; // Returns true if step is done std::function on_click; // Action when clicked }; ``` - **Items**: - "Load ROM" → `!rom_loaded` → `TriggerOpenRom()` - "Open Project" → `!project_loaded` → `TriggerOpenProject()` - "Pick an Editor" → `current_editor == nullptr` → `ShowDashboard()` - **Styling**: Use `AgentUI::GetTheme()` colors, checkmark icon when complete, muted when incomplete --- ### 2. Panel Request Queue (Auto-open after ROM load) **Goal**: Remember blocked panel requests and auto-open them when prerequisites are met. **Implementation**: - **File**: `src/app/editor/system/panel_manager.h/cc` - **New members**: ```cpp std::vector queued_panel_requests_; // Panels awaiting ROM void QueuePanelRequest(const std::string& panel_id); void ProcessQueuedPanels(); // Called when ROM loads ``` - **Wire up**: In `EditorManager`, after successful ROM load: ```cpp panel_manager_.ProcessQueuedPanels(); ``` - **Toast**: Use `ToastManager::Show("Panel will open when ROM loads", ToastType::kInfo)` - **Focus**: Auto-focus first queued panel via `ImGui::SetWindowFocus()` --- ### 3. Dashboard Quick-Picks **Goal**: One-click access to recent work without navigating the sidebar. **Implementation**: - **File**: `src/app/editor/ui/dashboard_panel.cc` - **Location**: Add row above editor grid - **Components**: - "Open Last Editor" button → reads from `user_settings_.prefs().last_editor` - "Recent Files" dropdown → reads from `recent_projects.txt` - **Callback**: `SetQuickPickCallback(std::function)` - **Styling**: Use `gui::PrimaryButton()` for emphasis, secondary buttons for recent files --- ### 4. Sidebar Toggle Tooltip with Shortcut **Goal**: Show current action and keyboard shortcut in tooltip. **Implementation**: - **File**: `src/app/editor/menu/activity_bar.cc` - **Location**: Collapse/expand button tooltip (line ~232) - **Current**: `ImGui::SetTooltip("Collapse Panel");` - **Change to**: ```cpp const char* action = panel_manager_.IsPanelExpanded() ? "Collapse" : "Expand"; const char* shortcut = "Ctrl+B"; // or Cmd+B on macOS ImGui::SetTooltip("%s Panel (%s)", action, shortcut); ``` - **Platform detection**: Use `#ifdef __APPLE__` for Cmd vs Ctrl --- ### 5. Status Bar Chips (ROM Status, Agent Status) **Goal**: Always-visible indicators for why features might be disabled. **Implementation**: - **File**: `src/app/editor/ui/status_bar.cc` - **New method**: `DrawStatusChips()` - **Chips**: ```cpp struct StatusChip { const char* icon; const char* label; ImVec4 color; // From theme (success, warning, error) }; // ROM chip if (rom_ && rom_->is_loaded()) { DrawChip(ICON_MD_CHECK_CIRCLE, rom_->name(), theme.success); } else { DrawChip(ICON_MD_ERROR, "No ROM", theme.warning); } // Agent chip (if YAZE_BUILD_AGENT_UI) DrawChip(agent_connected ? ICON_MD_CLOUD_DONE : ICON_MD_CLOUD_OFF, agent_connected ? "Agent Online" : "Agent Offline", agent_connected ? theme.success : theme.text_disabled); ``` - **Position**: Right side of status bar, before version info - **Interaction**: Click chip → opens relevant action (load ROM / agent settings) --- ### 6. Global Search on Welcome/Dashboard **Goal**: Quick access to commands, panels, and recent files from a single input. **Implementation**: - **File**: `src/app/editor/ui/welcome_screen.cc` or new `global_search_widget.cc` - **Components**: ```cpp class GlobalSearchWidget { char query_[256]; std::vector results_; struct SearchResult { enum Type { kCommand, kPanel, kRecentFile, kEditor }; Type type; std::string display_name; std::string icon; std::function on_select; }; void Search(const char* query); void Draw(); }; ``` - **Sources to search**: - `ShortcutManager::GetShortcuts()` → commands - `PanelManager::GetAllPanelDescriptors()` → panels - `RecentProjects` file → recent files - `EditorRegistry::GetAllEditorTypes()` → editors - **Behavior**: On select → hide welcome/dashboard, execute action - **Styling**: Centered search bar, dropdown results with fuzzy matching --- ### 7. Sticky Hint for Blocked Actions **Goal**: Persistent reminder when actions are blocked, clearing when resolved. **Implementation**: - **File**: `src/app/editor/ui/toast_manager.h/cc` - **New toast type**: `ToastType::kStickyHint` - **Behavior**: - Doesn't auto-dismiss (no timeout) - Has explicit dismiss callback: `on_condition_met` - Displayed in status bar area (not floating) ```cpp void ShowStickyHint(const std::string& message, std::function dismiss_condition); // Usage: toast_manager_.ShowStickyHint( "Load a ROM to enable this feature", [this]() { return rom_ && rom_->is_loaded(); }); ``` - **Visual**: Muted background, dismissible X button, auto-clears when condition met - **Position**: Below main toolbar or in status bar notification area --- ### 8. Activity Bar Icon State Improvements **Goal**: Better visual feedback for icon states. **Implementation**: - **File**: `src/app/editor/menu/activity_bar.cc` - **Enhancements**: - **Disabled state**: 50% opacity + lock icon overlay for ROM-gated categories - **Hover state**: Subtle background highlight even when inactive - **Badge support**: Small dot/number for notifications (e.g., "3 unsaved changes") ```cpp // Badge drawing after icon button if (has_badge) { ImVec2 badge_pos = {cursor.x + 36, cursor.y + 4}; DrawList->AddCircleFilled(badge_pos, 6.0f, badge_color); // Optional: draw count text } ``` - **Animation**: Consider subtle pulse for categories with pending actions --- ### 9. Collapse/Expand Icon Inversion Fix **Goal**: Glyph should reflect the action, not the state. **Implementation**: - **File**: `src/app/editor/menu/activity_bar.cc` (line ~232) - **Current issue**: Icon shows "collapse" when collapsed - **Fix**: ```cpp const char* icon = panel_manager_.IsPanelExpanded() ? ICON_MD_KEYBOARD_DOUBLE_ARROW_LEFT // Collapse action : ICON_MD_KEYBOARD_DOUBLE_ARROW_RIGHT; // Expand action ``` - **Tooltip**: Should match: "Collapse Panel" vs "Expand Panel" --- ### 10. Startup State Logging for CLI/Testing **Goal**: Emit structured log for reproducibility and debugging. **Implementation**: - **File**: `src/app/editor/ui/ui_coordinator.cc` - **Location**: End of constructor or in `DrawWelcomeScreen()` first call - **Log format**: ```cpp LOG_INFO("Startup", "State: surface=%s rom=%s welcome=%s dashboard=%s " "sidebar=%s panel_expanded=%s active_category=%s", GetStartupSurfaceName(current_startup_surface_), rom_loaded ? "loaded" : "none", ShouldShowWelcome() ? "visible" : "hidden", ShouldShowDashboard() ? "visible" : "hidden", ShouldShowActivityBar() ? "visible" : "hidden", panel_manager_.IsPanelExpanded() ? "expanded" : "collapsed", panel_manager_.GetActiveCategory().c_str()); ``` - **CLI flag**: `--log-startup-state` to enable verbose startup logging --- ## Priority Order for Future Implementation 1. **Status Bar Chips** - High visibility, low complexity 2. **Collapse/Expand Icon Fix** - Quick fix, improves UX 3. **Sidebar Toggle Tooltip** - Quick enhancement 4. **Panel Request Queue** - Medium complexity, high value 5. **Dashboard Quick-Picks** - Medium complexity 6. **Empty State Checklist** - Helps onboarding 7. **Global Search** - High complexity, high value 8. **Sticky Hints** - Medium complexity 9. **Activity Bar Badges** - Nice polish 10. **Startup State Logging** - Developer tooling