Skip to content

Commit 8f33cb1

Browse files
committed
feat(playground): implement resizable panels for improved layout and user experience
1 parent b0d1ebe commit 8f33cb1

File tree

7 files changed

+144
-97
lines changed

7 files changed

+144
-97
lines changed

apps/android-playground/src/App.less

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ body {
4646
}
4747

4848
&.left-panel {
49-
width: 480px;
50-
flex: none;
5149
overflow: hidden;
5250
height: 100%;
5351
display: flex;
@@ -179,4 +177,24 @@ body {
179177
&:hover {
180178
background-color: #1677ff;
181179
}
180+
}
181+
182+
.panel-resize-handle {
183+
width: 2px;
184+
background-color: #f0f0f0;
185+
cursor: col-resize;
186+
transition: background-color 0.2s;
187+
position: relative;
188+
189+
&:hover {
190+
background-color: #1677ff;
191+
}
192+
193+
&:active {
194+
background-color: #1677ff;
195+
}
196+
197+
&[data-resize-handle-active] {
198+
background-color: #1677ff;
199+
}
182200
}

apps/android-playground/src/App.tsx

Lines changed: 38 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ import {
66
useEnvConfig,
77
useServerValid,
88
} from '@midscene/visualizer';
9-
import { Col, ConfigProvider, Layout, Row, message } from 'antd';
9+
import { ConfigProvider, Layout, message } from 'antd';
1010
import { useCallback, useEffect, useRef, useState } from 'react';
11+
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
1112
import { type Socket, io } from 'socket.io-client';
1213
import AdbDevice from './components/adb-device';
1314
import PlaygroundPanel from './components/playground-panel';
@@ -121,37 +122,42 @@ export default function App() {
121122
{contextHolder}
122123
<Layout className="app-container playground-container vertical-mode">
123124
<Content className="app-content">
124-
<div className="app-grid-layout">
125-
<Row className="app-grid-layout">
126-
{/* left panel: PlaygroundPanel with Universal Playground */}
127-
<Col className="app-panel left-panel">
128-
<div className="panel-content left-panel-content">
129-
<PlaygroundPanel
130-
selectedDeviceId={selectedDeviceId}
131-
serverValid={serverValid}
132-
configAlreadySet={configAlreadySet}
133-
connectionReady={connectionReady}
134-
/>
135-
</div>
136-
</Col>
137-
138-
{/* right panel: ScrcpyPlayer */}
139-
<Col className="app-panel right-panel">
140-
<div className="panel-content right-panel-content">
141-
<AdbDevice
142-
selectedDeviceId={selectedDeviceId}
143-
scrcpyPlayerRef={scrcpyPlayerRef}
144-
/>
145-
<ScrcpyPlayer
146-
ref={scrcpyPlayerRef}
147-
serverUrl={serverUrl}
148-
autoConnect={connectToDevice}
149-
onConnectionStatusChange={handleConnectionStatusChange}
150-
/>
151-
</div>
152-
</Col>
153-
</Row>
154-
</div>
125+
<PanelGroup autoSaveId="android-playground-layout" direction="horizontal">
126+
{/* left panel: PlaygroundPanel with Universal Playground */}
127+
<Panel
128+
defaultSize={32}
129+
maxSize={60}
130+
minSize={20}
131+
className="app-panel left-panel"
132+
>
133+
<div className="panel-content left-panel-content">
134+
<PlaygroundPanel
135+
selectedDeviceId={selectedDeviceId}
136+
serverValid={serverValid}
137+
configAlreadySet={configAlreadySet}
138+
connectionReady={connectionReady}
139+
/>
140+
</div>
141+
</Panel>
142+
143+
<PanelResizeHandle className="panel-resize-handle" />
144+
145+
{/* right panel: ScrcpyPlayer */}
146+
<Panel className="app-panel right-panel">
147+
<div className="panel-content right-panel-content">
148+
<AdbDevice
149+
selectedDeviceId={selectedDeviceId}
150+
scrcpyPlayerRef={scrcpyPlayerRef}
151+
/>
152+
<ScrcpyPlayer
153+
ref={scrcpyPlayerRef}
154+
serverUrl={serverUrl}
155+
autoConnect={connectToDevice}
156+
onConnectionStatusChange={handleConnectionStatusChange}
157+
/>
158+
</div>
159+
</Panel>
160+
</PanelGroup>
155161
</Content>
156162
</Layout>
157163
</ConfigProvider>

apps/playground/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
"@midscene/visualizer": "workspace:*",
1717
"antd": "^5.21.6",
1818
"react": "18.3.1",
19-
"react-dom": "18.3.1"
19+
"react-dom": "18.3.1",
20+
"react-resizable-panels": "2.0.22"
2021
},
2122
"devDependencies": {
2223
"@rsbuild/core": "^1.3.22",

apps/playground/src/App.less

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,6 @@ body {
4646
}
4747

4848
&.left-panel {
49-
width: 480px;
50-
flex: none;
5149
overflow: hidden;
5250
height: 100%;
5351
display: flex;
@@ -305,6 +303,27 @@ body {
305303
}
306304
}
307305

306+
// PanelResizeHandle styles
307+
.panel-resize-handle {
308+
width: 2px;
309+
background-color: #f0f0f0;
310+
cursor: col-resize;
311+
transition: background-color 0.2s;
312+
position: relative;
313+
314+
&:hover {
315+
background-color: #1677ff;
316+
}
317+
318+
&:active {
319+
background-color: #1677ff;
320+
}
321+
322+
&[data-resize-handle-active] {
323+
background-color: #1677ff;
324+
}
325+
}
326+
308327
// Global styles for better integration
309328
.playground-container {
310329
.playground-container {
@@ -318,17 +337,7 @@ body {
318337
}
319338

320339
// Responsive design
321-
@media (max-width: 1200px) {
322-
.app-panel.left-panel {
323-
width: 420px;
324-
}
325-
}
326-
327340
@media (max-width: 768px) {
328-
.app-grid-layout .ant-row {
329-
flex-direction: column;
330-
}
331-
332341
.app-panel {
333342
&.left-panel {
334343
width: 100%;
@@ -345,6 +354,10 @@ body {
345354
}
346355
}
347356

357+
.panel-resize-handle {
358+
display: none;
359+
}
360+
348361
.server-offline-container {
349362
.server-offline-message {
350363
margin: 16px;

apps/playground/src/App.tsx

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import {
44
UniversalPlayground,
55
globalThemeConfig,
66
} from '@midscene/visualizer';
7-
import { Col, ConfigProvider, Layout, Row } from 'antd';
7+
import { ConfigProvider, Layout } from 'antd';
8+
import { Panel, PanelGroup, PanelResizeHandle } from 'react-resizable-panels';
89
import { useEffect, useMemo, useState } from 'react';
910
import ScreenshotViewer from './components/screenshot-viewer';
1011

@@ -84,53 +85,58 @@ export default function App() {
8485
<ConfigProvider theme={globalThemeConfig()}>
8586
<Layout className="app-container playground-container">
8687
<Content className="app-content">
87-
<div className="app-grid-layout">
88-
<Row className="app-grid-layout">
89-
{/* Left panel: UniversalPlayground */}
90-
<Col className="app-panel left-panel">
91-
<div className="panel-content left-panel-content">
92-
{/* Header with Logo and Config */}
93-
<div className="playground-panel-header">
94-
<div className="header-row">
95-
<Logo />
96-
{/* <EnvConfig /> */}
97-
</div>
98-
</div>
99-
100-
{/* Main playground area */}
101-
<div className="playground-panel-playground">
102-
<UniversalPlayground
103-
playgroundSDK={playgroundSDK}
104-
config={{
105-
showContextPreview: false,
106-
layout: 'vertical',
107-
showVersionInfo: true,
108-
enableScrollToBottom: true,
109-
serverMode: true,
110-
showEnvConfigReminder: false,
111-
}}
112-
branding={{
113-
title: 'Playground',
114-
version: __APP_VERSION__,
115-
}}
116-
className="playground-container"
117-
/>
88+
<PanelGroup autoSaveId="playground-layout" direction="horizontal">
89+
{/* Left panel: UniversalPlayground */}
90+
<Panel
91+
defaultSize={32}
92+
maxSize={60}
93+
minSize={20}
94+
className="app-panel left-panel"
95+
>
96+
<div className="panel-content left-panel-content">
97+
{/* Header with Logo and Config */}
98+
<div className="playground-panel-header">
99+
<div className="header-row">
100+
<Logo />
101+
{/* <EnvConfig /> */}
118102
</div>
119103
</div>
120-
</Col>
121104

122-
{/* Right panel: Screenshot Viewer */}
123-
<Col className="app-panel right-panel">
124-
<div className="panel-content right-panel-content">
125-
<ScreenshotViewer
105+
{/* Main playground area */}
106+
<div className="playground-panel-playground">
107+
<UniversalPlayground
126108
playgroundSDK={playgroundSDK}
127-
serverOnline={serverOnline}
128-
isUserOperating={isUserOperating}
109+
config={{
110+
showContextPreview: false,
111+
layout: 'vertical',
112+
showVersionInfo: true,
113+
enableScrollToBottom: true,
114+
serverMode: true,
115+
showEnvConfigReminder: false,
116+
}}
117+
branding={{
118+
title: 'Playground',
119+
version: __APP_VERSION__,
120+
}}
121+
className="playground-container"
129122
/>
130123
</div>
131-
</Col>
132-
</Row>
133-
</div>
124+
</div>
125+
</Panel>
126+
127+
<PanelResizeHandle className="panel-resize-handle" />
128+
129+
{/* Right panel: Screenshot Viewer */}
130+
<Panel className="app-panel right-panel">
131+
<div className="panel-content right-panel-content">
132+
<ScreenshotViewer
133+
playgroundSDK={playgroundSDK}
134+
serverOnline={serverOnline}
135+
isUserOperating={isUserOperating}
136+
/>
137+
</div>
138+
</Panel>
139+
</PanelGroup>
134140
</Content>
135141
</Layout>
136142
</ConfigProvider>

nx.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
"outputs": ["{projectRoot}/dist"]
2525
},
2626
"build:watch": {
27-
"dependsOn": ["^build", "^build:watch"]
27+
"dependsOn": ["^build"]
2828
},
2929
"test": {
3030
"cache": false

pnpm-lock.yaml

Lines changed: 10 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)