Skip to content

Commit ff92bf2

Browse files
Merge pull request #1466 from pablo-mayrgundter/fix-panel-drag
Fix SideDrawer drag
2 parents 1e7922e + 84c305c commit ff92bf2

File tree

6 files changed

+123
-23
lines changed

6 files changed

+123
-23
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "bldrs",
3-
"version": "1.0.1890",
3+
"version": "1.0.1894",
44
"main": "src/index.jsx",
55
"license": "AGPL-3.0",
66
"homepage": "https://github.com/bldrs-ai/Share",

src/Components/Apps/Apps.spec.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,26 @@ import {
33
homepageSetup,
44
returningUserVisitsHomepageWaitForModel,
55
} from '../../tests/e2e/utils'
6+
import {TITLE_NOTES} from '../Notes/component'
67
import {TITLE_APPS} from './component'
78

89

10+
/**
11+
* Assert `value` is not null.
12+
*
13+
* @template T
14+
* @param value
15+
* @param msg
16+
* @return value
17+
*/
18+
function assertNotNull<T>(value: T | null, msg: string): T {
19+
if (!value) {
20+
throw new Error(msg)
21+
}
22+
return value
23+
}
24+
25+
926
const {beforeEach, describe} = test
1027
/**
1128
* Migrated from cypress/e2e/apps/apps.cy.js
@@ -47,5 +64,58 @@ describe('AppsSideDrawer', () => {
4764
expect(parseInt(width)).toBeGreaterThan(MIN_FULLSCREEN_WIDTH)
4865
})
4966
})
67+
68+
test('resizing Notes drawer does not push Apps off-screen', async ({page}) => {
69+
// Open both Notes and Apps.
70+
await page.getByTestId('control-button-notes').click()
71+
await page.getByTestId('control-button-apps').click()
72+
73+
// Sanity: both titles visible.
74+
await expect(page.getByTestId(`PanelTitle-${TITLE_NOTES}`)).toBeVisible()
75+
await expect(page.getByTestId(`PanelTitle-${TITLE_APPS}`)).toBeVisible()
76+
77+
const notesDrawer = page.getByTestId('NotesAndPropertiesDrawer')
78+
const appsDrawer = page.getByTestId('AppsDrawer')
79+
80+
const handle = notesDrawer.getByTestId('resize-handle-x')
81+
const handleBox = assertNotNull(
82+
await handle.boundingBox(),
83+
'Expected Notes resize handle to have a bounding box',
84+
)
85+
const viewerContainer = page.locator('#viewer-container')
86+
const viewerBoxBefore = assertNotNull(
87+
await viewerContainer.boundingBox(),
88+
'Expected viewer container to have a bounding box',
89+
)
90+
91+
// Drag left to widen Notes (this used to push Apps out of view).
92+
await page.mouse.move(
93+
handleBox.x + (handleBox.width / 2),
94+
handleBox.y + (handleBox.height / 2),
95+
)
96+
await page.mouse.down()
97+
const dragDistance = 250
98+
await page.mouse.move(handleBox.x - dragDistance, handleBox.y + (handleBox.height / 2))
99+
await page.mouse.up()
100+
101+
// Apps should remain visible and inside the viewport.
102+
await expect(page.getByTestId(`PanelTitle-${TITLE_APPS}`)).toBeVisible()
103+
104+
const appsBox = assertNotNull(
105+
await appsDrawer.boundingBox(),
106+
'Expected Apps drawer to have a bounding box',
107+
)
108+
const vw = await page.evaluate(() => window.innerWidth)
109+
expect(appsBox.x).toBeGreaterThanOrEqual(0)
110+
expect(appsBox.x + (appsBox.width)).toBeLessThanOrEqual(vw + 1)
111+
112+
// Viewer should not resize when drawers open/resize (drawers overlay the canvas).
113+
const viewerBoxAfter = assertNotNull(
114+
await viewerContainer.boundingBox(),
115+
'Expected viewer container to have a bounding box after resize',
116+
)
117+
expect(Math.abs(viewerBoxAfter.width - viewerBoxBefore.width)).toBeLessThanOrEqual(1)
118+
expect(Math.abs(viewerBoxAfter.width - vw)).toBeLessThanOrEqual(2)
119+
})
50120
})
51121
})

src/Components/SideDrawer/SideDrawer.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@ export default function SideDrawer({
4444
sx={Object.assign({
4545
display: isDrawerVisible ? 'flex' : 'none',
4646
flexDirection: 'row',
47-
flexGrow: 1,
47+
// Desktop drawers must be fixed-width flex items.
48+
// If they grow/shrink, resizing one drawer can push siblings off-screen.
49+
...(isMobile ? {} : {flex: '0 0 auto', flexShrink: 0}),
4850
}, isMobile ? {
4951
width: '100%',
5052
height: drawerHeight,

src/Containers/CadView.jsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ export default function CadView({
5050
const hasGitHubIdentity = useStore((state) => state.hasGithubIdentity)
5151
const customViewSettings = useStore((state) => state.customViewSettings)
5252
const elementTypesMap = useStore((state) => state.elementTypesMap)
53-
const isAppsVisible = useStore((state) => state.isAppsVisible)
54-
const isNotesVisible = useStore((state) => state.isNotesVisible)
5553
const preselectedElementIds = useStore((state) => state.preselectedElementIds)
5654
const searchIndex = useStore((state) => state.searchIndex)
5755
const selectedElements = useStore((state) => state.selectedElements)
@@ -68,7 +66,6 @@ export default function CadView({
6866
const setSelectedElement = useStore((state) => state.setSelectedElement)
6967
const setSelectedElements = useStore((state) => state.setSelectedElements)
7068
const setViewer = useStore((state) => state.setViewer)
71-
const sidebarWidth = useStore((state) => state.sidebarWidth)
7269
const viewer = useStore((state) => state.viewer)
7370

7471
// AppSlice
@@ -703,17 +700,8 @@ export default function CadView({
703700
/* eslint-enable */
704701

