Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improve INP for drawer content opening and closing #642

Merged
merged 26 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
8f37e9e
fix: improve INP for drawer content opening and closing
artmsilva Jun 6, 2024
8ec15bf
fix: improve INP for drawer content opening and closing
artmsilva Jun 6, 2024
edfb618
fix: improve INP for drawer content opening and closing
artmsilva Jun 6, 2024
ddebd88
fix: also remove RTG from scrim too
artmsilva Jun 6, 2024
59531b6
fix: also remove RTG from scrim too
artmsilva Jun 6, 2024
6e64bb2
chore: commit save point
artmsilva Jun 6, 2024
e629a7e
chore: commit save point
artmsilva Jun 6, 2024
90fdf83
feat: add should render logic to help with mounting and unmounting an…
artmsilva Jun 7, 2024
3ba569d
feat: add should render logic to help with mounting and unmounting an…
artmsilva Jun 7, 2024
05b8db6
chore: commit save point
artmsilva Jun 7, 2024
2b02811
chore: commit save point
artmsilva Jun 7, 2024
5094b01
chore: commit save point
artmsilva Jun 7, 2024
99dc59d
chore: commit save point
artmsilva Jun 7, 2024
03e392a
chore: commit save point
artmsilva Jun 7, 2024
4818fd4
chore: commit save point
artmsilva Jun 7, 2024
03b6462
chore: commit save point
artmsilva Jun 7, 2024
3af2046
Merge branch 'main' into drawer-transition
artmsilva Jun 8, 2024
a64be41
chore: commit save point
artmsilva Jun 8, 2024
a4d523c
chore: commit save point
artmsilva Jun 8, 2024
351a295
chore: commit save point
artmsilva Jun 8, 2024
5f96cf6
chore: commit save point
artmsilva Jun 8, 2024
a34e10f
chore: commit save point
artmsilva Jun 8, 2024
ece0449
chore: commit save point
artmsilva Jun 8, 2024
c0fd446
chore: commit save point
artmsilva Jun 10, 2024
e84a002
chore: commit save point
artmsilva Jun 10, 2024
280b6af
chore: commit save point
artmsilva Jun 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ node_modules
out
jest-coverage
plop-templates
/ui/theme/src/tokens.ts
/packages/kit/src/theme/tokens.ts
8 changes: 4 additions & 4 deletions build.washingtonpost.com/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@
"@washingtonpost/site-footer": "0.25.3-alpha.1",
"@washingtonpost/tachyons-css": "^1.8.0",
"@washingtonpost/wpds-assets": "2.0.0",
"@washingtonpost/wpds-kitchen-sink": "2.3.0",
"@washingtonpost/wpds-tailwind-theme": "2.3.0",
"@washingtonpost/wpds-tokens": "2.3.0",
"@washingtonpost/wpds-ui-kit": "2.3.0",
"@washingtonpost/wpds-kitchen-sink": "*",
"@washingtonpost/wpds-tailwind-theme": "*",
"@washingtonpost/wpds-tokens": "*",
"@washingtonpost/wpds-ui-kit": "file:../packages/kit",
"fuse.js": "^6.6.2",
"gray-matter": "^4.0.2",
"lz-string": "^1.4.4",
Expand Down
1,243 changes: 396 additions & 847 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions packages/kit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"build": "npm run build:transform && tsup && npm run build-types",
"build-types": "tsup src/index.ts --dts-only",
"dev": "tsup --watch",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist",
"canary": "npm run build && npm version prerelease --preid=canary && npm publish --tag=canary"
},
"bugs": {
"url": "https://github.com/washingtonpost/wpds-ui-kit/issues"
Expand All @@ -47,6 +48,8 @@
"@radix-ui/react-radio-group": "^1.0.0",
"@radix-ui/react-select": "^1.2.2",
"@radix-ui/react-separator": "^1.0.0",
"@radix-ui/react-switch": "^1.0.0",
"@radix-ui/react-navigation-menu": "^1.0.0",
"@radix-ui/react-slot": "^1.0.0",
"@radix-ui/react-tabs": "latest",
"@radix-ui/react-tooltip": "^1.0.0",
Expand All @@ -58,7 +61,10 @@
"match-sorter": "6.3.1",
"nanoid": "^3.3.4",
"react-swipeable": "^7.0.0",
"react-transition-group": "^4.4.5"
"react-transition-group": "^4.4.5",
"react-popper": "^2.2.5",
"popper-max-size-modifier": "^0.2.0",
"@popperjs/core": "^2.11.6"
},
"devDependencies": {
"tsup": "8.0.2",
Expand Down
304 changes: 146 additions & 158 deletions packages/kit/src/drawer/DrawerContent.tsx
Original file line number Diff line number Diff line change
@@ -1,138 +1,95 @@
import React from "react";
import { CSSTransition } from "react-transition-group";
import React, { useState, useEffect, useTransition } from "react";
import { FocusScope } from "@radix-ui/react-focus-scope";
import { styled, theme } from "../theme";
import { styled, theme, keyframes } from "../theme";
import type * as WPDS from "../theme";
import { DrawerContext } from "./DrawerRoot";

const drawerTransition = `transform ${theme.transitions.normal} ${theme.transitions.inOut}, opacity ${theme.transitions.normal} ${theme.transitions.inOut}`;

const animateInFromTop = keyframes({
from: { transform: "translateY(-100%)" },
to: { transform: "translateY(0)" },
});

const animationOutFromTop = keyframes({
from: { transform: "translateY(0)" },
to: { transform: "translateY(-100%)" },
});

const animateInFromRight = keyframes({
from: { transform: "translateX(100%)" },
to: { transform: "translateX(0)" },
});

const animateInFromBottom = keyframes({
from: { transform: "translateY(100%)" },
to: { transform: "translateY(0)" },
});

const animateInFromLeft = keyframes({
from: { transform: "translateX(-100%)" },
to: { transform: "translateX(0)" },
});

const StyledContainer = styled("div", {
backgroundColor: theme.colors.secondary,
boxShadow: theme.shadows["300"],
color: theme.colors.primary,
maxHeight: "100%",
overflow: "auto",
position: "fixed",
transition: drawerTransition,
contentVisibility: "auto",
variants: {
/** controls which side of the screen the drawer comes from @default bottom */
position: {
top: {
top: 0,
right: 0,
left: 0,
"&.wpds-drawer-enter": {
opacity: 0,
transform: "translateY(-100%)",
},
"&.wpds-drawer-enter-active": {
opacity: 1,
transform: "translateY(0%)",
transition: drawerTransition,
"@reducedMotion": {
transition: "none",
},
},
"&.wpds-drawer-exit": {
opacity: 1,
transform: "translateY(0%)",
},
"&.wpds-drawer-exit-active": {
opacity: 0,
transform: "translateY(-100%)",
transition: drawerTransition,
"@reducedMotion": {
transition: "none",
},
},
},
right: {
top: 0,
right: 0,
bottom: 0,
"&.wpds-drawer-enter": {
opacity: 0,
transform: "translateX(100%)",
},
"&.wpds-drawer-enter-active": {
opacity: 1,
transform: "translateX(0%)",
transition: drawerTransition,
"@reducedMotion": {
transition: "none",
},
},
"&.wpds-drawer-exit": {
opacity: 1,
transform: "translateX(0%)",
},
"&.wpds-drawer-exit-active": {
opacity: 0,
transform: "translateX(100%)",
transition: drawerTransition,
"@reducedMotion": {
transition: "none",
},
},
},
bottom: {
right: 0,
bottom: 0,
left: 0,
"&.wpds-drawer-enter": {
opacity: 0,
transform: "translateY(100%)",
},
"&.wpds-drawer-enter-active": {
opacity: 1,
transform: "translateY(0%)",
transition: drawerTransition,
"@reducedMotion": {
transition: "none",
},
},
"&.wpds-drawer-exit": {
opacity: 1,
transform: "translateY(0%)",
},
"&.wpds-drawer-exit-active": {
opacity: 0,
transform: "translateY(100%)",
transition: drawerTransition,
"@reducedMotion": {
transition: "none",
},
},
},
left: {
top: 0,
bottom: 0,
left: 0,
"&.wpds-drawer-enter": {
opacity: 0,
transform: "translateX(-100%)",
},
"&.wpds-drawer-enter-active": {
opacity: 1,
transform: "translateX(0%)",
transition: drawerTransition,
"@reducedMotion": {
transition: "none",
},
},
"&.wpds-drawer-exit": {
opacity: 1,
transform: "translateX(0%)",
},
"&.wpds-drawer-exit-active": {
opacity: 0,
transform: "translateX(-100%)",
transition: drawerTransition,
"@reducedMotion": {
transition: "none",
},
},
},
top: { top: 0, right: 0, left: 0 },
right: { top: 0, right: 0, bottom: 0 },
bottom: { right: 0, bottom: 0, left: 0 },
left: { top: 0, bottom: 0, left: 0 },
},
},
"@reducedMotion": {
transition: "none",
},
"&[data-state='open']": {
opacity: 1,
// data=position="top" or "bottom" or "left" or "right"
"&[data-position='top']": {
animation: `${animateInFromTop} ${theme.transitions.normal} ${theme.transitions.inOut}`,
transform: "translateY(0)",
},
"&[data-position='right']": {
animation: `${animateInFromRight} ${theme.transitions.normal} ${theme.transitions.inOut}`,
transform: "translateX(0)",
},
"&[data-position='bottom']": {
animation: `${animateInFromBottom} ${theme.transitions.normal} ${theme.transitions.inOut}`,
transform: "translateY(0)",
},
"&[data-position='left']": {
animation: `${animateInFromLeft} ${theme.transitions.normal} ${theme.transitions.inOut}`,
transform: "translateX(0)",
},
},
// data-state="closed"
"&[data-state='closed']": {
opacity: 0,
// data=position="top" or "bottom" or "left" or "right"
"&[data-position='top']": {
animate: `${animationOutFromTop} ${theme.transitions.normal} ${theme.transitions.inOut}`,
artmsilva marked this conversation as resolved.
Show resolved Hide resolved
transform: "translateY(-100%)",
},
"&[data-position='right']": {
animate: `${animateInFromRight} ${theme.transitions.normal} ${theme.transitions.inOut}`,
transform: "translateX(100%)",
},
"&[data-position='bottom']": {
animate: `${animateInFromBottom} ${theme.transitions.normal} ${theme.transitions.inOut}`,
transform: "translateY(100%)",
},
"&[data-position='left']": {
animate: `${animateInFromLeft} ${theme.transitions.normal} ${theme.transitions.inOut}`,
transform: "translateX(-100%)",
},
},
});
Expand Down Expand Up @@ -175,52 +132,83 @@ export const DrawerContent = React.forwardRef<
ref
) => {
const context = React.useContext(DrawerContext);
const [isPending, startTransition] = useTransition();

const handleTransitionEnd = () => {
if (!context.open) {
handleExit();
setShouldRender(false);
}
};

function handleEnter() {
const handleEnter = () => {
document.addEventListener("keydown", handleKeyDown);
}
};

function handleExit() {
const handleExit = () => {
document.removeEventListener("keydown", handleKeyDown);
}
};

function handleKeyDown(event) {
const handleKeyDown = (event: { key: string }) => {
if (event.key === "Escape") {
context.onOpenChange(false);
}
}

return (
<CSSTransition
mountOnEnter
unmountOnExit
wp-aberg marked this conversation as resolved.
Show resolved Hide resolved
onEnter={handleEnter}
onExit={handleExit}
in={context.open}
timeout={300}
classNames="wpds-drawer"
>
<FocusScope loop={loopFocus} trapped={trapFocus} asChild>
<StyledContainer
id={context.contentId}
ref={ref}
style={{
width:
position === "left" || position === "right" ? width : undefined,
height:
position === "top" || position === "bottom"
? height
: undefined,
zIndex: context.zIndex as number,
}}
position={position}
{...props}
>
<StyledInner className={innerClassName}>{children}</StyledInner>
</StyledContainer>
</FocusScope>
</CSSTransition>
);
};

useEffect(() => {
startTransition(() => {
if (context.open) {
handleEnter();
} else {
handleExit();
}
});
}, [context.open]);

const [shouldRender, setShouldRender] = useState(false);

useEffect(() => {
if (context.open) {
setShouldRender(true);
}

// This is a workaround for a bug in Jest where animations are not run
// https://klaviyo.tech/hitting-a-moving-target-testing-javascript-animations-in-react-with-jest-8284a530a35a
if (process.env.NODE_ENV === "test" && !context.open) {
setShouldRender(false);
}
}, [context.open]);

const handleAnimationEnd = () => {
if (!isPending && !context.open) {
setShouldRender(false);
}
};

return shouldRender ? (
<FocusScope loop={loopFocus} trapped={trapFocus} asChild>
<StyledContainer
ref={ref}
id={context.contentId}
data-position={position}
data-state={context.open ? "open" : "closed"}
style={{
width:
position === "left" || position === "right" ? width : undefined,
height:
position === "top" || position === "bottom" ? height : undefined,
zIndex: context.zIndex as number,
}}
position={position}
val-l-hosler marked this conversation as resolved.
Show resolved Hide resolved
onTransitionEnd={handleTransitionEnd}
onAnimationStart={handleEnter}
onAnimationEnd={handleAnimationEnd}
{...props}
>
<StyledInner className={innerClassName}>{children}</StyledInner>
</StyledContainer>
</FocusScope>
) : null;
}
);

Expand Down
Loading
Loading