Skip to content

Commit 513d786

Browse files
authored
fix: After modifying style, it takes two clicks to select the next instance (#4314)
## Description Style Source looses focus after adding Token closes #4309 closes #4306 ## Steps for reproduction 1. click button 2. expect xyz ## Code Review - [ ] hi @kof, I need you to do - conceptual review (architecture, feature-correctness) - detailed review (read every line) - test it on preview ## Before requesting a review - [ ] made a self-review - [ ] added inline comments where things may be not obvious (the "why", not "what") ## Before merging - [ ] tested locally and on preview environment (preview dev login: 5de6) - [ ] updated [test cases](https://github.com/webstudio-is/webstudio/blob/main/apps/builder/docs/test-cases.md) document - [ ] added tests - [ ] if any new env variables are added, added them to `.env` file
1 parent 309b6a8 commit 513d786

File tree

2 files changed

+30
-0
lines changed

2 files changed

+30
-0
lines changed

apps/builder/app/builder/builder.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,16 @@ export const Builder = ({
345345
}
346346
}, []);
347347

348+
/**
349+
* Prevent Radix from stealing focus during editing in the style sources
350+
* For example, when the user select or create new style source item inside a dialog.
351+
*/
352+
const handleKeyDown = useCallback((event: React.KeyboardEvent) => {
353+
if (event.target instanceof HTMLInputElement) {
354+
canvasApi.setInert();
355+
}
356+
}, []);
357+
348358
/**
349359
* Prevent Radix from stealing focus during editing in the settings panel.
350360
* For example, when the user modifies the text content of an H1 element inside a dialog.
@@ -359,6 +369,7 @@ export const Builder = ({
359369
style={{ display: "contents" }}
360370
onPointerDown={handlePointerDown}
361371
onInput={handleInput}
372+
onKeyDown={handleKeyDown}
362373
>
363374
<ChromeWrapper
364375
isPreviewMode={isPreviewMode}

apps/builder/app/canvas/shared/inert.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,31 @@
11
let resetTimeoutHandle: number | undefined = undefined;
22

33
const resetAutoDisposeInert = () => {
4+
if (resetTimeoutHandle === undefined) {
5+
return;
6+
}
47
document.body.removeAttribute("inert");
58
clearTimeout(resetTimeoutHandle);
69
resetTimeoutHandle = undefined;
710
};
811

12+
let lastPointerEventTime = Date.now();
913
// 1000 ms is a reasonable time for the preview to reset.
1014
// Anyway should never happen after user has finished preview changes (can happen during preview changes)
1115
const AUTO_DISPOSE_INERT_TIMEOUT = 1000;
1216

1317
// A brief delay to ensure mutation observers within the focus scope are activated by the preview changes.
1418
const DISPOSE_INERT_TIMEOUT = 300;
1519

20+
const PREVENT_INERT_TIMEOUT = 100;
21+
1622
const setAutoDisposeInert = (timeout: number) => {
23+
// Some events in the builder can occur after clicking on the canvas (e.g., blur on an input field).
24+
// In such cases, we should prevent 'inert' from being set and allow the selection to complete.
25+
if (Date.now() - lastPointerEventTime < PREVENT_INERT_TIMEOUT) {
26+
return;
27+
}
28+
1729
document.body.setAttribute("inert", "true");
1830

1931
// To prevent a completely non-interactive canvas due to edge cases,
@@ -31,3 +43,10 @@ const setAutoDisposeInert = (timeout: number) => {
3143
*/
3244
export const setInert = () => setAutoDisposeInert(AUTO_DISPOSE_INERT_TIMEOUT);
3345
export const resetInert = () => setAutoDisposeInert(DISPOSE_INERT_TIMEOUT);
46+
47+
// window.self !== window.top means we are on canvas
48+
if (typeof window !== "undefined" && window.self !== window.top) {
49+
window.addEventListener("pointerdown", () => {
50+
lastPointerEventTime = Date.now();
51+
});
52+
}

0 commit comments

Comments
 (0)