feat(front): make the left sidebar collapsible on desktop - #3055
feat(front): make the left sidebar collapsible on desktop#3055Pierre-Gilles wants to merge 4 commits into
Conversation
The docked 15rem rail costs every page a column of width, which on a dashboard is width the widgets wanted (community request 10740). A chevron button in the rail's brand row undocks it: the rail then behaves exactly as it already does on mobile — off-canvas over a backdrop, opened on demand, closed by backdrop click, Escape or navigation — and the same button docks it back. The choice is a per-device localStorage preference, like dark mode: the same user wants the rail docked on a wide screen and out of the way on a wall tablet. The desktop drawer is opened by a floating frosted button in the 3.25rem gutter the page keeps free on the left, not by a mobile-style top bar: a full-width bar would have cost every page a row (and vertical space is not what drawer mode is for) and would have forced every full-height page and sticky offset written against "no chrome above on desktop" to be re-derived. Nothing moves vertically, so those pages keep working untouched; the chat page's scene slide-back follows the same 3.25rem. Also gives the mobile burger the accessible name it never had. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JnwsS9jopHYHX3GQMViT2c
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (12)
🚧 Files skipped from review as they are similar to previous changes (2)
Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review. 📝 WalkthroughWalkthroughThe PR replaces desktop drawer mode with a persisted collapsible sidebar rail. Header controls update the collapsed state, responsive styles adjust page and chat spacing, and English, German, and French labels support the controls. Mobile drawer Escape handling remains supported. ChangesSidebar collapse mode
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The PR makes the desktop sidebar collapsible while preserving the existing expanded default and mobile behavior. No actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant User
participant Header
participant MainStore
participant LocalStorage
participant PageLayout
User->>Header: click collapse or expand control
Header->>MainStore: toggleSidebarCollapsed()
MainStore->>LocalStorage: save sidebar-collapsed
MainStore-->>Header: update sidebarCollapsed
Header->>PageLayout: set gladys-sidebar-collapsed
PageLayout-->>User: animate rail and page spacing
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Full details: Docstring CoverageExplanation Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 5 files. (7 skipped: 7 unsupported.)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Deploying gladys-plus with
|
| Latest commit: |
3abf632
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://89cc8385.gladys-plus.pages.dev |
| Branch Preview URL: | https://claude-sidebar-drawer-mode-u.gladys-plus.pages.dev |
|
🐳 A Docker image has been built for this branch and pushed to the GitHub Container Registry. You can test this pull request (AMD64 only) by pulling the image below: For example, run it with: sudo docker run -d \
--log-driver json-file \
--log-opt max-size=10m \
--cgroupns=host \
--restart=always \
--privileged \
--network=host \
--name gladys-claude-sidebar-drawer-mode-uljznh \
-e NODE_ENV=production \
-e SERVER_PORT=80 \
-e TZ=Europe/Paris \
-e SQLITE_FILE_PATH=/var/lib/gladysassistant/gladys-production.db \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /var/lib/gladysassistant:/var/lib/gladysassistant \
-v /dev:/dev \
-v /run/udev:/run/udev:ro \
ghcr.io/gladysassistant/gladys-preview:claude-sidebar-drawer-mode-uljznhThis comment and the image are automatically updated on every new commit pushed to this pull request. Need an ARM64 image (Raspberry Pi, Apple Silicon, …)? Comment |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #3055 +/- ##
=======================================
Coverage 99.55% 99.55%
=======================================
Files 1269 1269
Lines 92987 92987
=======================================
Hits 92574 92574
Misses 413 413 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Stale comment
Opt-in desktop drawer for the left rail, matching the existing mobile off-canvas behaviour. Default stays the docked 15rem rail; the preference is per-device
localStorage(same idea as dark mode), so a wall tablet can hide the column without affecting a wide desktop session. No server, API, orDEVICE_FEATURE_*change.The layout split is careful: body classes
gladys-sidebar-nav/gladys-sidebar-drawerfrom the header constructor (so the first frame already has the 3.25rem gutter), page padding and.fixed-bottominstyle/index.css, and the chat slide-back as the one page that still copies the 15rem trick. Below 992px the chevron and floating opener are CSS-hidden; Cypress is green anddata-cy="sidebar-toggler"/sidebar-navare unchanged. Spec H2 is updated in the same diff.Two residuals, neither a merge blocker: Escape currently toggles rather than closes, and the new controls sit under the ~44px coarse-pointer floor this chrome already uses for the mobile burger — worth tightening because wall tablets are the reason the preference exists.
Not
risk:high. Notneeds:human-review.Sent by Cursor Automation: Automatic PR review
Five review findings on the drawer-mode rail: - the brand name shares its row with the dock button and no longer had the width for it: nowrap let it paint over that button and grow the rail's scroller, so it now ellipsises; - the two drawer-mode controls (the 2rem chevron and the 2.5rem floating opener) missed the ~44px coarse-pointer floor the rest of the rail keeps — and wall tablets, the feature's stated audience, are coarse-pointer at desktop widths. Both join the `pointer: coarse` block; the opener still clears the 3.25rem gutter at that size; - the opener is the only way back into an undocked rail on a keyboard, so it (and the chevron) get a `:focus-visible` ring; - both menu buttons kept the accessible name "Open the menu" while the drawer was open, contradicting their own `aria-expanded`: the label now swaps to a new `header.closeMenu`, added in the three languages; - Escape toggled `showCollapsedMenu`, so another document-level Escape handler closing the drawer in the same tick could see it reopened. It now dismisses the profile dropup first, then calls a dedicated `closeCollapsedMenu`. Co-Authored-By: Claude <noreply@anthropic.com> Autofix-Pass: 1
There was a problem hiding this comment.
Stale comment
Follow-up
fe26302lands the five residuals from the last pass. The brand title now ellipsises in the shared row; both drawer-mode controls grow to 2.75rem underpointer: coarse(gutter still clears at 3.25rem); the opener and chevron get a:focus-visiblering;aria-labelswaps toheader.closeMenuwhile the drawer is open; Escape dismisses the profile dropup first, then a dedicatedcloseCollapsedMenuinstead of toggling.Still an opt-in desktop drawer over the existing mobile off-canvas path. Default stays the docked 15rem rail; preference is per-device
localStorage(same idea as dark mode). No server, API, orDEVICE_FEATURE_*change. Spec H2 is already in the same diff. Front test/build, Cypress, Docker and codecov are green on this head.Not
risk:high. Notneeds:human-review.Sent by Cursor Automation: Automatic PR review
… overlay drawer Field feedback on the first iteration: reusing the mobile drawer on desktop (open = over a backdrop, page dimmed) lost the "rail open while working" state — open was always modal, which is worse than the docked rail. The desktop preference is now a plain collapse: expanded is the docked rail with the content beside it, exactly as before this feature; collapsed slides the rail off-canvas and gives the page the width back, with the floating button expanding it back into the docked rail. Neither state is an overlay — no backdrop, no Escape, no close-on-navigation on desktop; that whole grammar stays mobile-only. A matching padding-left transition on the outer page makes content and rail move as one. Renamed accordingly (sidebar-collapsed preference, toggleSidebarCollapsed, body.gladys-sidebar-collapsed, header.collapseMenu/expandMenu labels). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JnwsS9jopHYHX3GQMViT2c
The review pass landed on the drawer iteration; its five findings are ported onto the collapsed-rail behaviour: brand-name ellipsis next to the collapse button, ~44px coarse-pointer targets and focus-visible rings on the two rail controls, the mobile burger's open/close accessible name, and the Escape refinement (profile dropup first, dedicated close instead of a toggle). The open/close label swap on the desktop button no longer applies: the expand button is only rendered while the rail is collapsed and expands it in place, so its name is static. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JnwsS9jopHYHX3GQMViT2c
There was a problem hiding this comment.
Follow-up 3abf632 replaces the desktop overlay drawer with a real collapse: expanded is the same docked 15rem rail as today (content beside it, no backdrop, stays open across navigation); collapsed slides it off-canvas and gives the page the column back, with the floating button expanding it into that same docked rail. That is the right answer to the field regression — open-while-working was lost when open meant “over a dimmed page”. Overlay grammar (backdrop, Escape, close-on-navigation) stays mobile-only.
The five residuals from the drawer iteration are ported onto this behaviour: brand-name ellipsis next to the chevron; both rail controls at 2.75rem under pointer: coarse (gutter still clears at 3.25rem); :focus-visible rings; the mobile burger’s open/close name; Escape dismisses the profile dropup first, then a dedicated closeCollapsedMenu. The expand button’s name is now static (header.expandMenu) because it only exists while collapsed.
Still front-only, opt-in, default expanded. Preference is per-device localStorage (sidebar-collapsed), same idea as dark mode. Spec H2 is in the same diff. Front test/build, Cypress, Docker and codecov are green on this head. data-cy="sidebar-toggler" / sidebar-nav are unchanged.
One non-blocking residual: collapsing/expanding does not move keyboard focus onto the newly relevant control, so a keyboard user who just hid the rail lands on body until they tab to the floating button. Mouse and touch are unaffected.
Not risk:high. Not needs:human-review.
Sent by Cursor Automation: Automatic PR review


