Files
yaze/docs/internal/architecture/ui_layout_system.md

7.6 KiB

YAZE UI Layout Documentation

This document describes the layout logic for the YAZE editor interface, specifically focusing on the menu bar and sidebar interactions.

Menu Bar Layout

The main menu bar in UICoordinator::DrawMenuBarExtras handles the right-aligned status cluster.

Right-Aligned Status Cluster

The status cluster in DrawMenuBarExtras includes (in order from left to right):

  1. Version: vX.Y.Z (May be hidden on narrow windows)
  2. Dirty Indicator: Warning-colored dot (Visible when ROM has unsaved changes)
  3. Session Switcher: Layers icon (Visible when multiple sessions are open, may be hidden on narrow windows)
  4. Notification Bell: Bell icon (Always visible - high priority)

Panel Toggle Buttons

Panel toggle buttons are drawn at the end of the menu bar using screen coordinates:

  1. Panel Toggles: Icons for Agent, Proposals, Settings, Properties
  2. WASM Toggle: Chevron icon (Visible only in Emscripten builds)

These are positioned using ImGui::SetCursorScreenPos() with coordinates calculated from the true viewport (not the dockspace window). This ensures they remain in a fixed position even when panels open/close and the dockspace resizes.

Button Styling

All menu bar icon buttons use consistent styling via DrawMenuBarIconButton():

  • Transparent background
  • SurfaceContainerHigh color on hover
  • SurfaceContainerHighest color when active/pressed
  • TextSecondary color for inactive icons
  • Primary color for active icons (e.g., when a panel is open)

Sizing Calculation

The cluster_width is calculated dynamically using GetMenuBarIconButtonWidth() which accounts for:

  • Icon text width (using ImGui::CalcTextSize)
  • Frame padding (FramePadding.x * 2)
  • Item spacing between elements (6px)

The number of panel toggle buttons is determined at compile time:

  • With YAZE_WITH_GRPC: 4 buttons (Agent, Proposals, Settings, Properties)
  • Without YAZE_WITH_GRPC: 3 buttons (Proposals, Settings, Properties)

Responsive Behavior

When the window is too narrow to display all elements, they are hidden progressively based on priority:

  1. Always shown: Notification bell, WASM toggle, dirty indicator
  2. High priority: Version text
  3. Medium priority: Session switcher button
  4. Low priority: Panel toggle buttons

The available width is calculated as:

float available_width = menu_bar_end - menu_items_end - padding;

Right Panel Interaction

When the Right Panel (Agent, Settings, etc.) is expanded, it occupies the right side of the viewport.

The menubar uses screen coordinate positioning for optimal UX:

  1. Fixed Panel Toggles: Panel toggle buttons are positioned using ImGui::SetCursorScreenPos() with coordinates calculated from the true viewport. This keeps them at a fixed screen position regardless of dockspace resizing.

  2. Status Cluster: Version, dirty indicator, session button, and notification bell are drawn inside the dockspace menu bar using relative positioning. They shift naturally when panels open/close as the dockspace resizes.

// Panel toggle screen positioning (in DrawMenuBarExtras)
const ImGuiViewport* viewport = ImGui::GetMainViewport();
float panel_screen_x = viewport->WorkPos.x + viewport->WorkSize.x - panel_region_width;
if (panel_manager->IsPanelExpanded()) {
  panel_screen_x -= panel_manager->GetPanelWidth();
}
ImGui::SetCursorScreenPos(ImVec2(panel_screen_x, menu_bar_y));

This ensures users can quickly toggle panels without chasing moving buttons.

Menu Bar Positioning Patterns

When adding or modifying menu bar elements, choose the appropriate positioning strategy:

Pattern 1: Relative Positioning (Elements That Shift)

Use standard ImGui::SameLine() with window-relative coordinates for elements that should move naturally when the dockspace resizes:

const float window_width = ImGui::GetWindowWidth();
float start_pos = window_width - element_width - padding;
ImGui::SameLine(start_pos);
ImGui::Text("Shifting Element");

Use for: Version text, dirty indicator, session button, notification bell

Behavior: These elements shift left when a panel opens (dockspace shrinks)

Pattern 2: Screen Positioning (Elements That Stay Fixed)

Use ImGui::SetCursorScreenPos() with true viewport coordinates for elements that should remain at a fixed screen position:

// Get TRUE viewport dimensions (not affected by dockspace resize)
const ImGuiViewport* viewport = ImGui::GetMainViewport();
float screen_x = viewport->WorkPos.x + viewport->WorkSize.x - element_width;

// Adjust for any open panels
if (panel_manager->IsPanelExpanded()) {
  screen_x -= panel_manager->GetPanelWidth();
}

// Keep Y from current menu bar context
float screen_y = ImGui::GetCursorScreenPos().y;

// Position and draw
ImGui::SetCursorScreenPos(ImVec2(screen_x, screen_y));
ImGui::Button("Fixed Element");

Use for: Panel toggle buttons, any UI that should stay accessible when panels open

Behavior: These elements stay at a fixed screen position regardless of dockspace size

Key Coordinate Functions

Function Returns Use Case
ImGui::GetWindowWidth() Dockspace window width Relative positioning within menu bar
ImGui::GetMainViewport()->WorkSize.x True viewport width Fixed screen positioning
ImGui::GetWindowPos() Window screen position Converting between coordinate systems
ImGui::GetCursorScreenPos() Current cursor screen position Getting Y coordinate for screen positioning
ImGui::SetCursorScreenPos() N/A (sets position) Positioning at absolute screen coordinates

Common Pitfall

Do NOT use ImGui::GetWindowWidth() when calculating fixed positions. The window width changes when panels open/close, causing elements to shift. Always use ImGui::GetMainViewport() for fixed positioning.

Right Panel Styling

Panel Header

The panel header uses an elevated background (SurfaceContainerHigh) with:

  • Icon in primary color
  • Title in standard text color
  • Large close button (28x28) with rounded corners
  • Keyboard shortcut: Escape closes the panel

Panel Content Styling

Content uses consistent styling helpers:

  • BeginPanelSection() / EndPanelSection(): Collapsible sections with icons
  • DrawPanelDivider(): Themed separators
  • DrawPanelLabel(): Secondary text color labels
  • DrawPanelValue(): Label + value pairs
  • DrawPanelDescription(): Wrapped disabled text for descriptions

Color Scheme

  • Backgrounds: SurfaceContainer for panel, SurfaceContainerHigh for sections
  • Borders: Outline color
  • Text: Primary for titles, Secondary for labels, Disabled for descriptions
  • Accents: Primary color for icons and active states

Sidebar Layout

The left sidebar (EditorCardRegistry) provides navigation for editor cards.

Placeholder Sidebar

When no ROM is loaded, EditorManager::DrawPlaceholderSidebar renders a placeholder.

  • Theme: Uses Surface Container color for background to distinguish it from the main window.
  • Content: Displays "Open ROM" and "New Project" buttons.
  • Behavior: Fills the full height of the viewport work area (below the dockspace menu bar).

Active Sidebar

When a ROM is loaded, the sidebar displays editor categories and cards.

  • Width: Fixed width defined in EditorCardRegistry.
  • Collapse: Can be collapsed via the hamburger menu in the menu bar or Ctrl+B.
  • Theme: Matches the placeholder sidebar for consistency.

Theme Integration

The UI uses ThemeManager for consistent colors:

  • Sidebar Background: gui::GetSurfaceContainerVec4()
  • Sidebar Border: gui::GetOutlineVec4()
  • Text: gui::GetTextSecondaryVec4() (for placeholders)