Skip to content

Commit 98299ff

Browse files
committed
Menu UI fixes [publish]
1 parent ce12fed commit 98299ff

File tree

4 files changed

+35
-6
lines changed

4 files changed

+35
-6
lines changed

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## 3.1.1
4+
5+
- Correctly display component using forwardRef
6+
- Fix menu position when div is taller than viewport
7+
- Use dynamic z-index to always be on top of the targeted element (like MUI dialog) (fixes #9)
8+
39
## 3.1.0
410

511
- Experimental support for React 19. `_debugSource` [was removed](https://github.com/facebook/react/pull/28265) in React 19. The PR says that tools should lazily generate component stack strace, but I couldn't find a way to use the React devtools globals to generate one for a given Fiber node. I've aksed some React team members about insights on how to make this works, but for now I decided to patch the jsx dev runtime (when serving it) to reinject into Fiber node the source prop added by JSX transform.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vite-plugin-react-click-to-component",
33
"type": "module",
4-
"version": "3.1.0",
4+
"version": "3.1.1",
55
"license": "MIT",
66
"scripts": {
77
"postinstall": "cd playground && bun i",

playground/src/App.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,6 @@ export const App = () => (
2424
<p className="read-the-docs">
2525
Click on the Vite and React logos to learn more
2626
</p>
27+
<div style={{ height: "1000px" }}>Tall div</div>
2728
</div>
2829
);

src/client.ts

+27-5
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ style.innerHTML = `[data-click-to-component-target] {
99
}
1010
#click-to-component-menu {
1111
position: fixed !important;
12-
z-index: 1000 !important;
12+
z-index: 1000;
1313
margin-top: 8px !important;
1414
margin-bottom: 8px !important;
1515
background: #222 !important;
@@ -62,13 +62,25 @@ window.addEventListener("mousemove", (event) => {
6262
event.target.dataset["clickToComponentTarget"] = "true";
6363
});
6464

65+
const getMaxZIndex = (target: HTMLElement, current: number) => {
66+
const parent = target.parentElement;
67+
if (!parent || parent === document.body) return current;
68+
const zIndex = parseInt(window.getComputedStyle(parent).zIndex);
69+
return getMaxZIndex(
70+
parent,
71+
isNaN(zIndex) ? current : Math.max(zIndex, current),
72+
);
73+
};
74+
6575
window.addEventListener("contextmenu", (event) => {
6676
if (!event.altKey) return;
6777
const target = event.target;
6878
if (!(target instanceof HTMLElement)) return;
6979
event.preventDefault();
7080
const layers = getLayersForElement(target);
7181
if (layers.length === 0) return;
82+
const zIndex = getMaxZIndex(target, 999);
83+
if (zIndex > 999) menuElement.style.zIndex = `${zIndex + 1}`;
7284
const rect = target.getBoundingClientRect();
7385
if (rect.bottom < window.innerHeight / 2) {
7486
menuElement.style.top = `${rect.bottom}px`;
@@ -79,9 +91,14 @@ window.addEventListener("contextmenu", (event) => {
7991
menuElement.style.top = "";
8092
menuElement.style.maxHeight = `${rect.top - 16}px`;
8193
} else {
82-
menuElement.style.bottom = `${window.innerHeight - rect.bottom}px`;
94+
const bottomVisible = rect.bottom < window.innerHeight;
95+
menuElement.style.bottom = `${
96+
bottomVisible ? window.innerHeight - rect.bottom : 0
97+
}px`;
8398
menuElement.style.top = "";
84-
menuElement.style.maxHeight = `${rect.bottom - 16}px`;
99+
menuElement.style.maxHeight = `${
100+
(bottomVisible ? rect.bottom : window.innerHeight) - 16
101+
}px`;
85102
}
86103
if (rect.left < window.innerWidth / 2) {
87104
menuElement.style.left = `${rect.left}px`;
@@ -147,7 +164,10 @@ const getLayersForElement = (element: Element) => {
147164
const name =
148165
typeof instance.type === "string"
149166
? instance.type
150-
: instance.type.displayName ?? instance.type.name;
167+
: instance.type.displayName ??
168+
instance.type.name ??
169+
instance.type.render?.name ??
170+
"undefined";
151171
layers.push({ name, path });
152172
}
153173
instance = instance._debugOwner;
@@ -175,7 +195,9 @@ type Fiber = {
175195
_debugSource?: Source;
176196
_debugInfo?: Source; // Injected by React jsxDev patch for React 19
177197
_debugOwner?: Fiber;
178-
type: string | { displayName?: string; name: string };
198+
type:
199+
| string
200+
| { displayName?: string; name?: string; render?: () => unknown };
179201
};
180202

181203
const getReactInstanceForElement = (element: Element): Fiber | undefined => {

0 commit comments

Comments
 (0)