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

> Discover the Omarchy bar widget panels lifecycle: summon, hide, and toggle mechanisms. Learn how pickPanelSlot summons, hides, and toggles panels in the QML layer.

- Repository: [Omacom/omarchy](https://github.com/omacom/omarchy)
- Tags: internals
- Published: 2026-09-10

---

**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`](https://github.com/omacom/omarchy/blob/main/BarModel.js) executes the `pickPanelSlot()` function to determine the target instance. The selection logic in [`shell/plugins/bar/BarModel.js`](https://github.com/omacom/omarchy/blob/main/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:

```qml
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`](https://github.com/omacom/omarchy/blob/main/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

```bash

# 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:

```javascript
// 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`](https://github.com/omacom/omarchy/blob/main/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`](https://github.com/omacom/omarchy/blob/main/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.