Skip to content

Commit

Permalink
feat: add auto-scroll to canvas elements when selected from panel (#3344
Browse files Browse the repository at this point in the history
)

Co-authored-by: MUI bot <[email protected]>
  • Loading branch information
b4s36t4 and Janpot authored May 2, 2024
1 parent 2dc8875 commit 8a989bd
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 1 deletion.
4 changes: 4 additions & 0 deletions packages/toolpad-studio/src/canvas/ToolpadBridge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export interface ToolpadBridge {
canvasCommands: Commands<{
getViewCoordinates(clientX: number, clientY: number): { x: number; y: number } | null;
getPageViewState(): PageViewState;
scrollComponent(nodeId: string): void;
isReady(): boolean;
invalidateQueries(): void;
}>;
Expand All @@ -73,6 +74,9 @@ const bridge: ToolpadBridge | null = isRenderedInCanvas
getPageViewState: () => {
throw new Error('Not implemented');
},
scrollComponent: () => {
throw new Error('Not Implemented');
},
getViewCoordinates: () => {
throw new Error('Not implemented');
},
Expand Down
10 changes: 9 additions & 1 deletion packages/toolpad-studio/src/canvas/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,6 @@ export default function AppCanvas({ basename, state }: AppCanvasProps) {

setCommandHandler(bridge.canvasCommands, 'getPageViewState', () => {
invariant(appRootRef.current, 'App root not found');

let nodes = viewState.current.nodes;

for (const [nodeId, nodeInfo] of Object.entries(nodes)) {
Expand All @@ -154,6 +153,15 @@ export default function AppCanvas({ basename, state }: AppCanvasProps) {
return { nodes };
});

setCommandHandler(bridge.canvasCommands, 'scrollComponent', (nodeId) => {
if (!nodeId) {
return;
}
invariant(appRootRef.current, 'App root not found');
const canvasNode = appRootRef.current.querySelector(`[data-node-id='${nodeId}']`);
canvasNode?.scrollIntoView({ behavior: 'instant', block: 'end', inline: 'end' });
});

setCommandHandler(bridge.canvasCommands, 'getViewCoordinates', (clientX, clientY) => {
if (!appRootRef.current) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
AppHostProvider,
useAppHost,
queryClient,
NodeId,
} from '@toolpad/studio-runtime';
import createCache from '@emotion/cache';
import { CacheProvider } from '@emotion/react';
Expand Down Expand Up @@ -182,6 +183,13 @@ export default function EditorCanvasHost({
queryClient.invalidateQueries();
},
update: () => {},
scrollComponent: (nodeId: NodeId) => {
if (!appRoot) {
return;
}
const node = appRoot.querySelector(`[data-node-id='${nodeId}']`);
node?.scrollIntoView({ behavior: 'instant', block: 'end', inline: 'end' });
},
}),
} satisfies ToolpadBridge;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,17 @@ export default function RenderOverlay({ bridge }: RenderOverlayProps) {
};
}, [handleNodeDragEnd]);

const scrollSelectedNode = React.useCallback(() => {
if (!selectedNode) {
return;
}
bridge?.canvasCommands.scrollComponent(selectedNode.id as string);
}, [bridge?.canvasCommands, selectedNode]);

React.useEffect(() => {
scrollSelectedNode();
}, [scrollSelectedNode]);

const resizePreviewElementRef = React.useRef<HTMLDivElement | null>(null);

const overlayGridRef = React.useRef<OverlayGridHandle>({
Expand Down
3 changes: 3 additions & 0 deletions test/visual/components/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ test('rendering components in the app editor', async ({ page, argosScreenshot })

await clickCenter(page, image);
await argosScreenshot('with-selection');

await page.getByRole('treeitem', { name: 'typography1' }).click();
await argosScreenshot('with-selection-scroll');
});

test('building layouts', async ({ page, argosScreenshot }) => {
Expand Down

0 comments on commit 8a989bd

Please sign in to comment.