feat(studio): auto-reveal source when selecting elements in Code tab

When the Code tab is active and a user clicks an element in the preview,
the code editor now auto-scrolls to the corresponding HTML source. This
removes the need for Alt+click — the existing click-to-source mechanism
fires automatically when the Code tab is already open.

- Add getTab() to LeftSidebarHandle for reading the active tab
- Add getSidebarTab getter to useDomEditSession
- Add effect that calls openSourceForSelection on selection change
  when Code tab is active
This commit is contained in:
Miguel Ángel
2026-05-21 15:25:51 -04:00
parent afa6530a10
commit e2de547a28
4 changed files with 40 additions and 3 deletions
+19 -1
View File
@@ -1,4 +1,4 @@
import { useCallback, useEffect } from "react";
import { useCallback, useEffect, useRef } from "react";
import type { TimelineElement } from "../player";
import { STUDIO_INSPECTOR_PANELS_ENABLED } from "../components/editor/manualEditingAvailability";
import { findElementForSelection, type DomEditSelection } from "../components/editor/domEditing";
@@ -56,6 +56,7 @@ export interface UseDomEditSessionParams {
setRefreshKey: React.Dispatch<React.SetStateAction<number>>;
openSourceForSelection?: (sourceFile: string, target: PatchTarget) => void;
selectSidebarTab?: (tab: SidebarTab) => void;
getSidebarTab?: () => SidebarTab;
}
// ── Hook ──
@@ -93,6 +94,7 @@ export function useDomEditSession({
setRefreshKey: _setRefreshKey,
openSourceForSelection,
selectSidebarTab,
getSidebarTab,
}: UseDomEditSessionParams) {
void _setRefreshKey;
@@ -281,6 +283,22 @@ export function useDomEditSession({
applyStudioManualEditsToPreviewRef,
]);
// Auto-reveal source when an element is selected while the Code tab is active.
// Use a ref for the callback so the effect only fires on selection changes,
// not when openSourceForSelection is recreated due to editingFile content updates.
const openSourceRef = useRef(openSourceForSelection);
openSourceRef.current = openSourceForSelection;
useEffect(() => {
if (!domEditSelection || !openSourceRef.current || !getSidebarTab) return;
if (!domEditSelection.sourceFile) return;
if (getSidebarTab() !== "code") return;
openSourceRef.current(domEditSelection.sourceFile, {
id: domEditSelection.id,
selector: domEditSelection.selector,
selectorIndex: domEditSelection.selectorIndex,
});
}, [domEditSelection, getSidebarTab]);
return {
// State
domEditSelection,