[DevTools] More robust resize handling (#34036)

This commit is contained in:
Sebastian "Sebbie" Silbermann
2025-07-29 17:45:00 +02:00
committed by GitHub
parent 9c9136b441
commit b1cbb482d5
4 changed files with 66 additions and 67 deletions
+1
View File
@@ -608,6 +608,7 @@ module.exports = {
symbol: 'readonly',
SyntheticEvent: 'readonly',
SyntheticMouseEvent: 'readonly',
SyntheticPointerEvent: 'readonly',
Thenable: 'readonly',
TimeoutID: 'readonly',
WheelEventHandler: 'readonly',
@@ -16,7 +16,6 @@
.TreeWrapper {
flex: 0 0 var(--horizontal-resize-percentage);
overflow: auto;
}
.InspectedElementWrapper {
@@ -32,7 +31,14 @@
.ResizeBar {
position: absolute;
left: -2px;
/*
* moving the bar out of its bounding box might cause its hitbox to overlap
* with another scrollbar creating disorienting UX where you both resize and scroll
* at the same time.
* If you adjust this value, double check that starting resize right on this edge
* doesn't also cause scroll
*/
left: 1px;
width: 5px;
height: 100%;
cursor: ew-resize;
@@ -52,7 +58,7 @@
}
.ResizeBar {
top: -2px;
top: 1px;
left: 0;
width: 100%;
height: 5px;
@@ -29,7 +29,6 @@ type Orientation = 'horizontal' | 'vertical';
type ResizeActionType =
| 'ACTION_SET_DID_MOUNT'
| 'ACTION_SET_IS_RESIZING'
| 'ACTION_SET_HORIZONTAL_PERCENTAGE'
| 'ACTION_SET_VERTICAL_PERCENTAGE';
@@ -40,7 +39,6 @@ type ResizeAction = {
type ResizeState = {
horizontalPercentage: number,
isResizing: boolean,
verticalPercentage: number,
};
@@ -81,82 +79,81 @@ function Components(_: {}) {
return () => clearTimeout(timeoutID);
}, [horizontalPercentage, verticalPercentage]);
const {isResizing} = state;
const onResizeStart = (event: SyntheticPointerEvent<HTMLElement>) => {
const element = event.currentTarget;
element.setPointerCapture(event.pointerId);
};
const onResizeStart = () =>
dispatch({type: 'ACTION_SET_IS_RESIZING', payload: true});
const onResizeEnd = (event: SyntheticPointerEvent<HTMLElement>) => {
const element = event.currentTarget;
element.releasePointerCapture(event.pointerId);
};
let onResize;
let onResizeEnd;
if (isResizing) {
onResizeEnd = () =>
dispatch({type: 'ACTION_SET_IS_RESIZING', payload: false});
const onResize = (event: SyntheticPointerEvent<HTMLElement>) => {
const element = event.currentTarget;
const isResizing = element.hasPointerCapture(event.pointerId);
if (!isResizing) {
return;
}
// $FlowFixMe[missing-local-annot]
onResize = event => {
const resizeElement = resizeElementRef.current;
const wrapperElement = wrapperElementRef.current;
const resizeElement = resizeElementRef.current;
const wrapperElement = wrapperElementRef.current;
if (!isResizing || wrapperElement === null || resizeElement === null) {
return;
}
if (wrapperElement === null || resizeElement === null) {
return;
}
event.preventDefault();
event.preventDefault();
const orientation = getOrientation(wrapperElement);
const orientation = getOrientation(wrapperElement);
const {height, width, left, top} = wrapperElement.getBoundingClientRect();
const {height, width, left, top} = wrapperElement.getBoundingClientRect();
const currentMousePosition =
const currentMousePosition =
orientation === 'horizontal' ? event.clientX - left : event.clientY - top;
const boundaryMin = MINIMUM_SIZE;
const boundaryMax =
orientation === 'horizontal'
? width - MINIMUM_SIZE
: height - MINIMUM_SIZE;
const isMousePositionInBounds =
currentMousePosition > boundaryMin && currentMousePosition < boundaryMax;
if (isMousePositionInBounds) {
const resizedElementDimension =
orientation === 'horizontal' ? width : height;
const actionType =
orientation === 'horizontal'
? event.clientX - left
: event.clientY - top;
? 'ACTION_SET_HORIZONTAL_PERCENTAGE'
: 'ACTION_SET_VERTICAL_PERCENTAGE';
const percentage = (currentMousePosition / resizedElementDimension) * 100;
const boundaryMin = MINIMUM_SIZE;
const boundaryMax =
orientation === 'horizontal'
? width - MINIMUM_SIZE
: height - MINIMUM_SIZE;
setResizeCSSVariable(resizeElement, orientation, percentage);
const isMousePositionInBounds =
currentMousePosition > boundaryMin &&
currentMousePosition < boundaryMax;
if (isMousePositionInBounds) {
const resizedElementDimension =
orientation === 'horizontal' ? width : height;
const actionType =
orientation === 'horizontal'
? 'ACTION_SET_HORIZONTAL_PERCENTAGE'
: 'ACTION_SET_VERTICAL_PERCENTAGE';
const percentage =
(currentMousePosition / resizedElementDimension) * 100;
setResizeCSSVariable(resizeElement, orientation, percentage);
dispatch({
type: actionType,
payload: currentMousePosition / resizedElementDimension,
});
}
};
}
dispatch({
type: actionType,
payload: currentMousePosition / resizedElementDimension,
});
}
};
return (
<SettingsModalContextController>
<OwnersListContextController>
<div
ref={wrapperElementRef}
className={styles.Components}
onMouseMove={onResize}
onMouseLeave={onResizeEnd}
onMouseUp={onResizeEnd}>
<div ref={wrapperElementRef} className={styles.Components}>
<Fragment>
<div ref={resizeElementRef} className={styles.TreeWrapper}>
<Tree />
</div>
<div className={styles.ResizeBarWrapper}>
<div onMouseDown={onResizeStart} className={styles.ResizeBar} />
<div
onPointerDown={onResizeStart}
onPointerMove={onResize}
onPointerUp={onResizeEnd}
className={styles.ResizeBar}
/>
</div>
<div className={styles.InspectedElementWrapper}>
<NativeStyleContextController>
@@ -193,18 +190,12 @@ function initResizeState(): ResizeState {
return {
horizontalPercentage,
isResizing: false,
verticalPercentage,
};
}
function resizeReducer(state: ResizeState, action: ResizeAction): ResizeState {
switch (action.type) {
case 'ACTION_SET_IS_RESIZING':
return {
...state,
isResizing: action.payload,
};
case 'ACTION_SET_HORIZONTAL_PERCENTAGE':
return {
...state,
@@ -38,6 +38,7 @@
font-family: var(--font-family-monospace);
font-size: var(--font-size-monospace-normal);
line-height: var(--line-height-data);
user-select: none;
}
.VRule {