# Positional Right‑Sidebar Docks vs Shared‑Rail Modes for Plugin Panels in GeoLibre

> Discover the key differences between positional right-sidebar docks and shared-rail modes for GeoLibre plugin panels. Understand how each mode manages panel mounting and state preservation to optimize your workflow.

- Repository: [Open Geospatial Solutions/GeoLibre](https://github.com/opengeos/GeoLibre)
- Tags: internals
- Published: 2026-08-15

---

**Positional right‑sidebar docks create independent rails on the far‑right edge where panels unmount when collapsed, while shared‑rail modes let plugins replace the built‑in Layers or Style sidebar, keeping both panels mounted and preserving state.**

GeoLibre's plugin architecture offers two distinct ways to expose **right‑sidebar panels**, each with different implications for UI layout, component lifecycle, and user experience. Understanding when to use **positional right‑sidebar docks** versus **shared‑rail modes** is essential for building plugins that integrate naturally with the desktop application's shell.

---

## How Right‑Sidebar Docking Works in GeoLibre

In [`apps/geolibre-desktop/src/components/layout/DesktopShell.tsx`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/components/layout/DesktopShell.tsx), the shell inspects each plugin panel's `dock` property to determine rendering strategy. This single configuration value branches the layout into two fundamentally different behaviors.

---

## Positional Right‑Sidebar Dock: Stand‑Alone Rails

The **positional right‑sidebar dock** assigns a plugin its own dedicated rail on the far‑right edge of the application window.

### Key Characteristics

- **Dock value**: `dock: "right"` or any custom string that is **not** a replace‑mode
- **Rail independence**: The panel gets its own rail entry with an icon and title, sitting alongside the built‑in *Layers* and *Style* sidebars
- **Simultaneous visibility**: Users can expand multiple right‑side rails at once
- **Unmounted on collapse**: The React component is **removed from the DOM** when collapsed; internal state is lost unless manually persisted

### Implementation Example

```tsx
// Positional right‑sidebar dock (stand‑alone rail)
export const MyMeasurementsPanel = {
  id: "measurements",
  title: "Measurements",
  icon: "measure.svg",
  dock: "right",          // <-- separate rail on the far‑right edge
  Component: MeasurementsComponent,
};

```

### Source Implementation

In [`apps/geolibre-desktop/src/components/panels/PluginRightPanel.tsx`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/components/panels/PluginRightPanel.tsx), the `PluginRightPanel` component receives the `dock` prop and renders the panel content. When `dock="right"`, the shell wraps this in a standalone `<RightPanel>` container rather than embedding it in a shared rail.

The `useRightPanelState` hook ([`apps/geolibre-desktop/src/hooks/useRightPanels.ts`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/hooks/useRightPanels.ts)) tracks the active panel ID and collapse state, but the component lifecycle is managed by React's standard conditional rendering—when collapsed, the panel simply isn't rendered.

### Best Use Cases

- **Stand‑alone tools** like measurement utilities, coordinate converters, or data exporters
- Panels that need **persistent dedicated space** without competing for limited sidebar width
- Workflows where users need **multiple tools visible simultaneously**

---

## Shared‑Rail Mode: Replacing Built‑In Sidebars

The **shared‑rail mode** allows a plugin panel to **replace** either the built‑in *Layers* sidebar (`replace-layers`) or the *Style* sidebar (`replace-style`), sharing a single rail between the built‑in panel and the plugin panel.

### Key Characteristics

- **Dock values**: `dock: "replace-layers"` or `dock: "replace-style"`
- **Rail sharing**: Both built‑in and plugin panels occupy the **same rail entry list**
- **Mutual exclusivity**: Only one panel expanded at a time; selecting one automatically collapses the other
- **Preserved state**: Both panels stay **mounted** even when collapsed, using the `hideOwnRail` flag to render nothing while maintaining React state

### Implementation Example

```tsx
// Shared‑rail mode (replaces the built‑in Layers panel)
export const MyBrowserPanel = {
  id: "browser",
  title: "Browser",
  icon: "browser.svg",
  dock: "replace-layers", // <-- shares the Layers sidebar rail
  Component: BrowserComponent,
};

```

### Source Implementation

The `SharedSidebar` component in [`apps/geolibre-desktop/src/components/panels/SharedSidebar.tsx`](https://github.com/opengeos/GeoLibre/blob/main/apps/geolibre-desktop/src/components/panels/SharedSidebar.tsx) implements the shared‑rail surface. It:

1. Creates a combined rail with entries from both the built‑in panel and the plugin panel
2. maintains both components in the React tree regardless of visibility
3. coordinates expand/collapse logic so only one panel shows content at a time
4. passes `hideOwnRail` to collapsed panels so they render null while staying mounted

[`DesktopShell.tsx`](https://github.com/opengeos/GeoLibre/blob/main/DesktopShell.tsx) routes panels with `replace-*` dock values into this `SharedSidebar` rather than rendering them as standalone rails.

### Best Use Cases

- **Conceptual replacements** for built‑in functionality (custom layer browsers, alternative style editors)
- Workflows where **screen real estate is constrained** and multiple rails would clutter the interface
- Panels that need to **preserve complex state** (selections, scroll positions, form inputs) across toggle operations

---

## Side‑By‑Side Comparison

| Aspect | Positional Right‑Sidebar Dock | Shared‑Rail Mode |
|--------|------------------------------|------------------|
| **Configuration** | `dock: "right"` | `dock: "replace-layers"` or `dock: "replace-style"` |
| **Rail ownership** | Independent rail on far‑right | Shared with *Layers* or *Style* sidebar |
| **Visual layout** | Standalone vertical strip | Combined entry list with built‑in panel |
| **Expansion behavior** | Independent; multiple rails can be open | Mutually exclusive; one panel at a time |
| **Component lifecycle** | **Unmounted** when collapsed | **Remains mounted** when collapsed |
| **State preservation** | Manual persistence required | Automatic via React state |
| **Typical plugins** | Measurement tools, exporters | Layer browsers, style editors |

---

## Choosing the Right Docking Strategy

Consider these factors when selecting between **positional right‑sidebar docks** and **shared‑rail modes**:

- **Does your plugin conceptually replace a built‑in feature?** → Use **shared‑rail mode**
- **Do users need your tool alongside other sidebars simultaneously?** → Use **positional dock**
- **Does your panel hold complex state that would be expensive to reconstruct?** → Use **shared‑rail mode** for automatic preservation
- **Is your tool entirely new functionality with no built‑in equivalent?** → Use **positional dock**

---

## Summary

- **Positional right‑sidebar docks** (`dock: "right"`) give plugins an independent rail on the far‑right edge, allowing multiple rails open simultaneously but unmounting components when collapsed
- **Shared‑rail modes** (`dock: "replace-layers"` or `dock: "replace-style"`) let plugins share a rail with built‑in panels, enforcing mutual exclusivity while preserving component state via continuous mounting
- The shell's routing logic in [`DesktopShell.tsx`](https://github.com/opengeos/GeoLibre/blob/main/DesktopShell.tsx) determines which strategy applies based on the `dock` value
- Choose **positional docks** for stand‑alone tools and **shared rails** for conceptual replacements that need state persistence

---

## Frequently Asked Questions

### How do I preserve state in a positional right‑sidebar dock panel?

You must implement manual state persistence, such as lifting state to a context store or using external state management. According to the GeoLibre source code, [`PluginRightPanel.tsx`](https://github.com/opengeos/GeoLibre/blob/main/PluginRightPanel.tsx) conditionally renders the component based on expansion state, causing full unmount when collapsed.

### Can multiple plugins share the same rail in shared‑rail mode?

The current [`SharedSidebar.tsx`](https://github.com/opengeos/GeoLibre/blob/main/SharedSidebar.tsx) implementation supports one built‑in panel and one plugin panel per rail. Multiple plugins configured with the same `replace-*` dock value would compete for the same slot; the last registered panel typically wins.

### Does shared‑rail mode affect the left sidebar (Layers) or right sidebar (Style)?

Both. Use `dock: "replace-layers"` to share the **left** sidebar rail with the Layers panel, or `dock: "replace-style"` to share the **right** sidebar rail with the Style panel. The replacement target is explicit in the dock value.

### What happens if I use an unrecognized dock value?

Per [`DesktopShell.tsx`](https://github.com/opengeos/GeoLibre/blob/main/DesktopShell.tsx), unrecognized values default to the **positional right‑sidebar dock** behavior, rendering as a standalone rail on the far‑right edge.