mirror of
https://github.com/webstudio-is/webstudio.git
synced 2026-11-08 21:15:18 +09:00
fix: Dialog focus issues (#2908)
## Description closes #2889 ## 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
This commit is contained in:
1 parent
2e5e116b47
commit
e67b13d64d
2 files changed
+38
-1
No files matched your search
@@ -9,6 +9,7 @@ export const SelectControl = ({
|
||||
property,
|
||||
currentStyle,
|
||||
setProperty,
|
||||
deleteProperty,
|
||||
items,
|
||||
}: ControlProps) => {
|
||||
const { items: defaultItems } = styleConfigByName(property);
|
||||
@@ -48,7 +49,7 @@ export const SelectControl = ({
|
||||
onOpenChange={(isOpen) => {
|
||||
// Remove ephemeral changes when closing the menu.
|
||||
if (isOpen === false && styleValue !== undefined) {
|
||||
setValue(styleValue, { isEphemeral: true });
|
||||
deleteProperty(property, { isEphemeral: true });
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -116,7 +116,43 @@ const subscribePreviewMode = () => {
|
||||
const subscribeEphemeralStyle = (params: Params) => {
|
||||
// track custom properties added on previous ephemeral styles change
|
||||
const addedCustomProperties = new Set<string>();
|
||||
|
||||
let timeoutHandle: number | undefined = undefined;
|
||||
|
||||
const resetInert = () => {
|
||||
document.body.removeAttribute("inert");
|
||||
clearTimeout(timeoutHandle);
|
||||
timeoutHandle = 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(timeoutHandle);
|
||||
|
||||
timeoutHandle = window.setTimeout(resetInert, timeout);
|
||||
};
|
||||
|
||||
return $ephemeralStyles.subscribe((ephemeralStyles) => {
|
||||
// Controls (e.g., radix focus scope) may inadvertently shift focus from inputs.
|
||||
// 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.
|
||||
if (ephemeralStyles.length > 0) {
|
||||
setAutoDisposeInert(AUTO_DISPOSE_INERT_TIMEOUT);
|
||||
} else {
|
||||
// Delayed reset same as set with smaller timeout
|
||||
setAutoDisposeInert(DISPOSE_INERT_TIMEOUT);
|
||||
}
|
||||
|
||||
// track custom properties not set on this change
|
||||
const deletedCustomProperties = new Set(addedCustomProperties);
|
||||
|
||||
|
||||
Reference in new issue
Block a user