Skip to content

Commit b867e67

Browse files
authored
feat: Experimental INP fix (#4560)
## Description https://vercel.com/blog/demystifying-inp-new-tools-and-actionable-insights ## new https://inp-inp-inp-inp.wstd.work/ ## prev https://no-inp-no-no.wstd.work/ ## 20x slowdown new (click) <img width="323" alt="image" src="https://github.com/user-attachments/assets/08b063f6-93a3-4e2b-8e5d-e9521f97a40d" /> ## 20x slowdown new (keyboard) <img width="305" alt="image" src="https://github.com/user-attachments/assets/3a1bb563-392f-40d9-9067-7cb085adcedd" /> ## 20x slowdown old (click) <img width="308" alt="image" src="https://github.com/user-attachments/assets/41ff36cd-bd27-4e5d-b569-9040ce12b845" /> ## 20x slowdown old (keyboard) <img width="304" alt="image" src="https://github.com/user-attachments/assets/4cc41ef9-f6d1-4e2a-ad41-de601d713bc9" /> ## 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: 0000) - [ ] 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 8cd3dc3 commit b867e67

File tree

6 files changed

+88
-17
lines changed

6 files changed

+88
-17
lines changed

packages/sdk-components-react-radix/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,12 @@
5959
"@radix-ui/react-switch": "^1.1.1",
6060
"@radix-ui/react-tabs": "^1.1.1",
6161
"@radix-ui/react-tooltip": "^1.1.4",
62+
"@radix-ui/react-use-controllable-state": "^1.1.0",
6263
"@webstudio-is/css-engine": "workspace:*",
6364
"@webstudio-is/icons": "workspace:*",
6465
"@webstudio-is/react-sdk": "workspace:*",
65-
"@webstudio-is/sdk": "workspace:*"
66+
"@webstudio-is/sdk": "workspace:*",
67+
"await-interaction-response": "^0.0.2"
6668
},
6769
"devDependencies": {
6870
"@types/node": "^22.9.3",

packages/sdk-components-react-radix/src/dialog.tsx

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import {
77
useEffect,
88
useRef,
99
useContext,
10+
useCallback,
1011
} from "react";
1112
import * as DialogPrimitive from "@radix-ui/react-dialog";
1213
import {
1314
ReactSdkContext,
1415
getClosestInstance,
1516
type Hook,
1617
} from "@webstudio-is/react-sdk/runtime";
18+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
19+
import interactionResponse from "await-interaction-response";
1720

1821
/**
1922
* Naive heuristic to determine if a click event will cause navigate
@@ -49,9 +52,22 @@ export const Dialog = forwardRef<
4952
HTMLDivElement,
5053
Omit<ComponentPropsWithoutRef<typeof DialogPrimitive.Root>, "defaultOpen">
5154
>((props, _ref) => {
52-
const { open, onOpenChange } = props;
5355
const { renderer } = useContext(ReactSdkContext);
5456

57+
const [open, onOpenChange] = useControllableState({
58+
prop: props.open,
59+
defaultProp: false,
60+
onChange: props.onOpenChange,
61+
});
62+
63+
const onOpenChangeHandler = useCallback(
64+
async (open: boolean) => {
65+
await interactionResponse();
66+
onOpenChange(open);
67+
},
68+
[onOpenChange]
69+
);
70+
5571
/**
5672
* Close the dialog when a navigable link within it is clicked.
5773
*/
@@ -76,15 +92,21 @@ export const Dialog = forwardRef<
7692
}
7793

7894
if (target.closest('[role="dialog"]')) {
79-
onOpenChange?.(false);
95+
onOpenChangeHandler?.(false);
8096
}
8197
};
8298

8399
window.addEventListener("click", handleClick);
84100
return () => window.removeEventListener("click", handleClick);
85-
}, [open, onOpenChange, renderer]);
101+
}, [open, onOpenChangeHandler, renderer]);
86102

87-
return <DialogPrimitive.Root {...props} />;
103+
return (
104+
<DialogPrimitive.Root
105+
{...props}
106+
onOpenChange={onOpenChangeHandler}
107+
open={open}
108+
/>
109+
);
88110
});
89111

90112
/**

packages/sdk-components-react-radix/src/tabs.tsx

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,43 @@
1-
import {
2-
type ComponentPropsWithoutRef,
3-
type ForwardRefExoticComponent,
4-
forwardRef,
5-
type ComponentProps,
6-
type RefAttributes,
7-
} from "react";
1+
import { type ComponentPropsWithoutRef, forwardRef, useCallback } from "react";
82
import { Root, List, Trigger, Content } from "@radix-ui/react-tabs";
93
import {
104
getClosestInstance,
115
getIndexWithinAncestorFromComponentProps,
126
type Hook,
137
} from "@webstudio-is/react-sdk/runtime";
8+
import { useControllableState } from "@radix-ui/react-use-controllable-state";
9+
import interactionResponse from "await-interaction-response";
10+
11+
export const Tabs = forwardRef<
12+
HTMLDivElement,
13+
Omit<ComponentPropsWithoutRef<typeof Root>, "value" | "onValueChange"> & {
14+
value?: string;
15+
onValueChange?: (value: string) => void;
16+
}
17+
>(({ defaultValue, ...props }, ref) => {
18+
const [value, onValueChange] = useControllableState({
19+
prop: props.value,
20+
defaultProp: defaultValue,
21+
onChange: props.onValueChange,
22+
});
1423

15-
export const Tabs: ForwardRefExoticComponent<
16-
Omit<ComponentProps<typeof Root>, "asChild"> & RefAttributes<HTMLDivElement>
17-
> = Root;
24+
const handleValueChange = useCallback(
25+
async (value: string) => {
26+
await interactionResponse();
27+
onValueChange(value);
28+
},
29+
[onValueChange]
30+
);
31+
32+
return (
33+
<Root
34+
ref={ref}
35+
{...props}
36+
value={value}
37+
onValueChange={handleValueChange}
38+
/>
39+
);
40+
});
1841

1942
export const TabsList = List;
2043

packages/sdk-components-react/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
"@webstudio-is/react-sdk": "workspace:*",
5353
"@webstudio-is/sdk": "workspace:*",
5454
"colord": "^2.9.3",
55-
"micromark": "^4.0.0"
55+
"micromark": "^4.0.0",
56+
"await-interaction-response": "^0.0.2"
5657
},
5758
"devDependencies": {
5859
"@testing-library/react": "^14.2.2",

packages/sdk-components-react/src/vimeo-play-button.tsx

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ import {
33
type ElementRef,
44
type ComponentProps,
55
useContext,
6+
useCallback,
67
} from "react";
78
import { VimeoContext } from "./vimeo";
89
import { Button, defaultTag } from "./button";
10+
import interactionResponse from "await-interaction-response";
911

1012
export { defaultTag };
1113

@@ -14,10 +16,17 @@ type Props = ComponentProps<typeof Button>;
1416
export const VimeoPlayButton = forwardRef<ElementRef<typeof defaultTag>, Props>(
1517
(props, ref) => {
1618
const vimeoContext = useContext(VimeoContext);
19+
20+
const handleClick = useCallback(async () => {
21+
await interactionResponse();
22+
vimeoContext.onInitPlayer();
23+
}, [vimeoContext]);
24+
1725
if (vimeoContext.status !== "initial") {
1826
return;
1927
}
20-
return <Button {...props} onClick={vimeoContext.onInitPlayer} ref={ref} />;
28+
29+
return <Button {...props} onClick={handleClick} ref={ref} />;
2130
}
2231
);
2332

pnpm-lock.yaml

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)