Omarchy Bar Widget Panels Lifecycle: Summon, Hide, and Toggle Mechanisms

The Omarchy bar widget panels follow a strict three-phase lifecycle where pickPanelSlot() selects the correct monitor instance before delegating to summonPanel(), hidePanel(), or togglePanel() methods in the QML layer.

The Omarchy desktop environment builds its status bar per-monitor using Quickshell, creating independent instances of widget panels like network, clock, and battery for each display. Understanding the lifecycle for summoning, hiding, and toggling Omarchy bar widget panels is essential for customizing interactions and debugging panel behavior. This architecture ensures that panel commands always target the correct visual instance based on current focus and visibility state.

How Panel Instances Are Managed Per Monitor

Omarchy instantiates widget panels as QML components once for every monitor that hosts a bar. When you trigger a panel action, the system must first identify which of these duplicate instances should receive the command.

The Panel Slot Selection Algorithm

Before any visibility change occurs, BarModel.js executes the pickPanelSlot() function to determine the target instance. The selection logic in shell/plugins/bar/BarModel.js (lines 61-78) follows this priority:

  1. Opened copy wins – If the panel is currently visible on any monitor, that instance receives the command
  2. Focused monitor fallback – If no copy is open, the instance on the currently focused monitor is selected
  3. First available fallback – If the focused monitor lacks a bar, the first available copy is used

This guarantees that user interactions consistently affect the panel the user is actually viewing or the one most relevant to their current workspace.

The Core Lifecycle Actions

Once the target slot is identified, the Bar model forwards the request to the QML layer in shell/plugins/bar/Bar.qml (lines 745-770), which exposes three public methods controlling the lifecycle:

Summoning a Panel

The summonPanel(id) method makes a widget panel visible or expands its popup. According to the implementation in Bar.qml, this method sets the panel's visible property to true and optionally shifts focus to the widget. If the panel is already visible, the call is a no-op, preventing redundant animations or state flicker.

Hiding a Panel

Conversely, hidePanel(id) collapses the panel or hides its popup entirely. The method first checks the current visibility state in isPanelVisible(id) and only modifies the DOM when necessary. This conditional check prevents unnecessary layout recalculations when the panel is already hidden.

Toggling Visibility

The togglePanel(id) method provides a single-command interface that internally branches:

if (panelIsVisible(id)) {
    hidePanel(id);
} else {
    summonPanel(id);
}

This ensures atomic toggle behavior without race conditions, as the visibility check and state transition occur within the same execution context.

Inline Settings Updates Without Rebuilding

When widget configuration changes—such as toggling battery percentage display—the lifecycle avoids full panel reconstruction. The inlineSettingsDelta() function in BarModel.js (lines 68-102) computes a minimal property delta that applies directly to the existing QML instance. This optimization maintains panel state (scroll position, focus) while updating visual elements, eliminating the flicker associated with destroying and recreating components.

CLI and Programmatic Usage

You can trigger these lifecycle methods through generated CLI commands or direct programmatic access.

Shell Commands


# Summon the network panel on the focused monitor

omarchy-toggle-panel network

# Explicitly hide the battery panel instance currently visible

omarchy-hide-panel battery

# Toggle the clock panel visibility

omarchy-toggle-panel clock

QML Programmatic Access

For custom scripts or widget interactions, access the Bar model directly:

// Select the appropriate slot for the current screen context
BarModel.pickPanelSlot(BarModel.candidateSlots(), Shell.currentScreen())
       .then(slot => slot.summonPanel("network"));

This pattern mirrors the internal CLI implementation, first resolving the correct monitor instance before invoking the lifecycle method.

Summary

  • Instance selection precedes all actions via pickPanelSlot() in shell/plugins/bar/BarModel.js, prioritizing opened copies over focused monitors
  • Summon operations use summonPanel(id) in shell/plugins/bar/Bar.qml to set visibility flags and handle focus
  • Hide operations leverage hidePanel(id) with pre-checks to avoid unnecessary state changes
  • Toggle combines visibility checks and conditional calls to provide atomic state switching
  • Settings updates use inlineSettingsDelta() to modify panels without destroying their QML instances, preserving user context and preventing flicker

Frequently Asked Questions

How does Omarchy decide which monitor displays a summoned panel?

The system calls pickPanelSlot() which first checks for any panel copy already opened (visible) on any monitor. If found, that instance receives the command. If no panel is currently open, Omarchy selects the copy attached to the monitor with current user focus, falling back to the first available bar if the focused screen lacks one.

What happens if I call toggle on a panel that is already animating?

The togglePanel(id) method checks current visibility state atomically before deciding to summon or hide. If the panel is mid-animation but technically visible, it will trigger hidePanel(); if hidden, it triggers summonPanel(). The underlying QML engine queues these state changes, preventing conflicting transitions.

Can I summon a panel on a specific monitor regardless of focus?

Direct specification requires accessing the candidateSlots() array and selecting a specific index rather than using the automatic picker. The default CLI commands (omarchy-toggle-panel) always route through pickPanelSlot(), which respects the opened-then-focused priority order defined in BarModel.js.

Why don't panel settings changes reset my scroll position or selected items?

Omarchy uses inlineSettingsDelta() to compute minimal property changes rather than destroying and reinstantiating QML components. This preserves transient UI state like scroll position, text selection, and focus because the underlying QML object persists while only specific bound properties update.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →