Skip to content

Commit ed023cf

Browse files
authored
[devtools-shell] layout options for testing (#33516)
## Summary This PR adds a 'Layout' selector to the devtools shell main example, as well as a resizable split pane, allowing more realistic testing of how the devtools behaves when used in a vertical or horizontal layout and at different sizes (e.g. when resizing the Chrome Dev Tools pane). ## How did you test this change? https://github.com/user-attachments/assets/81179413-7b46-47a9-bc52-4f7ec414e8be
1 parent a00ca6f commit ed023cf

File tree

1 file changed

+202
-63
lines changed

1 file changed

+202
-63
lines changed
Lines changed: 202 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,213 @@
11
<!doctype html>
22
<html>
3-
<head>
4-
<meta charset="utf8">
5-
<title>React DevTools</title>
6-
<meta name="viewport" content="width=device-width, initial-scale=1">
7-
<style>
8-
#target {
9-
flex: 1;
10-
border: none;
11-
}
12-
#devtools {
13-
height: 400px;
14-
max-height: 50%;
15-
overflow: hidden;
16-
z-index: 10000001;
17-
}
18-
body {
19-
display: flex;
20-
flex-direction: column;
21-
position: absolute;
22-
top: 0;
23-
left: 0;
24-
right: 0;
25-
bottom: 0;
26-
margin: 0;
27-
padding: 0;
28-
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
29-
sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
30-
font-size: 12px;
31-
line-height: 1.5;
32-
}
33-
.optionsRow {
34-
width: 100%;
35-
display: flex;
36-
padding: 0.25rem;
37-
background: aliceblue;
38-
border-bottom: 1px solid lightblue;
39-
box-sizing: border-box;
40-
}
41-
.optionsRowSpacer {
42-
flex: 1;
43-
}
44-
</style>
45-
</head>
46-
<body>
47-
<div class="optionsRow">
48-
<button id="mountButton">Unmount test app</button>
49-
<div class="optionsRowSpacer">&nbsp;</div>
50-
<span>
51-
<a href="/multi.html">multi DevTools</a>
52-
|
53-
<a href="/e2e.html">e2e tests</a>
54-
|
55-
<a href="/e2e-regression.html">e2e regression tests</a>
56-
|
57-
<a href="/perf-regression.html">perf regression tests</a>
58-
</span>
59-
</div>
603

4+
<head>
5+
<meta charset="utf8">
6+
<title>React DevTools</title>
7+
<meta name="viewport" content="width=device-width, initial-scale=1">
8+
<style>
9+
#panes {
10+
display: grid;
11+
height: 100%;
12+
width: 100%;
13+
position: relative;
14+
}
15+
16+
#divider {
17+
position: absolute;
18+
z-index: 10000002;
19+
background-color: #ccc;
20+
transition: background-color 0.2s;
21+
}
22+
23+
#divider:hover,
24+
#divider.dragging {
25+
background-color: #aaa;
26+
}
27+
28+
#divider.horizontal-divider {
29+
width: 100%;
30+
height: 5px;
31+
cursor: row-resize;
32+
}
33+
34+
#divider.vertical-divider {
35+
width: 5px;
36+
height: 100%;
37+
cursor: col-resize;
38+
}
39+
40+
#target {
41+
height: 100%;
42+
width: 100%;
43+
border: none;
44+
}
45+
46+
#devtools {
47+
height: 100%;
48+
width: 100%;
49+
overflow: hidden;
50+
z-index: 10000001;
51+
}
52+
53+
body {
54+
display: flex;
55+
height: 100vh;
56+
width: 100vw;
57+
contain: strict;
58+
flex-direction: column;
59+
margin: 0;
60+
padding: 0;
61+
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial,
62+
sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol;
63+
font-size: 12px;
64+
line-height: 1.5;
65+
}
66+
67+
.optionsRow {
68+
width: 100%;
69+
display: flex;
70+
padding: 0.25rem;
71+
background: aliceblue;
72+
border-bottom: 1px solid lightblue;
73+
box-sizing: border-box;
74+
}
75+
76+
.optionsRowSpacer {
77+
flex: 1;
78+
}
79+
</style>
80+
</head>
81+
82+
<body>
83+
<div class="optionsRow">
84+
<button id="mountButton">Unmount test app</button>
85+
<div class="optionsRowSpacer">&nbsp;</div>
86+
<span>
87+
<a href="/multi.html">multi DevTools</a>
88+
|
89+
<a href="/e2e.html">e2e tests</a>
90+
|
91+
<a href="/e2e-regression.html">e2e regression tests</a>
92+
|
93+
<a href="/perf-regression.html">perf regression tests</a>
94+
</span>
95+
96+
<label style="margin-left: 4px">
97+
Layout:
98+
<select id="layout">
99+
<option value="leftright">Left/Right Split</option>
100+
<option value="topbottom">Top/Bottom Split</option>
101+
</select></label>
102+
</div>
103+
104+
<div id="panes">
61105
<!-- React test app (shells/dev/app) is injected here -->
62106
<!-- DevTools backend (shells/dev/src) is injected here -->
63107
<!-- global "hook" is defined on the iframe's contentWindow -->
64108
<iframe id="target"></iframe>
65109

110+
<!-- Draggable divider between panes -->
111+
<div id="divider"></div>
112+
66113
<!-- DevTools frontend UI (shells/dev/src) renders here -->
67114
<div id="devtools"></div>
115+
</div>
116+
117+
<!-- This script installs the hook, injects the backend, and renders the DevTools UI -->
118+
<!-- In DEV mode, this file is served by the Webpack dev server -->
119+
<!-- For production builds, it's built by Webpack and uploaded from the local file system -->
120+
<script src="dist/app-devtools.js"></script>
121+
<script type="module">
122+
let layoutType = 'leftright';
123+
let splitRatio = 0.5;
124+
let isDragging = false;
125+
126+
// handle layout changes
127+
const layout = document.getElementById('layout');
128+
function setLayout(layoutType, splitRatio) {
129+
const panes = document.getElementById('panes');
130+
if (layoutType === 'topbottom') {
131+
panes.style.gridTemplateColumns = '100%'; // Full width for each row
132+
panes.style.gridTemplateRows = `${splitRatio * 100}% ${(1 - splitRatio) * 100}%`;
133+
} else if (layoutType === 'leftright') {
134+
panes.style.gridTemplateRows = '100%'; // Full height for each column
135+
panes.style.gridTemplateColumns = `${splitRatio * 100}% ${(1 - splitRatio) * 100}%`;
136+
}
137+
}
138+
layout.addEventListener('change', () => {
139+
layoutType = layout.value;
140+
setLayout(layoutType, splitRatio);
141+
updateDividerPosition(); // Ensure divider updates when layout changes
142+
});
143+
144+
// handle changing the split ratio
145+
const divider = document.getElementById('divider');
146+
function updateDividerPosition() {
147+
if (layoutType === 'topbottom') {
148+
// For top/bottom layout, divider should be horizontal (spanning across)
149+
divider.className = 'horizontal-divider';
150+
divider.style.top = `calc(${splitRatio * 100}% - 2.5px)`;
151+
divider.style.left = '0';
152+
} else {
153+
// For left/right layout, divider should be vertical (spanning down)
154+
divider.className = 'vertical-divider';
155+
divider.style.left = `calc(${splitRatio * 100}% - 2.5px)`;
156+
divider.style.top = '0';
157+
}
158+
}
159+
160+
// Add event listeners for dragging
161+
divider.addEventListener('mousedown', (e) => {
162+
isDragging = true;
163+
divider.classList.add('dragging');
164+
165+
// Disable pointer events on the iframe to prevent it from capturing mouse events
166+
const iframe = document.getElementById('target');
167+
iframe.style.pointerEvents = 'none';
168+
169+
e.preventDefault(); // Prevent text selection during drag
170+
});
171+
172+
document.addEventListener('mousemove', (e) => {
173+
if (!isDragging) return;
174+
175+
const panes = document.getElementById('panes');
176+
const rect = panes.getBoundingClientRect();
177+
178+
if (layoutType === 'topbottom') {
179+
// Calculate new split ratio based on vertical position
180+
const newRatio = Math.max(0.1, Math.min(0.9, (e.clientY - rect.top) / rect.height));
181+
splitRatio = newRatio;
182+
} else {
183+
// Calculate new split ratio based on horizontal position
184+
const newRatio = Math.max(0.1, Math.min(0.9, (e.clientX - rect.left) / rect.width));
185+
splitRatio = newRatio;
186+
}
187+
188+
// Update layout and divider position
189+
setLayout(layoutType, splitRatio);
190+
updateDividerPosition();
191+
});
192+
193+
document.addEventListener('mouseup', () => {
194+
if (isDragging) {
195+
isDragging = false;
196+
divider.classList.remove('dragging');
197+
198+
// Re-enable pointer events on the iframe
199+
const iframe = document.getElementById('target');
200+
iframe.style.pointerEvents = 'auto';
201+
}
202+
});
203+
204+
// Initialize
205+
setLayout(
206+
layoutType,
207+
splitRatio,
208+
);
209+
updateDividerPosition();
210+
</script>
211+
</body>
68212

69-
<!-- This script installs the hook, injects the backend, and renders the DevTools UI -->
70-
<!-- In DEV mode, this file is served by the Webpack dev server -->
71-
<!-- For production builds, it's built by Webpack and uploaded from the local file system -->
72-
<script src="dist/app-devtools.js"></script>
73-
</body>
74-
</html>
213+
</html>

0 commit comments

Comments
 (0)