diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/OverlayGrid.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/OverlayGrid.tsx index bb1be6234e3..a96cc0719bb 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/OverlayGrid.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/OverlayGrid.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { Grid, styled } from '@mui/material'; +import invariant from 'invariant'; export interface OverlayGridHandle { gridElement: HTMLDivElement | null; @@ -37,17 +38,18 @@ export const OverlayGrid = React.forwardRef(function OverlayG React.useImperativeHandle( forwardedRef, () => { + const gridElement = gridRef.current; + invariant(gridElement, 'Overlay grid ref not bound'); + let columnEdges: number[] = []; - if (gridRef.current) { - const gridColumnContainers = Array.from(gridRef.current.children); - const gridColumnEdges = gridColumnContainers.map((container: Element) => { - const containerRect = container.firstElementChild?.getBoundingClientRect(); - return containerRect - ? [Math.round(containerRect.x), Math.round(containerRect.x + containerRect.width)] - : []; - }); - columnEdges = gridColumnEdges.flat(); - } + const gridColumnContainers = Array.from(gridElement.children); + const gridColumnEdges = gridColumnContainers.map((container: Element) => { + const containerRect = container.firstElementChild?.getBoundingClientRect(); + return containerRect + ? [Math.round(containerRect.x), Math.round(containerRect.x + containerRect.width)] + : []; + }); + columnEdges = gridColumnEdges.flat(); return { gridElement: gridRef.current, diff --git a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx index 0da48a4598e..972ef881bc3 100644 --- a/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx +++ b/packages/toolpad-app/src/toolpad/AppEditor/PageEditor/RenderPanel/RenderOverlay.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { NodeId } from '@mui/toolpad-core'; import { styled } from '@mui/material'; import clsx from 'clsx'; +import invariant from 'invariant'; import * as appDom from '../../../../appDom'; import { useDom, useDomApi } from '../../../DomLoader'; @@ -164,6 +165,8 @@ export default function RenderOverlay({ canvasHostRef }: RenderOverlayProps) { const selectedNode = selection && appDom.getNode(dom, selection); + const overlayRef = React.useRef(null); + const draggedNode = React.useMemo( (): appDom.ElementNode | null => newNode || (draggedNodeId && appDom.getNode(dom, draggedNodeId, 'element')), @@ -1011,14 +1014,19 @@ export default function RenderOverlay({ canvasHostRef }: RenderOverlayProps) { } } - api.dragEnd(); - if (selection) { deleteOrphanedLayoutComponents(draggedNode, dragOverNodeId); } + api.dragEnd(); + if (newNode) { api.select(newNode.id); + + // Refocus on overlay so that keyboard events can keep being caught by it + const overlayElement = overlayRef.current; + invariant(overlayElement, 'Overlay ref not bound'); + overlayElement.focus(); } }, [ @@ -1309,6 +1317,7 @@ export default function RenderOverlay({ canvasHostRef }: RenderOverlayProps) { return (