Description
The docked 15rem rail costs every page a column of width, which on a dashboard is width the widgets wanted. This makes the rail collapsible on desktop, as a per-device opt-in.
How it works
localStoragepreference (sidebar-collapsed), like dark mode and unlike anything account-scoped: the same user wants the rail expanded on a wide screen and out of the way on a wall tablet. No server change, no API change.padding-lefttransition on the page so content and rail move as one. The button carries the mobile burger's amber dot when the instance-update notice is waiting in the hidden rail.:focus-visiblerings on both rail controls, the mobile burger's open/close accessible name (it never had one), Escape closing the profile dropup before the mobile drawer via a dedicated close action.Mobile is untouched; the default stays the expanded rail — nothing changes for anyone who does not press the button.
docs/specs/dashboard-flexible-layout-and-widgets.md§ H2 (app navigation) is updated in the same diff, as the spec process requires.Verified in the running app (Chromium, 1440×900 and 390×780):
padding-left: 240px, rail visible, no backdrop;padding-left: 52px, rail off-canvas, no backdrop, preference persisted;Forum
Forum: https://community.gladysassistant.com/t/mettre-la-barre-laterale-gauche-en-mode-tiroir/10740
Checklist
cd server && npm run coverage(Codecov requires 100% coverage on changed lines) and Cypress (npm run cypress:run) if the UI changednpm run eslint,npm run prettier)Notes on the checklist: the change is front-only, so no server test or coverage is involved.
npm run prettier-check,npm run eslint,npm run compare-translationsandnpm run buildall pass infront/. Cypress could not be run here — its binary download is blocked in this environment — but no spec touches the header markup (data-cy="sidebar-toggler"andsidebar-navare preserved), so CI's run is the check that matters.Summary by CodeRabbit