Skip to content

Commit 9a15aa7

Browse files
committed
Highlight connections between <a> / <form> and the corresponding Turbo Frame
1 parent c3a31ee commit 9a15aa7

5 files changed

Lines changed: 3759 additions & 3 deletions

File tree

public/styles/panel/main.css

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@
5858

5959
--wa-border-width-scale: 1;
6060
--wa-space-scale: 0.625;
61+
62+
--pane-footer-height: 2rem;
6163
}
6264

6365
body {
@@ -200,6 +202,10 @@ button.action-icon:active svg {
200202
height: 100%;
201203
}
202204

205+
wa-tab-panel .pane-container {
206+
max-height: calc(100% - var(--pane-footer-height));
207+
}
208+
203209
.pane-header {
204210
border-bottom: 3px solid var(--wa-color-surface-border);
205211
margin-bottom: 0.5em;
@@ -216,7 +222,7 @@ button.action-icon:active svg {
216222
}
217223

218224
.pane-footer {
219-
height: 2rem;
225+
height: var(--pane-footer-height);
220226
position: relative;
221227
background-color: var(--wa-color-surface-raised);
222228
}
@@ -439,3 +445,7 @@ wa-input[size="extra-small"] {
439445
height: 100%;
440446
padding: 0;
441447
}
448+
449+
.pane-container wa-tab::part(base) {
450+
padding: 0.2rem 1.5em;
451+
}

src/browser_panel/page/backend.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import TurboCableObserver from "./turbo_cable_observer.js"
66
import StimulusObserver from "./stimulus_observer.js"
77
import TurboAttributeElementsObserver from "./turbo_attribute_elements_observer.js"
88
import ElementObserver from "./element_observer.js"
9+
import LeaderLine from "$lib/leader_line.js"
910

1011
// This is the backend script which interacts with the page's DOM.
1112
// It observes changes and relays information to the DevTools panel.
@@ -309,6 +310,24 @@ function init() {
309310
}
310311
}
311312

313+
showTurboFrameConnections(turboFrameId, triggerSelector) {
314+
this.removeTurboFrameConnections()
315+
if (!turboFrameId || !triggerSelector) {
316+
return
317+
}
318+
319+
document.querySelectorAll(triggerSelector).forEach((trigger) => {
320+
const turboFrame = document.getElementById(trigger.dataset.turboFrame)
321+
if (turboFrame) {
322+
new LeaderLine(trigger, turboFrame)
323+
}
324+
})
325+
}
326+
327+
removeTurboFrameConnections() {
328+
document.querySelectorAll(".leader-line").forEach((line) => line.remove())
329+
}
330+
312331
getElementsByPayload(payload) {
313332
if (payload.elementPath) {
314333
return [getElementFromIndexPath(payload.elementPath)]
@@ -401,6 +420,18 @@ function init() {
401420
}
402421
})
403422
}
423+
break
424+
}
425+
case PANEL_TO_BACKEND_MESSAGES.SHOW_TURBO_FRAME_CONNECTIONS: {
426+
const turboFrameId = e.data.payload.turboFrameId
427+
const triggerSelector = e.data.payload.triggerSelector
428+
429+
devtoolsBackend.showTurboFrameConnections(turboFrameId, triggerSelector)
430+
break
431+
}
432+
case PANEL_TO_BACKEND_MESSAGES.HIDE_TURBO_FRAME_CONNECTIONS: {
433+
devtoolsBackend.removeTurboFrameConnections()
434+
break
404435
}
405436
}
406437
}

src/browser_panel/panel/tabs/TurboTab.svelte

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,42 @@
184184
})
185185
}
186186
187+
const showTurboFrameConnections = (triggerElement) => {
188+
if (selected.type !== SELECTABLE_TYPES.TURBO_FRAME || !selected.uuid) return
189+
190+
const triggerSelector = triggerElement ? selectorByUUID(triggerElement.uuid) : null
191+
192+
addHighlightOverlay(`${triggerSelector}, ${selectorByUUID(selected.uuid)}`)
193+
panelPostMessage({
194+
action: PANEL_TO_BACKEND_MESSAGES.SHOW_TURBO_FRAME_CONNECTIONS,
195+
source: HOTWIRE_DEV_TOOLS_PANEL_SOURCE,
196+
turboFrameId: selected.frame.id,
197+
triggerSelector: triggerSelector,
198+
})
199+
}
200+
201+
const showAllTurboFrameConnections = () => {
202+
if (selected.type !== SELECTABLE_TYPES.TURBO_FRAME || !selected.uuid) return
203+
const triggerElements = selected.frame.referenceElements
204+
const selectors = triggerElements.map((el) => selectorByUUID(el.uuid))
205+
selectors.push(selectorByUUID(selected.uuid))
206+
addHighlightOverlay(selectors.join(", "))
207+
panelPostMessage({
208+
action: PANEL_TO_BACKEND_MESSAGES.SHOW_TURBO_FRAME_CONNECTIONS,
209+
source: HOTWIRE_DEV_TOOLS_PANEL_SOURCE,
210+
turboFrameId: selected.frame.id,
211+
triggerSelector: `[data-turbo-frame='${selected.frame.id}']`,
212+
})
213+
}
214+
215+
const hideTurboFrameConnections = () => {
216+
panelPostMessage({
217+
action: PANEL_TO_BACKEND_MESSAGES.HIDE_TURBO_FRAME_CONNECTIONS,
218+
source: HOTWIRE_DEV_TOOLS_PANEL_SOURCE,
219+
})
220+
hideHighlightOverlay()
221+
}
222+
187223
const handleFrameListKeyboardNavigation = (event) => {
188224
if (!turboFrames.length) return
189225
event.preventDefault() // Prevents automatic browser scrolling
@@ -475,11 +511,11 @@
475511
{#if selected.type === SELECTABLE_TYPES.TURBO_FRAME && selected.uuid}
476512
<div class="pane-scrollable-list">
477513
{#if selected.frame.referenceElements.length > 0}
478-
<div class="pane-section-heading">
514+
<div class="pane-section-heading" onmouseenter={showAllTurboFrameConnections} onmouseleave={hideTurboFrameConnections} role="button" tabindex="0">
479515
<span>Targeted by</span>
480516
</div>
481517
{#each selected.frame.referenceElements as referenceElement}
482-
<div class="entry-row p-2 border-bottom" onmouseenter={() => addHighlightOverlay(selectorByUUID(referenceElement.uuid))} onmouseleave={() => hideHighlightOverlay()} role="button" tabindex="0">
518+
<div class="entry-row p-2 border-bottom" onmouseenter={() => showTurboFrameConnections(referenceElement)} onmouseleave={hideTurboFrameConnections} role="button" tabindex="0">
483519
<div class="d-flex justify-content-between align-items-center">
484520
<StripedHtmlTag element={referenceElement} />
485521
<InspectButton class="btn-hoverable" uuid={referenceElement.uuid}></InspectButton>

src/lib/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ export const PANEL_TO_BACKEND_MESSAGES = {
3333
REFRESH_ALL_STATE: "refresh-all-state",
3434
SCROLL_AND_HIGHLIGHT: "scroll-and-highlight",
3535
UPDATE_DATA_ATTRIBUTE: "update-data-attribute",
36+
SHOW_TURBO_FRAME_CONNECTIONS: "show-turbo-frame-connections",
37+
HIDE_TURBO_FRAME_CONNECTIONS: "hide-turbo-frame-connections",
3638
}
3739

3840
export const TURBO_EVENTS = [

0 commit comments

Comments
 (0)