Skip to content

Commit

Permalink
fix: After modifying style, it takes two clicks to select the next in…
Browse files Browse the repository at this point in the history
…stance (#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
  • Loading branch information
istarkov authored Oct 19, 2024
1 parent 309b6a8 commit 513d786
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 0 deletions.
11 changes: 11 additions & 0 deletions apps/builder/app/builder/builder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,16 @@ export const Builder = ({
}
}, []);

/**
* Prevent Radix from stealing focus during editing in the style sources
* For example, when the user select or create new style source item inside a dialog.
*/
const handleKeyDown = useCallback((event: React.KeyboardEvent) => {
if (event.target instanceof HTMLInputElement) {
canvasApi.setInert();
}
}, []);

/**
* Prevent Radix from stealing focus during editing in the settings panel.
* For example, when the user modifies the text content of an H1 element inside a dialog.
Expand All @@ -359,6 +369,7 @@ export const Builder = ({
style={{ display: "contents" }}
onPointerDown={handlePointerDown}
onInput={handleInput}
onKeyDown={handleKeyDown}
>
<ChromeWrapper
isPreviewMode={isPreviewMode}
Expand Down
19 changes: 19 additions & 0 deletions apps/builder/app/canvas/shared/inert.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
let resetTimeoutHandle: number | undefined = undefined;

const resetAutoDisposeInert = () => {
if (resetTimeoutHandle === undefined) {
return;
}
document.body.removeAttribute("inert");
clearTimeout(resetTimeoutHandle);
resetTimeoutHandle = undefined;
};

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

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

const PREVENT_INERT_TIMEOUT = 100;

const setAutoDisposeInert = (timeout: number) => {
// Some events in the builder can occur after clicking on the canvas (e.g., blur on an input field).
// In such cases, we should prevent 'inert' from being set and allow the selection to complete.
if (Date.now() - lastPointerEventTime < PREVENT_INERT_TIMEOUT) {
return;
}

document.body.setAttribute("inert", "true");

// To prevent a completely non-interactive canvas due to edge cases,
Expand All @@ -31,3 +43,10 @@ const setAutoDisposeInert = (timeout: number) => {
*/
export const setInert = () => setAutoDisposeInert(AUTO_DISPOSE_INERT_TIMEOUT);
export const resetInert = () => setAutoDisposeInert(DISPOSE_INERT_TIMEOUT);

// window.self !== window.top means we are on canvas
if (typeof window !== "undefined" && window.self !== window.top) {
window.addEventListener("pointerdown", () => {
lastPointerEventTime = Date.now();
});
}

0 comments on commit 513d786

Please sign in to comment.