ECHOES-1308 Remove the thin collapsed sidebar and implement the new undocked interaction model#716
Conversation
✅ Deploy Preview for echoes-react ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
2819d96 to
5aa93fe
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the Layout sidebar to remove the “thin collapsed” mode and introduce a new undocked interaction model where the sidebar is fully hidden when undocked and only revealed via the top-left trigger (hover/focus/click) or focusing into the sidebar interaction boundary.
Changes:
- Introduces a sidebar “interaction boundary” + safe-area logic to keep the undocked sidebar open while focus/pointer remains in the intended region, and closes it when leaving.
- Refactors SidebarNavigation rendering/styling to use a true hidden/visible open state (opacity/transform/visibility) instead of hover/focus-within collapse behavior.
- Updates Storybook stories, i18n keys, and several tests to match the new docking/undocking and open/close behaviors.
Reviewed changes
Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| stories/layout/sidebar-navigation/SidebarNavigationAccordionItem-stories.tsx | Removes stories/examples tied to the old “collapsed/docked icon hiding” behavior. |
| stories/layout/sidebar-navigation/SidebarNavigation-stories.tsx | Splits the sidebar story into Docked / Undocked Hidden / Undocked Open variants and adds open-on-mount behavior. |
| stories/layout/Layout-stories.tsx | Makes sidebar accordion item examples compatible with the new undocked model; stabilizes ColorBox rendering deterministically. |
| src/components/layout/sidebar-navigation/SidebarNavigationHeader.tsx | Removes collapsed-mode-only padding adjustments. |
| src/components/layout/sidebar-navigation/SidebarNavigationGroup.tsx | Removes collapsed-mode-only label hiding/divider behavior. |
| src/components/layout/sidebar-navigation/SidebarNavigationFooterPromotionCard.tsx | Removes collapsed-mode-only opacity/transition behavior. |
| src/components/layout/sidebar-navigation/SidebarNavigationBody.tsx | Removes collapsed-mode scroll/shadow styling and factors spacing tokens into constants. |
| src/components/layout/sidebar-navigation/SidebarNavigationBaseItem.tsx | Removes accordion “visibility/outline” CSS variable usage and updates icon-hide logic to depend on data-sidebar-open. |
| src/components/layout/sidebar-navigation/SidebarNavigationAccordionItem.tsx | Simplifies accordion child CSS variables to only control display (open/closed). |
| src/components/layout/sidebar-navigation/SidebarNavigation.tsx | Implements the new hidden/visible undocked sidebar presentation and wires interaction boundary event handlers + safe area ref. |
| src/components/layout/sidebar-navigation/tests/SidebarNavigationItem-test.tsx | Updates CSS-variable expectations to match the new accordion integration contract. |
| src/components/layout/sidebar-navigation/tests/SidebarNavigationAccordionChildItem-test.tsx | Updates CSS-variable expectations to match the new accordion integration contract. |
| src/components/layout/sidebar-navigation/tests/SidebarNavigation-test.tsx | Updates tests to provide the expanded LayoutContext shape required by the new interaction model. |
| src/components/layout/LayoutSidebarInteraction.ts | Adds helpers for detecting interaction boundary targets and pointer-safe-area checks. |
| src/components/layout/LayoutContext.ts | Extends LayoutContext with sidebar open/close + boundary interaction handlers and state. |
| src/components/layout/Layout.tsx | Implements the new undocked open state and document-level closing behavior; exposes data-sidebar-open. |
| src/components/layout/global-navigation/GlobalNavigationPrimary.tsx | Updates the trigger button behavior/ARIA to support undocked reveal and non-dockable “open sidebar” behavior. |
| src/components/layout/global-navigation/tests/GlobalNavigationPrimary-test.tsx | Updates tests for the new trigger rendering and “Open sidebar” behavior. |
| src/components/layout/tests/Layout-test.tsx | Adds tests for the new undocked interaction model (hover/focus/click open/close, safe-area behavior). |
| i18n/keys.json | Adds the global_navigation.sidebar.open key for the non-dockable trigger label. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
5aa93fe to
6b665b3
Compare
Code Review ✅ Approved 2 resolved / 2 findingsRefactors the sidebar to an undocked interaction model and removes the thin collapsed state. Resolved previous findings regarding null guards and test helper usage. ✅ 2 resolved✅ Quality: Raw truthiness/null guards instead of isDefined() helper
✅ Quality: Test files call render() directly in it() without shared helper
OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
6b665b3 to
6649c3f
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 21 out of 21 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/components/layout/sidebar-navigation/SidebarNavigation.tsx:62
setHasSidebar(true)is triggered from a React effect, so the first paint renders withhasSidebar=false(hiding the sidebar + trigger button even when the sidebar should start docked). UsinguseLayoutEffecthere would avoid that visible flicker/blank sidebar column on mount.
useEffect(() => {
setHasSidebar(true);
return () => {
setHasSidebar(false);
};
}, [setHasSidebar]);
6649c3f to
5d996bd
Compare
990c146 to
3ff1814
Compare
2df9928 to
d7cb27b
Compare
d7cb27b to
2c58f2b
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 28 out of 28 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
src/components/layout/sidebar-navigation/SidebarNavigation.tsx:68
- Setting
hasSidebarviauseEffectcan cause a brief mount-time state mismatch where the layout reserves space for a docked sidebar but the sidebar stays hidden until the effect runs (becauseisSidebarOpenis gated byhasSidebar). UseuseLayoutEffecthere so the sidebar presence is registered before the browser paints.
useEffect(() => {
setHasSidebar(true);
return () => {
setHasSidebar(false);
};
}, [setHasSidebar]);
2c58f2b to
bb60c2f
Compare
4f2f772 to
d45a6c0
Compare
bb60c2f to
169fd3b
Compare
ac9339c to
a0d6349
Compare
a0d6349 to
9296e73
Compare
Code Review ✅ Approved 10 resolved / 10 findingsReplaces the collapsed sidebar with an undocked interaction model and consolidates state logic via useLayoutSidebarState. All previous findings regarding prop forwarding, helper usage, and testing patterns have been resolved. ✅ 10 resolved✅ Quality: Raw truthiness/null guards instead of isDefined() helper
✅ Quality: Test files call render() directly in it() without shared helper
✅ Quality: SidebarNavigation does not forward rest props to root
✅ Quality: Use isDefined() instead of raw !== undefined guards
✅ Edge Case: Overflow handoff surface has zero width and can't be hovered
...and 5 more resolved from earlier reviews OptionsAuto-apply is off → Gitar will not commit updates to this branch. Comment with these commands to change the behavior for this request:
Was this helpful? React with 👍 / 👎 | Gitar |
|



Summary by Gitar
SIDEBAR_INTERACTION_ZONE_ATTRIBUTEand pointer-handoff surfaces inGlobalNavigationPrimaryandSidebarNavigationto support transient sidebar states without flickering.useLayoutSidebarStateto centralize sidebar logic, including media query handling, interaction-zone blur/hover events, and open/docked state synchronization.refandclassNameprops toLayout,GlobalNavigationPrimary,SidebarNavigation,SidebarNavigationGroup, andSidebarNavigationFooterPromotionCardfor improved consumer control.SidebarNavigationstories to demonstrateDocked,UndockedHidden, andUndockedOpenstates using a unifiedSidebarNavigationStoryLayout.This will update automatically on new commits.