Skip to content

feat(dashboard): make the dashboard panel collapsible (#459)#463

Merged
giswqs merged 1 commit into
mainfrom
feat/collapsible-dashboard
Jun 18, 2026
Merged

feat(dashboard): make the dashboard panel collapsible (#459)#463
giswqs merged 1 commit into
mainfrom
feat/collapsible-dashboard

Conversation

@giswqs

@giswqs giswqs commented Jun 18, 2026

Copy link
Copy Markdown
Member

Summary

Closes #459. The Dashboard panel can now be collapsed to a thin header bar at the bottom of the screen with a single click, reclaiming the full map view, and expanded back to its previous height — no more deactivating it via the menu or dragging the divider to the bottom.

  • Added a collapse/expand toggle to the dashboard header (using the PanelBottomClose / PanelBottomOpen icons), placed beside the close button.
  • When collapsed, the resize handle, column picker, Add widget button, and widget grid are hidden; only the header bar remains docked at the bottom.
  • The last height is kept in component state, so expanding restores the panel to exactly the size it was last resized to (the issue's requested behavior).
  • New i18n strings dashboard.collapse / dashboard.expand in en.json (the typed source of truth; other locales fall back to English).

Mirrors the existing collapse pattern in NotebookPanel.

Testing

  • npm run typecheck (full build) passes.
  • pre-commit run --files … passes (eslint + npm build).
  • Verified end-to-end in the real app with Playwright against a real US-states GeoJSON layer:
    • Resized the expanded panel to 480px via keyboard.
    • Collapse → panel height dropped to 46px (header only); resize separator and Add widget button removed; button relabeled "Expand dashboard".
    • Expand → panel restored to exactly 480px with all controls back.

Summary by CodeRabbit

  • New Features
    • Dashboard panel now supports collapsing into a header-only view with new collapse/expand button visuals.
    • Widget list and add widget button are hidden when the panel is collapsed and shown when expanded.

Add a collapse/expand toggle to the Dashboard panel header so users can
temporarily reclaim the full map view without deactivating the dashboard
or dragging the divider to the bottom.

Collapsing hides the resize handle, column picker, Add widget button, and
widget grid, leaving just the header bar docked at the bottom. The last
height is kept in state, so expanding restores the panel to exactly the
size it was last dragged/resized to. Mirrors NotebookPanel's collapse
pattern using PanelBottomClose/PanelBottomOpen icons.
@netlify

netlify Bot commented Jun 18, 2026

Copy link
Copy Markdown

Deploy Preview for geolibre-app ready!

Name Link
🔨 Latest commit e36aa6d
🔍 Latest deploy log https://app.netlify.com/projects/geolibre-app/deploys/6a334dd0ef78510008493ec4
😎 Deploy Preview https://deploy-preview-463--geolibre-app.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 9d963d54-0d9e-4376-a753-de0db6bc6648

📥 Commits

Reviewing files that changed from the base of the PR and between d949203 and e36aa6d.

📒 Files selected for processing (2)
  • apps/geolibre-desktop/src/components/panels/DashboardPanel.tsx
  • apps/geolibre-desktop/src/i18n/locales/en.json

📝 Walkthrough

Walkthrough

DashboardPanel gains an isCollapsed state that toggles a header-only view. When collapsed, the panel height is set to zero (preserving the last dragged height for restore), the resize drag handle is hidden, the "add widget" button is hidden, new PanelBottomOpen/PanelBottomClose icons replace the old toggle visuals, and the entire widget grid is conditionally unmounted. Two i18n strings support the new button labels.

Changes

Dashboard collapse/expand feature

Layer / File(s) Summary
isCollapsed state and icon imports
apps/geolibre-desktop/src/components/panels/DashboardPanel.tsx
Adds isCollapsed boolean state and replaces the previous bottom-panel icon import with PanelBottomClose and PanelBottomOpen from lucide-react.
Panel height, resize handle, header wiring, and i18n
apps/geolibre-desktop/src/components/panels/DashboardPanel.tsx, apps/geolibre-desktop/src/i18n/locales/en.json
Conditionally applies inline height to preserve last-dragged size, hides the drag resize separator when collapsed, updates the header collapse/expand button to toggle isCollapsed with the new icons, guards the "add widget" button behind !isCollapsed, and adds collapse/expand locale strings.
Conditional widget grid rendering
apps/geolibre-desktop/src/components/panels/DashboardPanel.tsx
Wraps the full widget list/grid and empty-state region in an !isCollapsed guard, unmounting the content area entirely when the panel is collapsed.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Hop, hop, the dashboard tucks away,
A single click to clear the map's display.
The widgets hide, the height recalled,
No more drag-and-drop when walls feel walled.
Expand again with one small bound —
The rabbit kept your last resize sound! 🗺️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main feature: making the dashboard panel collapsible, which matches the core objective of the changeset.
Linked Issues check ✅ Passed The implementation fully addresses issue #459 by adding collapse/expand toggle functionality with state preservation, matching all stated requirements.
Out of Scope Changes check ✅ Passed All changes directly support the collapsible dashboard feature: DashboardPanel component modifications and i18n strings for collapse/expand labels.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/collapsible-dashboard

Comment @coderabbitai help to get the list of available commands and usage tips.

@giswqs giswqs merged commit fe227e8 into main Jun 18, 2026
17 of 18 checks passed
@giswqs giswqs deleted the feat/collapsible-dashboard branch June 18, 2026 01:50
Comment on lines +86 to +89
// Collapse the panel to just its header bar for a full map view, without
// losing the last height (issue #459). The height is kept in state so an
// expand restores the panel to exactly the size the user last dragged it to.
const [isCollapsed, setIsCollapsed] = useState(false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CLAUDE.md violation — issue reference in comment

(issue #459) is the kind of reference CLAUDE.md explicitly says to keep in the PR description, not in source comments: "Don't reference the current task, fix, or callers…since those belong in the PR description and rot as the codebase evolves."

The non-obvious WHY (keeping height separate from the collapsed flag so an expand round-trip restores the last drag size) is worth preserving; only the tracker link needs to go.

Suggested change
// Collapse the panel to just its header bar for a full map view, without
// losing the last height (issue #459). The height is kept in state so an
// expand restores the panel to exactly the size the user last dragged it to.
const [isCollapsed, setIsCollapsed] = useState(false);
// Height is kept separately from `isCollapsed` so expanding restores the
// panel to the exact size the user last dragged it to.
const [isCollapsed, setIsCollapsed] = useState(false);

Comment on lines 246 to 263
<Button
variant="outline"
size="sm"
className="h-8 px-2"
onClick={openAdd}
disabled={chartableLayers.length === 0}
variant="ghost"
size="icon"
className="h-8 w-8"
aria-label={
isCollapsed ? t("dashboard.expand") : t("dashboard.collapse")
}
title={
chartableLayers.length === 0
? t("dashboard.noLayersHint")
: t("dashboard.addWidget")
isCollapsed ? t("dashboard.expand") : t("dashboard.collapse")
}
onClick={() => setIsCollapsed((c) => !c)}
>
<Plus className="h-3.5 w-3.5" />
<span className="hidden sm:inline">{t("dashboard.addWidget")}</span>
{isCollapsed ? (
<PanelBottomOpen className="h-4 w-4" />
) : (
<PanelBottomClose className="h-4 w-4" />
)}
</Button>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Accessibility — missing aria-expanded

For a disclosure button (one that shows/hides a region), aria-expanded is the correct ARIA attribute to communicate the current state to assistive technologies. The dynamic aria-label communicates the next action ("Collapse dashboard" / "Expand dashboard"), which is fine, but aria-expanded additionally exposes the current state to AT without requiring the AT to parse the label. Both together follow the ARIA authoring practices for disclosure widgets.

Suggested change
<Button
variant="outline"
size="sm"
className="h-8 px-2"
onClick={openAdd}
disabled={chartableLayers.length === 0}
variant="ghost"
size="icon"
className="h-8 w-8"
aria-label={
isCollapsed ? t("dashboard.expand") : t("dashboard.collapse")
}
title={
chartableLayers.length === 0
? t("dashboard.noLayersHint")
: t("dashboard.addWidget")
isCollapsed ? t("dashboard.expand") : t("dashboard.collapse")
}
onClick={() => setIsCollapsed((c) => !c)}
>
<Plus className="h-3.5 w-3.5" />
<span className="hidden sm:inline">{t("dashboard.addWidget")}</span>
{isCollapsed ? (
<PanelBottomOpen className="h-4 w-4" />
) : (
<PanelBottomClose className="h-4 w-4" />
)}
</Button>
<Button
variant="ghost"
size="icon"
className="h-8 w-8"
isCollapsed ? t("dashboard.expand") : t("dashboard.collapse")
}
aria-expanded={!isCollapsed}
isCollapsed ? t("dashboard.expand") : t("dashboard.collapse")
}
onClick={() => setIsCollapsed((c) => !c)}
>
{isCollapsed ? (
<PanelBottomOpen className="h-4 w-4" />
) : (
<PanelBottomClose className="h-4 w-4" />
)}
</Button>

@github-actions

Copy link
Copy Markdown
Contributor

Code review

Reviewed DashboardPanel.tsx (165 changed lines) and en.json (+2 keys). Verified the collapse/expand state machine, resize interaction, style-prop handling, i18n additions, and compared the pattern against NotebookPanel.tsx. Two findings:


CLAUDE.md

Finding Confidence
🔴 Comment contains issue reference (#459) — CLAUDE.md says "Don't reference the current task, fix, or callers…since those belong in the PR description and rot as the codebase evolves." The explanatory WHY is worth keeping; only the (issue #459) token needs to be dropped. See inline suggestion on line 86–89. High

Accessibility

Finding Confidence
🟡 Collapse button missing aria-expanded — The button correctly updates its aria-label to reflect the next action, but ARIA authoring practices for disclosure buttons recommend also setting aria-expanded to communicate the current state. The aria-label swap alone is not incorrect, but aria-expanded makes the state machine explicit for AT without requiring label parsing. See inline suggestion on lines 246–263. Medium

Bugs / Performance / Security

Nothing found. Specifically checked:

  • Style-during-resize race: startResize attaches mousemove/mouseup to window and updates the DOM directly via RAF; React's style={isCollapsed ? undefined : { height }} will clear the inline style on collapse and restore it on expand from the React state. There is a one-frame window where a pending RAF could re-apply a height after React collapses the panel, but this requires simultaneously dragging the resize handle and activating the collapse button — not reachable via normal UI. Not a practical concern.
  • isCollapsed resets on close/reopen: Closing the dashboard unmounts the component, so isCollapsed and height both reset. This is consistent with the pre-existing height behavior and the NotebookPanel pattern, so it is not a regression.
  • No stale-closure risk in startResize — it is redefined on each render and always captures the current height.
  • i18n additions are in en.json only (the typed source of truth); other locales fall back correctly per the project's policy.
  • Icon semantics (PanelBottomClose for collapse, PanelBottomOpen for expand) are correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Featurerequest: Dashboard should be collapsible.

1 participant