Files
webstudio/apps/builder/app/canvas/shared/inert.ts
T
Ivan Starkov 3c189aff97 fix: HTML Embed Code editor inside Dialog Content looses focus (#3020)
## Description

closes #2998

Also fixes name edits etc.
The same issue with radix as we had in the past, focus lock on any
mutation inside dialog aquires focus.
And we have no good way to prevent programmatic focus inside iframe.



## 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.example`
and the `builder/env-check.js` if mandatory
2024-03-20 22:42:44 +03:00

34 lines
1.5 KiB
TypeScript

let resetTimeoutHandle: number | undefined = undefined;
const resetAutoDisposeInert = () => {
document.body.removeAttribute("inert");
clearTimeout(resetTimeoutHandle);
resetTimeoutHandle = undefined;
};
// 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 setAutoDisposeInert = (timeout: number) => {
document.body.setAttribute("inert", "true");
// To prevent a completely non-interactive canvas due to edge cases,
// make sure to clean up preview changes if preview styles fail to reset correctly.
clearTimeout(resetTimeoutHandle);
resetTimeoutHandle = window.setTimeout(resetAutoDisposeInert, timeout);
};
/**
* Controls (e.g., radix focus scope) may inadvertently shift focus from inputs.
* Example: When the user modifies styles or content in the settings panel, the use of a mutation observer with Radix causes the focus to shift to the Radix dialog.
* Currently, there's no way to block focus shifts inside iframes (see https:*github.com/w3c/webappsec-permissions-policy/issues/273 for future updates).
* Workaround: use the `inert` attribute on iframe body to prevent focus changes.
*/
export const setInert = () => setAutoDisposeInert(AUTO_DISPOSE_INERT_TIMEOUT);
export const resetInert = () => setAutoDisposeInert(DISPOSE_INERT_TIMEOUT);