diff --git a/apps/geolibre-desktop/src/components/layout/DesktopShell.tsx b/apps/geolibre-desktop/src/components/layout/DesktopShell.tsx index f5b96de388..ae656a8166 100644 --- a/apps/geolibre-desktop/src/components/layout/DesktopShell.tsx +++ b/apps/geolibre-desktop/src/components/layout/DesktopShell.tsx @@ -2227,7 +2227,9 @@ export function DesktopShell({ // On a phone-width viewport both start collapsed (panels overlay // there), matching the mobile "panels default collapsed" behavior. initialBuiltinExpanded={ - replaceLayersPanelId === BROWSER_PANEL_ID && !getIsMobileViewport() + replaceLayersPanelId === BROWSER_PANEL_ID && + !getIsMobileViewport() && + !layoutOptions.panelsCollapsed } // The story-map presentation is the only standalone Layers // autoCollapse trigger (the notebook collapses Style, not Layers). @@ -2267,7 +2269,11 @@ export function DesktopShell({ openRasterLayerPanel(createAppAPI(mapControllerRef)) } onOpenRasterSubset={setRasterSubsetLayer} - autoCollapse={storymapPresenting || autoCollapsedPanel === "layers"} + autoCollapse={ + storymapPresenting || + layoutOptions.panelsCollapsed || + autoCollapsedPanel === "layers" + } /> )} @@ -2508,7 +2514,10 @@ export function DesktopShell({ mapControllerRef={mapControllerRef} onResizeStart={startStylePanelResize} autoCollapse={ - notebookOpen || storymapPresenting || autoCollapsedPanel === "style" + notebookOpen || + storymapPresenting || + layoutOptions.panelsCollapsed || + autoCollapsedPanel === "style" } /> diff --git a/apps/geolibre-desktop/src/hooks/useLayoutOptions.ts b/apps/geolibre-desktop/src/hooks/useLayoutOptions.ts index 627fba9cce..6eac49cb23 100644 --- a/apps/geolibre-desktop/src/hooks/useLayoutOptions.ts +++ b/apps/geolibre-desktop/src/hooks/useLayoutOptions.ts @@ -14,6 +14,8 @@ export interface LayoutOptions { * shared rail — so a map-only embed shows nothing but the map. */ panelsHidden: boolean; + /** Start the Layers and Style panels on their rails without hiding them. */ + panelsCollapsed: boolean; showProjectInfo: boolean; statusBarVisible: boolean; stylePanelVisible: boolean; @@ -41,6 +43,7 @@ export function layoutOptionsFromLocation(layoutSettings: DesktopLayoutSettings) attributePanelVisible: true, compact: false, panelsHidden: false, + panelsCollapsed: false, statusBarVisible: true, toolbarVisible: true, viewer: false, @@ -67,6 +70,7 @@ export function layoutOptionsFromLocation(layoutSettings: DesktopLayoutSettings) mapOnly || HIDDEN_PANEL_VALUES.has(panels) || normalizedParam(params.get("hidePanels")) === "true"; + const panelsCollapsed = !panelsHidden && panels === "collapsed"; const toolbarLabels = !compact && !ICON_TOOLBAR_VALUES.has(toolbar) ? layoutSettings.toolbarLabels : false; const showProjectInfo = compact ? false : layoutSettings.showProjectInfo; @@ -82,6 +86,7 @@ export function layoutOptionsFromLocation(layoutSettings: DesktopLayoutSettings) compact, layerPanelVisible, panelsHidden, + panelsCollapsed, showProjectInfo, statusBarVisible: !mapOnly, stylePanelVisible, diff --git a/docs/index.md b/docs/index.md index 71e952b1d2..fdf488933b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -152,6 +152,9 @@ https://web.geolibre.app/?url=https://share.geolibre.app/giswqs/3d-tiles.geolibr Use `toolbar=icons` when you only want icon-only toolbar buttons. `panels=hidden`, `panels=hide`, `panels=off`, and `hidePanels=true` are accepted aliases for hiding panels. +Use `panels=collapsed` to keep the Layers and Style icon rails visible while +starting both panels collapsed. + For a fully chrome-free, map-only embed, add `&maponly` to hide the toolbar menu, all panels, and the status bar: ```text diff --git a/docs/user-guide/embedding.md b/docs/user-guide/embedding.md index 3c0d39a0d2..52482a0602 100644 --- a/docs/user-guide/embedding.md +++ b/docs/user-guide/embedding.md @@ -25,7 +25,7 @@ A chrome-free `maponly` embed shows only the map, as in this shared 3D Tiles pro | `url` | `url=https://share.geolibre.app/you/project.geolibre.json` | Loads a `.geolibre.json` project from a public URL. | | `layout` | `layout=viewer` | `viewer` provides read-only chrome: Layers, View, Controls, basemaps, search/identify, and Help, with authoring UI hidden. `compact` is the icon-only full-app layout; `embed` and `iframe` are aliases. | | `toolbar` | `toolbar=icons` | Icon-only toolbar buttons without the full compact layout. `icon` and `icon-only` are aliases. | -| `panels` | `panels=none` | Hides the Layers, Style, and Attribute table panels. `hidden`, `hide`, and `off` are aliases. | +| `panels` | `panels=collapsed` | Starts Layers and Style collapsed to their icon rails. Use `none` to hide all panels; `hidden`, `hide`, and `off` are aliases. | | `hidePanels` | `hidePanels=true` | Alternative way to hide those panels. | | `maponly` | `maponly` | Hides all chrome (toolbar, panels, and status bar), leaving only the map. The bare flag or `true`, `1`, `yes`, `on` enable it. | | `welcome` | `welcome=0` | Hides the first-launch welcome wizard. Accepts `0`, `false`, `off`, or `no`. A `url=` deep link already suppresses it automatically. | diff --git a/tests/layout-options.test.ts b/tests/layout-options.test.ts index 8f6f9d0e02..c7f49a6759 100644 --- a/tests/layout-options.test.ts +++ b/tests/layout-options.test.ts @@ -29,6 +29,7 @@ describe("layoutOptionsFromLocation", () => { assert.equal(options.stylePanelVisible, true); assert.equal(options.attributePanelVisible, true); assert.equal(options.panelsHidden, false); + assert.equal(options.panelsCollapsed, false); }); it("hides every chrome element when maponly is set as a bare flag", () => { @@ -88,6 +89,17 @@ describe("layoutOptionsFromLocation", () => { assert.equal(options.panelsHidden, true); }); + it("starts side panels collapsed without hiding their rails", () => { + withSearch("?panels=collapsed"); + const options = layoutOptionsFromLocation(DEFAULT_DESKTOP_LAYOUT_SETTINGS); + assert.equal(options.toolbarVisible, true); + assert.equal(options.layerPanelVisible, true); + assert.equal(options.stylePanelVisible, true); + assert.equal(options.attributePanelVisible, true); + assert.equal(options.panelsHidden, false); + assert.equal(options.panelsCollapsed, true); + }); + it("provides read-only viewer chrome between the full app and maponly", () => { withSearch("?layout=viewer"); const options = layoutOptionsFromLocation(DEFAULT_DESKTOP_LAYOUT_SETTINGS);