705702

706-
// Shrink the scene viewer when drawer is open. This recenters the
707-
// view in the new shrunk canvas, which preserves what the user is
708-
// looking at.
709-
// TODO(pablo): add render testing
710-
useEffect(() => {
711-
const isDrawerOpen = isNotesVisible || isAppsVisible
712-
if (viewer && !isMobile) {
713-
viewer.container.style.width = isDrawerOpen ? `calc(100vw - ${sidebarWidth}px)` : '100vw'
714-
viewer.context.resize()
715-
}
716-
}, [isNotesVisible, isAppsVisible, isMobile, viewer, sidebarWidth])
703+
// NOTE: Do not resize the 3D canvas when drawers open/resize.
704+
// Drawers should overlay the viewer without changing its dimensions.
717705

718706
useEffect(() => {
719707
const setViewportHeight = () => {

src/Containers/RootLandscape.jsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,17 @@ export default function RootLandscape({pathPrefix, branch, selectWithShiftClickE
2828
return (
2929
<Stack
3030
direction='row'
31-
justifyContent='space-between'
32-
alignItems='center'
33-
sx={{width: '100%', height: isMobile ? `${vh}px` : '100vh'}}
31+
justifyContent='flex-start'
32+
alignItems='stretch'
33+
sx={{width: '100%', height: isMobile ? `${vh}px` : '100vh', overflow: 'hidden'}}
3434
data-testid='RootLandscape-RootStack'
3535
>
3636
{!isMobile &&
3737
<Box
3838
sx={{
39-
flexBasis: '0%',
40-
flexGrow: 1,
39+
// Left drawer should take only its own width.
40+
flex: '0 0 auto',
41+
flexShrink: 0,
4142
}}
4243
>
4344
<NavTreeAndVersionsDrawer
@@ -49,7 +50,7 @@ export default function RootLandscape({pathPrefix, branch, selectWithShiftClickE
4950
}
5051
<Stack
5152
justifyContent='space-between'
52-
sx={{width: '100%', height: '100%'}}
53+
sx={{flex: '1 1 auto', minWidth: 0, height: '100%'}}
5354
data-testid='CenterPane'
5455
>
5556
<Box sx={{opacity: 0.5}}>
@@ -71,7 +72,7 @@ export default function RootLandscape({pathPrefix, branch, selectWithShiftClickE
7172
justifyContent='space-between'
7273
// This pushes bottom bar down
7374
flexGrow={1}
74-
sx={{width: '100%'}}
75+
sx={{width: '100%', minWidth: 0}}
7576
data-testid='RootLandscape-CenterPaneTopStack'
7677
>
7778
<ControlsGroup/>
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import React from 'react'
2+
import {render} from '@testing-library/react'
3+
import ShareMock from '../ShareMock'
4+
import RootLandscape from './RootLandscape'
5+
6+
7+
jest.mock('./ControlsGroup', () => ({
8+
__esModule: true,
9+
default: () => <div data-testid='MockControlsGroup'/>,
10+
}))
11+
12+
jest.mock('./OperationsGroup', () => ({
13+
__esModule: true,
14+
default: () => <div data-testid='MockOperationsGroup'/>,
15+
}))
16+
17+
describe('RootLandscape', () => {
18+
it('center pane is flex and root does not overflow', () => {
19+
const {getByTestId} = render(
20+
<ShareMock>
21+
<RootLandscape
22+
pathPrefix=''
23+
branch=''
24+
selectWithShiftClickEvents={jest.fn()}
25+
deselectItems={jest.fn()}
26+
/>
27+
</ShareMock>,
28+
)
29+
30+
const root = getByTestId('RootLandscape-RootStack')
31+
const centerPane = getByTestId('CenterPane')
32+
33+
expect(getComputedStyle(root).overflow).toBe('hidden')
34+
35+
// Center pane should shrink when drawers grow.
36+
expect(getComputedStyle(centerPane).flexGrow).toBe('1')
37+
expect(getComputedStyle(centerPane).minWidth).toMatch(/^0(px)?$/)
38+
})
39+
})

0 commit comments

Comments
 (0)