Positional Right‑Sidebar Docks vs Shared‑Rail Modes for Plugin Panels in GeoLibre
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, 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
// 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, 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) 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"ordock: "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
hideOwnRailflag to render nothing while maintaining React state
Implementation Example
// 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 implements the shared‑rail surface. It:
- Creates a combined rail with entries from both the built‑in panel and the plugin panel
- maintains both components in the React tree regardless of visibility
- coordinates expand/collapse logic so only one panel shows content at a time
- passes
hideOwnRailto collapsed panels so they render null while staying mounted
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"ordock: "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.tsxdetermines which strategy applies based on thedockvalue - 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 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 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, unrecognized values default to the positional right‑sidebar dock behavior, rendering as a standalone rail on the far‑right edge.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →