diff --git a/packages/paste-core/components/combobox/__tests__/combobox-customization.spec.tsx b/packages/paste-core/components/combobox/__tests__/combobox-customization.spec.tsx index c758040b33..4df1776662 100644 --- a/packages/paste-core/components/combobox/__tests__/combobox-customization.spec.tsx +++ b/packages/paste-core/components/combobox/__tests__/combobox-customization.spec.tsx @@ -24,13 +24,13 @@ const getStyles = (element = "COMBOBOX"): { [key: string]: PasteCustomCSS } => ( }); const initCustomizationWrapper = (elementName?: string | undefined): RenderOptions["wrapper"] => - (function Wrapper({ children }) { + function Wrapper({ children }) { return ( {children} ); - }); + }; const ComboboxToTest = ({ element = "COMBOBOX" }): React.ReactElement => ( // NOTE: This file should not be edited -// see https://nextjs.org/docs/basic-features/typescript for more information. +// see https://nextjs.org/docs/pages/api-reference/config/typescript for more information. diff --git a/packages/paste-theme/__tests__/withTheme.spec.tsx b/packages/paste-theme/__tests__/withTheme.spec.tsx index affacfdc49..b08400c213 100644 --- a/packages/paste-theme/__tests__/withTheme.spec.tsx +++ b/packages/paste-theme/__tests__/withTheme.spec.tsx @@ -6,7 +6,9 @@ import { createRoot } from "testing-tools/react-dom-create-root"; import type { ThemeShape } from "../src"; import { Theme, withTheme } from "../src"; -const MockComponent = ({ theme }: { theme: ThemeShape }): React.ReactElement =>

{theme.textColors.colorText}

; +const MockComponent = ({ theme }: { theme: ThemeShape }): React.ReactElement => ( +

{theme.textColors.colorText}

+); const MockComponentWithTheme = withTheme(MockComponent); describe("withTheme", () => { diff --git a/packages/paste-website/package.json b/packages/paste-website/package.json index cfe0a5b6ba..319f742de2 100644 --- a/packages/paste-website/package.json +++ b/packages/paste-website/package.json @@ -184,9 +184,9 @@ "react-github-button": "^0.1.11", "react-hook-form": "^7.30.0", "react-hotkeys-hook": "^4.4.1", + "react-intersection-observer": "^9.15.1", "react-live": "^3.1.1", "react-scrollspy": "^3.4.0", - "react-visibility-sensor": "5.1.1", "remark-gfm": "^3.0.1", "rollbar": "^2.26.2", "sharp": "^0.32.5", @@ -201,7 +201,7 @@ "zustand": "^4.4.7" }, "devDependencies": { - "@next/eslint-plugin-next": "15.2.0", + "@next/eslint-plugin-next": "14.2.24", "@storybook/react": "7.6.4", "@tanstack/eslint-plugin-query": "^5.17.7", "@testing-library/react": "^16.2.0", diff --git a/packages/paste-website/src/assets/illustrations/DoodleArrow.tsx b/packages/paste-website/src/assets/illustrations/DoodleArrow.tsx index df3930e2f1..9f8711ac60 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleArrow.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleArrow.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; -import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import * as React from "react"; +import { useInView } from "react-intersection-observer"; const dashArray = 250; @@ -10,20 +11,27 @@ export const DoodleArrow = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); + return ( - - + { d="m344.148655 2159.0516-19.1052-24.0516 29.0358 1.512m-12.636 190.8252c69.120001-25.92 101.520001-132.3 0-184.14" transform="matrix(-1 0 0 1 408.043 -2133)" /> - - + + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleBurst.tsx b/packages/paste-website/src/assets/illustrations/DoodleBurst.tsx index 56b568adb7..0daf3b0d37 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleBurst.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleBurst.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; -import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import * as React from "react"; +import { useInView } from "react-intersection-observer"; const dashArray = 260; @@ -10,20 +11,27 @@ export const DoodleBurst = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); + return ( - - + { height="57" fill="none" viewBox="0 0 62 57" - xmlns="http://www.w3.org/2000/svg" + xmlns="http:www.w3.org/2000/svg" > { strokeWidth="2" d="M41.9 1.811L49.76 31.14M19.856 16.52l19.743 23.629M1.366 38.239L32.938 52.83" /> - - + + //{" "} + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleCloud.tsx b/packages/paste-website/src/assets/illustrations/DoodleCloud.tsx index 84bd7d96a7..ef9ca315c1 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleCloud.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleCloud.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; -import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import * as React from "react"; +import { useInView } from "react-intersection-observer"; const dashArray = 160; @@ -10,11 +11,16 @@ export const DoodleCloud = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, @@ -24,15 +30,17 @@ export const DoodleCloud = (): JSX.Element => { }, }); + const AnimatedPath = animated("path"); + return ( - + - - { /> - + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleCurve.tsx b/packages/paste-website/src/assets/illustrations/DoodleCurve.tsx index e24f532719..39103a67e9 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleCurve.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleCurve.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; -import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import * as React from "react"; +import { useInView } from "react-intersection-observer"; const dashArray = 50; @@ -10,20 +11,27 @@ export const DoodleCurve = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); + return ( - - + { d="m1335 1226c-.25169 1.35808-1.83458 9.29809-8.94915 13.52449-7.11458 4.22641-16.96983 3.00357-24.05085-3.38112" transform="matrix(-.5 -.8660254 .8660254 -.5 -392.924817 1771.854751)" /> - - + + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleLoopArrow.tsx b/packages/paste-website/src/assets/illustrations/DoodleLoopArrow.tsx index 7cd0881a8e..46eb82bb8d 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleLoopArrow.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleLoopArrow.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import { useInView } from "react-intersection-observer"; const dashArray = 250; @@ -10,20 +11,27 @@ export const DoodleLoopArrow = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); + return ( - - + { strokeWidth="2" d="M67.65 30.703l24.992 13.844L81.73 9.203" /> - - + + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleLoopArrowLarge.tsx b/packages/paste-website/src/assets/illustrations/DoodleLoopArrowLarge.tsx index d545cc51c0..da99b18976 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleLoopArrowLarge.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleLoopArrowLarge.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; -import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import * as React from "react"; +import { useInView } from "react-intersection-observer"; const dashArray = 350; @@ -10,20 +11,27 @@ export const DoodleLoopArrowLarge = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); + return ( - - + { strokeWidth="2" d="M171.344 1.59c-34.204 9.243-53.899 28.315-45.514 45.922 6.641 13.944 18.251 14.936 12.365.38-25.277-62.508-125.41 60.186-125.65 119.236" /> - - + + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleLoopLarge.tsx b/packages/paste-website/src/assets/illustrations/DoodleLoopLarge.tsx index 6a5861f8e0..b09f042d30 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleLoopLarge.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleLoopLarge.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import { useInView } from "react-intersection-observer"; const dashArray = 350; @@ -10,20 +11,26 @@ export const DoodleLoopLarge = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); return ( - - + { d="m1243 2198c64.87467-44.8 80.72191-116.48 51.50355-122.58462-12.47475-2.6043-18.93746 4.47508-6.43794 7.87693 53.66769 14.61169 23.27564-111.75385-15.35202-141.29231" transform="translate(-1241 -1940)" /> - - + + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleLoopMedium.tsx b/packages/paste-website/src/assets/illustrations/DoodleLoopMedium.tsx index ea8bb09bd3..bb0f3a7405 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleLoopMedium.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleLoopMedium.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; -import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import * as React from "react"; +import { useInView } from "react-intersection-observer"; const dashArray = 350; @@ -10,20 +11,27 @@ export const DoodleLoopMedium = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); + return ( - - + { strokeWidth="2" d="M53.527 139.26a74.384 74.384 0 0021.888-30.826c8.939-23.983-2.428-68.705-23.83-69.065-12.107-.203-12.712 13.61 3.671 14.666C73.936 55.239 96.861 26.418 85.161 2" /> - - + + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleLoopSmall.tsx b/packages/paste-website/src/assets/illustrations/DoodleLoopSmall.tsx index f6721d7c71..c6992e9ab3 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleLoopSmall.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleLoopSmall.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; -import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import * as React from "react"; +import { useInView } from "react-intersection-observer"; const dashArray = 110; @@ -10,20 +11,27 @@ export const DoodleLoopSmall = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); + return ( - - + { d="M364,1507.07693 C349.942623,1512.99997 333.47541,1504.31284 333.877049,1493.65136 C334.278689,1482.98987 345.52459,1484.17448 345.52459,1492.86162 C345.52459,1504.70771 325.040984,1512.99997 315,1505.10258" transform="rotate(36 2469.219 271.304)" /> - - + + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleLoopTiny.tsx b/packages/paste-website/src/assets/illustrations/DoodleLoopTiny.tsx index 657a905093..e934b72844 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleLoopTiny.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleLoopTiny.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import { useInView } from "react-intersection-observer"; const dashArray = 110; @@ -10,20 +11,26 @@ export const DoodleLoopTiny = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); return ( - - + { strokeWidth="2" d="M2 47.603a38.008 38.008 0 0019.233 1.81c12.897-2.172 29.783-18.627 24.474-28.19-3.003-5.41-9.27-2.148-5.551 5.371 4.239 8.574 22.85 11.355 30.666-.06" /> - - + + ); }; diff --git a/packages/paste-website/src/assets/illustrations/DoodleZigzag.tsx b/packages/paste-website/src/assets/illustrations/DoodleZigzag.tsx index 737e5ecf4b..7147c72168 100644 --- a/packages/paste-website/src/assets/illustrations/DoodleZigzag.tsx +++ b/packages/paste-website/src/assets/illustrations/DoodleZigzag.tsx @@ -1,8 +1,9 @@ import { animated, useSpring } from "@twilio-paste/animation-library"; +import { Box } from "@twilio-paste/box"; import { useTheme } from "@twilio-paste/theme"; import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import { useInView } from "react-intersection-observer"; const dashArray = 260; @@ -10,20 +11,27 @@ export const DoodleZigzag = (): JSX.Element => { const [show, setShow] = React.useState(false); const theme = useTheme(); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { - setShow(isVisible); + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (inView && !show) { + setShow(true); } - } + }, [inView, show]); const styles = useSpring({ x: show ? 0 : -1 * dashArray, config: { mass: 1, tension: 280, friction: 40 }, }); + const AnimatedSVG = animated("svg"); + return ( - - + { d="m464 1781.6-14.8-37.2-17.6 38.8-22-47.2-14 50.8-29.6-24.4 2.4 33.6" transform="translate(-365 -1735)" /> - - + + ); }; diff --git a/packages/paste-website/src/components/color-swatch/ColorGradient.tsx b/packages/paste-website/src/components/color-swatch/ColorGradient.tsx index d2064c7720..3f6bde4aa1 100644 --- a/packages/paste-website/src/components/color-swatch/ColorGradient.tsx +++ b/packages/paste-website/src/components/color-swatch/ColorGradient.tsx @@ -6,7 +6,7 @@ import { styled, themeGet } from "@twilio-paste/styling-library"; import { useUID } from "@twilio-paste/uid-library"; import * as React from "react"; import type { JSX } from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import { useInView } from "react-intersection-observer"; import { useDarkModeContext } from "../../context/DarkModeContext"; import type { Themes } from "../../types"; @@ -52,11 +52,8 @@ const StyledGradientSwatch = styled.div<{ backgroundColor: string }>` const StyledGradientSwatchTall = styled.div<{ backgroundColor: string; rounded: boolean }>((props) => { return { backgroundColor: props.backgroundColor, - // @ts-expect-error this works fine height: props.theme.space.space120, - // @ts-expect-error this works fine borderBottomLeftRadius: props.rounded ? props.theme.radii.borderRadius20 : 0, - // @ts-expect-error this works fine borderBottomRightRadius: props.rounded ? props.theme.radii.borderRadius20 : 0, }; }); @@ -69,13 +66,18 @@ export const ColorGradient: React.FC< const aliasValues = getAliasValuesFromPrefix(aliasPrefix, theme); const count = aliasValues.length - 1; - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.3, + }); + + React.useEffect(() => { + if (inView && !show) { setTimeout(() => { - setShow(isVisible); + setShow(true); }, index * 50); } - } + }, [inView, show, index]); const styles = useSpring({ opacity: show ? 1 : 0.1, @@ -86,13 +88,13 @@ export const ColorGradient: React.FC< if (makeTall) { return ( - + {aliasValues.map((aliasValue, _index) => ( ))} - + ); } return ( diff --git a/packages/paste-website/src/components/customization-landing-page/ReadyToGetStarted.tsx b/packages/paste-website/src/components/customization-landing-page/ReadyToGetStarted.tsx index de3b27b5ac..30bd6d4b71 100644 --- a/packages/paste-website/src/components/customization-landing-page/ReadyToGetStarted.tsx +++ b/packages/paste-website/src/components/customization-landing-page/ReadyToGetStarted.tsx @@ -15,6 +15,7 @@ export const ReadyToGetStarted = (): JSX.Element => { diff --git a/packages/paste-website/src/components/customization-landing-page/image-slider/ImageSlider.tsx b/packages/paste-website/src/components/customization-landing-page/image-slider/ImageSlider.tsx index 60c325c5b7..f72c42ebfa 100644 --- a/packages/paste-website/src/components/customization-landing-page/image-slider/ImageSlider.tsx +++ b/packages/paste-website/src/components/customization-landing-page/image-slider/ImageSlider.tsx @@ -2,7 +2,7 @@ import { Box } from "@twilio-paste/box"; import { useUIDSeed } from "@twilio-paste/uid-library"; import Image from "next/image"; import * as React from "react"; -import type { JSX, Ref, MutableRefObject } from "react"; +import type { JSX, Ref, RefObject } from "react"; import HeroBack from "../../../assets/images/customization/hero-back.png"; import HeroFront from "../../../assets/images/customization/hero-front.png"; @@ -94,7 +94,7 @@ export const ImageSlider = (): JSX.Element => { maxWidth="size60" position="absolute" top="space150" - ref={containerRef as MutableRefObject} + ref={containerRef as RefObject} right="spaceNegative150" width="60%" zIndex="zIndex10" diff --git a/packages/paste-website/src/components/homepage/HomeHeroIllustration.tsx b/packages/paste-website/src/components/homepage/HomeHeroIllustration.tsx index 4fcf23c750..ad6eeee4b8 100644 --- a/packages/paste-website/src/components/homepage/HomeHeroIllustration.tsx +++ b/packages/paste-website/src/components/homepage/HomeHeroIllustration.tsx @@ -4,7 +4,7 @@ import type { ValueOf } from "@twilio-paste/types"; import lottie from "lottie-web"; import Image from "next/image"; import * as React from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import { useInView } from "react-intersection-observer"; import HomeHeroIllu from "../../assets/illustrations/home_hero.svg"; import { inCypress } from "../../utils/inCypress"; @@ -44,11 +44,16 @@ const HomeHeroIllustration: React.FC> = () => { const containerRef = React.useRef(null); const [illustrationState, setIllustrationState] = React.useState(IllustrationStates.UNINITIALIZED); - const handleVisibilityChange = (isVisible: boolean): void => { - if (illustrationState === IllustrationStates.UNINITIALIZED && isVisible) { + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 0.1, + }); + + React.useEffect(() => { + if (illustrationState === IllustrationStates.UNINITIALIZED && inView) { setIllustrationState(prefersReducedMotion ? IllustrationStates.STATIC : IllustrationStates.DYNAMIC); } - }; + }, [inView, illustrationState, prefersReducedMotion]); React.useEffect(() => { if (!prefersReducedMotion && illustrationState === IllustrationStates.DYNAMIC) { @@ -84,7 +89,7 @@ const HomeHeroIllustration: React.FC> = () => { * Also to prevent height fouc when the animation loads */ return ( - + - + ); }; diff --git a/packages/paste-website/src/components/homepage/Themeable.tsx b/packages/paste-website/src/components/homepage/Themeable.tsx index 596bf6dd06..678a5a342b 100644 --- a/packages/paste-website/src/components/homepage/Themeable.tsx +++ b/packages/paste-website/src/components/homepage/Themeable.tsx @@ -71,10 +71,12 @@ const Boop: React.FC = ({ }; }, [isBooped, timing]); + const AnimatedSpan = animated("span"); + return ( - + {children} - + ); }; diff --git a/packages/paste-website/src/components/homepage/WeDoTheThinking.tsx b/packages/paste-website/src/components/homepage/WeDoTheThinking.tsx index 87c303cd36..98cc468fda 100644 --- a/packages/paste-website/src/components/homepage/WeDoTheThinking.tsx +++ b/packages/paste-website/src/components/homepage/WeDoTheThinking.tsx @@ -4,7 +4,7 @@ import { Heading } from "@twilio-paste/heading"; import { CheckboxCheckIcon } from "@twilio-paste/icons/esm/CheckboxCheckIcon"; import { Text } from "@twilio-paste/text"; import * as React from "react"; -import VisibilitySensor from "react-visibility-sensor"; +import { useInView } from "react-intersection-observer"; import { SectionContainer } from "./SectionContainer"; @@ -16,13 +16,19 @@ const ThinkingLine: React.FC<{ children: React.ReactNode; index: number }> = ({ }): React.ReactElement => { const [show, setShow] = React.useState(false); - function handleVisibilityChange(isVisible: boolean): void { - if (!show) { + const { ref, inView } = useInView({ + triggerOnce: true, + threshold: 1, + delay: 100, + }); + + React.useEffect(() => { + if (inView && !show) { setTimeout(() => { - setShow(isVisible); + setShow(true); }, index * 50); } - } + }, [inView, show, index]); const styles = useSpring({ opacity: show ? 1 : 0.1, @@ -32,7 +38,7 @@ const ThinkingLine: React.FC<{ children: React.ReactNode; index: number }> = ({ }); return ( - + = ({ {children} - + ); }; diff --git a/packages/paste-website/src/components/site-wrapper/site-footer/SiteFooterNav.tsx b/packages/paste-website/src/components/site-wrapper/site-footer/SiteFooterNav.tsx index de302f125f..6e5b11cb3d 100644 --- a/packages/paste-website/src/components/site-wrapper/site-footer/SiteFooterNav.tsx +++ b/packages/paste-website/src/components/site-wrapper/site-footer/SiteFooterNav.tsx @@ -196,7 +196,7 @@ const SiteFooterNav = (): JSX.Element => { diff --git a/yarn.lock b/yarn.lock index 2148723423..beed64c788 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3776,26 +3776,7 @@ __metadata: languageName: node linkType: hard -"@emotion/babel-plugin@npm:^11.11.0": - version: 11.13.5 - resolution: "@emotion/babel-plugin@npm:11.13.5" - dependencies: - "@babel/helper-module-imports": ^7.16.7 - "@babel/runtime": ^7.18.3 - "@emotion/hash": ^0.9.2 - "@emotion/memoize": ^0.9.0 - "@emotion/serialize": ^1.3.3 - babel-plugin-macros: ^3.1.0 - convert-source-map: ^1.5.0 - escape-string-regexp: ^4.0.0 - find-root: ^1.1.0 - source-map: ^0.5.7 - stylis: 4.2.0 - checksum: c41df7e6c19520e76d1939f884be878bf88b5ba00bd3de9d05c5b6c5baa5051686ab124d7317a0645de1b017b574d8139ae1d6390ec267fbe8e85a5252afb542 - languageName: node - linkType: hard - -"@emotion/babel-plugin@npm:^11.2.0, @emotion/babel-plugin@npm:^11.7.1": +"@emotion/babel-plugin@npm:^11.10.5, @emotion/babel-plugin@npm:^11.2.0, @emotion/babel-plugin@npm:^11.7.1": version: 11.10.5 resolution: "@emotion/babel-plugin@npm:11.10.5" dependencies: @@ -3831,33 +3812,7 @@ __metadata: languageName: node linkType: hard -"@emotion/cache@npm:11.11.0": - version: 11.11.0 - resolution: "@emotion/cache@npm:11.11.0" - dependencies: - "@emotion/memoize": ^0.8.1 - "@emotion/sheet": ^1.2.2 - "@emotion/utils": ^1.2.1 - "@emotion/weak-memoize": ^0.3.1 - stylis: 4.2.0 - checksum: 8eb1dc22beaa20c21a2e04c284d5a2630a018a9d51fb190e52de348c8d27f4e8ca4bbab003d68b4f6cd9cc1c569ca747a997797e0f76d6c734a660dc29decf08 - languageName: node - linkType: hard - -"@emotion/cache@npm:^11.11.0": - version: 11.14.0 - resolution: "@emotion/cache@npm:11.14.0" - dependencies: - "@emotion/memoize": ^0.9.0 - "@emotion/sheet": ^1.4.0 - "@emotion/utils": ^1.4.2 - "@emotion/weak-memoize": ^0.4.0 - stylis: 4.2.0 - checksum: 0a81591541ea43bc7851742e6444b7800d72e98006f94e775ae6ea0806662d14e0a86ff940f5f19d33b4bb2c427c882aa65d417e7322a6e0d5f20fe65ed920c9 - languageName: node - linkType: hard - -"@emotion/cache@npm:^11.7.1": +"@emotion/cache@npm:11.10.5, @emotion/cache@npm:^11.10.5, @emotion/cache@npm:^11.7.1": version: 11.10.5 resolution: "@emotion/cache@npm:11.10.5" dependencies: @@ -3921,13 +3876,6 @@ __metadata: languageName: node linkType: hard -"@emotion/hash@npm:^0.9.2": - version: 0.9.2 - resolution: "@emotion/hash@npm:0.9.2" - checksum: 379bde2830ccb0328c2617ec009642321c0e009a46aa383dfbe75b679c6aea977ca698c832d225a893901f29d7b3eef0e38cf341f560f6b2b56f1ff23c172387 - languageName: node - linkType: hard - "@emotion/is-prop-valid@npm:^0.8.1": version: 0.8.8 resolution: "@emotion/is-prop-valid@npm:0.8.8" @@ -3937,12 +3885,12 @@ __metadata: languageName: node linkType: hard -"@emotion/is-prop-valid@npm:^1.2.1": - version: 1.3.1 - resolution: "@emotion/is-prop-valid@npm:1.3.1" +"@emotion/is-prop-valid@npm:^1.2.0": + version: 1.2.0 + resolution: "@emotion/is-prop-valid@npm:1.2.0" dependencies: - "@emotion/memoize": ^0.9.0 - checksum: fe6549d54f389e1a17cb02d832af7ee85fb6ea126fc18d02ca47216e8ff19332c1983f4a0ba68602cfcd3b325ffd4ebf0b2d0c6270f1e7e6fe3fca4ba7741e1a + "@emotion/memoize": ^0.8.0 + checksum: cc7a19850a4c5b24f1514665289442c8c641709e6f7711067ad550e05df331da0692a16148e85eda6f47e31b3261b64d74c5e25194d053223be16231f969d633 languageName: node linkType: hard @@ -3988,38 +3936,27 @@ __metadata: languageName: node linkType: hard -"@emotion/memoize@npm:^0.8.1": - version: 0.8.1 - resolution: "@emotion/memoize@npm:0.8.1" - checksum: a19cc01a29fcc97514948eaab4dc34d8272e934466ed87c07f157887406bc318000c69ae6f813a9001c6a225364df04249842a50e692ef7a9873335fbcc141b0 - languageName: node - linkType: hard - -"@emotion/memoize@npm:^0.9.0": - version: 0.9.0 - resolution: "@emotion/memoize@npm:0.9.0" - checksum: 038132359397348e378c593a773b1148cd0cf0a2285ffd067a0f63447b945f5278860d9de718f906a74c7c940ba1783ac2ca18f1c06a307b01cc0e3944e783b1 - languageName: node - linkType: hard - -"@emotion/react@npm:11.11.0": - version: 11.11.0 - resolution: "@emotion/react@npm:11.11.0" +"@emotion/react@npm:11.10.5": + version: 11.10.5 + resolution: "@emotion/react@npm:11.10.5" dependencies: "@babel/runtime": ^7.18.3 - "@emotion/babel-plugin": ^11.11.0 - "@emotion/cache": ^11.11.0 - "@emotion/serialize": ^1.1.2 - "@emotion/use-insertion-effect-with-fallbacks": ^1.0.1 - "@emotion/utils": ^1.2.1 - "@emotion/weak-memoize": ^0.3.1 + "@emotion/babel-plugin": ^11.10.5 + "@emotion/cache": ^11.10.5 + "@emotion/serialize": ^1.1.1 + "@emotion/use-insertion-effect-with-fallbacks": ^1.0.0 + "@emotion/utils": ^1.2.0 + "@emotion/weak-memoize": ^0.3.0 hoist-non-react-statics: ^3.3.1 peerDependencies: + "@babel/core": ^7.0.0 react: ">=16.8.0" peerDependenciesMeta: + "@babel/core": + optional: true "@types/react": optional: true - checksum: 2653e7c3de7b6fd5b0e18dea15621a9886104cc7c8cd5522ca69e52bd547ef6f13644193f8e0a906eea1e29a4f1d8167cdfa4667572fb7fafe0c62ab30fbaab6 + checksum: 32b67b28e9b6d6c53b970072680697f04c2521441050bdeb19a1a7f0164af549b4dad39ff375eda1b6a3cf1cc86ba2c6fa55460ec040e6ebbca3e9ec58353cf7 languageName: node linkType: hard @@ -4036,19 +3973,6 @@ __metadata: languageName: node linkType: hard -"@emotion/serialize@npm:^1.1.2, @emotion/serialize@npm:^1.3.3": - version: 1.3.3 - resolution: "@emotion/serialize@npm:1.3.3" - dependencies: - "@emotion/hash": ^0.9.2 - "@emotion/memoize": ^0.9.0 - "@emotion/unitless": ^0.10.0 - "@emotion/utils": ^1.4.2 - csstype: ^3.0.2 - checksum: 510331233767ae4e09e925287ca2c7269b320fa1d737ea86db5b3c861a734483ea832394c0c1fe5b21468fe335624a75e72818831d303ba38125f54f44ba02e7 - languageName: node - linkType: hard - "@emotion/sheet@npm:^1.0.3, @emotion/sheet@npm:^1.2.1": version: 1.2.1 resolution: "@emotion/sheet@npm:1.2.1" @@ -4056,37 +3980,26 @@ __metadata: languageName: node linkType: hard -"@emotion/sheet@npm:^1.2.2, @emotion/sheet@npm:^1.4.0": - version: 1.4.0 - resolution: "@emotion/sheet@npm:1.4.0" - checksum: eeb1212e3289db8e083e72e7e401cd6d1a84deece87e9ce184f7b96b9b5dbd6f070a89057255a6ff14d9865c3ce31f27c39248a053e4cdd875540359042586b4 - languageName: node - linkType: hard - -"@emotion/styled@npm:11.11.0": - version: 11.11.0 - resolution: "@emotion/styled@npm:11.11.0" +"@emotion/styled@npm:11.10.5": + version: 11.10.5 + resolution: "@emotion/styled@npm:11.10.5" dependencies: "@babel/runtime": ^7.18.3 - "@emotion/babel-plugin": ^11.11.0 - "@emotion/is-prop-valid": ^1.2.1 - "@emotion/serialize": ^1.1.2 - "@emotion/use-insertion-effect-with-fallbacks": ^1.0.1 - "@emotion/utils": ^1.2.1 + "@emotion/babel-plugin": ^11.10.5 + "@emotion/is-prop-valid": ^1.2.0 + "@emotion/serialize": ^1.1.1 + "@emotion/use-insertion-effect-with-fallbacks": ^1.0.0 + "@emotion/utils": ^1.2.0 peerDependencies: + "@babel/core": ^7.0.0 "@emotion/react": ^11.0.0-rc.0 react: ">=16.8.0" peerDependenciesMeta: + "@babel/core": + optional: true "@types/react": optional: true - checksum: 904f641aad3892c65d7d6c0808b036dae1e6d6dad4861c1c7dc0baa59977047c6cad220691206eba7b4059f1a1c6e6c1ef4ebb8c829089e280fa0f2164a01e6b - languageName: node - linkType: hard - -"@emotion/unitless@npm:^0.10.0": - version: 0.10.0 - resolution: "@emotion/unitless@npm:0.10.0" - checksum: d79346df31a933e6d33518e92636afeb603ce043f3857d0a39a2ac78a09ef0be8bedff40130930cb25df1beeee12d96ee38613963886fa377c681a89970b787c + checksum: 1cec5f6aeb227a7255141031e8594f38ad83902413472aae0a46c27e5f9769c01e23c1ad39adee408d8a2168a697464314d1a0c4f50b31a5d25ea506b2d7bbc8 languageName: node linkType: hard @@ -4106,15 +4019,6 @@ __metadata: languageName: node linkType: hard -"@emotion/use-insertion-effect-with-fallbacks@npm:^1.0.1": - version: 1.2.0 - resolution: "@emotion/use-insertion-effect-with-fallbacks@npm:1.2.0" - peerDependencies: - react: ">=16.8.0" - checksum: 8ff6aec7f2924526ff8c8f8f93d4b8236376e2e12c435314a18c9a373016e24dfdf984e82bbc83712b8e90ff4783cd765eb39fc7050d1a43245e5728740ddd71 - languageName: node - linkType: hard - "@emotion/utils@npm:^1.0.0, @emotion/utils@npm:^1.2.0": version: 1.2.0 resolution: "@emotion/utils@npm:1.2.0" @@ -4122,13 +4026,6 @@ __metadata: languageName: node linkType: hard -"@emotion/utils@npm:^1.2.1, @emotion/utils@npm:^1.4.2": - version: 1.4.2 - resolution: "@emotion/utils@npm:1.4.2" - checksum: 04cf76849c6401205c058b82689fd0ec5bf501aed6974880fe9681a1d61543efb97e848f4c38664ac4a9068c7ad2d1cb84f73bde6cf95f1208aa3c28e0190321 - languageName: node - linkType: hard - "@emotion/weak-memoize@npm:^0.3.0": version: 0.3.0 resolution: "@emotion/weak-memoize@npm:0.3.0" @@ -4136,20 +4033,6 @@ __metadata: languageName: node linkType: hard -"@emotion/weak-memoize@npm:^0.3.1": - version: 0.3.1 - resolution: "@emotion/weak-memoize@npm:0.3.1" - checksum: b2be47caa24a8122622ea18cd2d650dbb4f8ad37b636dc41ed420c2e082f7f1e564ecdea68122b546df7f305b159bf5ab9ffee872abd0f052e687428459af594 - languageName: node - linkType: hard - -"@emotion/weak-memoize@npm:^0.4.0": - version: 0.4.0 - resolution: "@emotion/weak-memoize@npm:0.4.0" - checksum: db5da0e89bd752c78b6bd65a1e56231f0abebe2f71c0bd8fc47dff96408f7065b02e214080f99924f6a3bfe7ee15afc48dad999d76df86b39b16e513f7a94f52 - languageName: node - linkType: hard - "@esbuild/android-arm64@npm:0.18.20": version: 0.18.20 resolution: "@esbuild/android-arm64@npm:0.18.20" @@ -5989,12 +5872,12 @@ __metadata: languageName: node linkType: hard -"@next/eslint-plugin-next@npm:15.2.0": - version: 15.2.0 - resolution: "@next/eslint-plugin-next@npm:15.2.0" +"@next/eslint-plugin-next@npm:14.2.24": + version: 14.2.24 + resolution: "@next/eslint-plugin-next@npm:14.2.24" dependencies: - fast-glob: 3.3.1 - checksum: 3ce7ddcf8d2d66bf44adc5ed224f4fe3b7d6eb9566ef2a95d9c700c5e5cf5dd274fd9152c1585448f423c4079b24d21e9fd42e783fc9c8aaa7c3a536f6b625a5 + glob: 10.3.10 + checksum: fbcfa0eaa592930d1da7be55a78caf3232783644bd62e2c545f865bc45633917d1b897e955f675e921108903b0db4e89660037efdda659016095ac68474284e4 languageName: node linkType: hard @@ -15559,9 +15442,9 @@ __metadata: version: 0.0.0-use.local resolution: "@twilio-paste/styling-library@workspace:packages/paste-libraries/styling" dependencies: - "@emotion/cache": 11.11.0 - "@emotion/react": 11.11.0 - "@emotion/styled": 11.11.0 + "@emotion/cache": 11.10.5 + "@emotion/react": 11.10.5 + "@emotion/styled": 11.10.5 "@styled-system/css": 5.1.5 "@styled-system/should-forward-prop": 5.1.5 "@styled-system/theme-get": 5.1.2 @@ -16466,7 +16349,7 @@ __metadata: "@mdx-js/mdx": ^1.6.22 "@mdx-js/react": ^1.6.22 "@next/bundle-analyzer": 15.2.0 - "@next/eslint-plugin-next": 15.2.0 + "@next/eslint-plugin-next": 14.2.24 "@next/mdx": 15.2.0 "@octokit/core": ^5.0.1 "@octokit/plugin-paginate-graphql": ^4.0.0 @@ -16630,9 +16513,9 @@ __metadata: react-github-button: ^0.1.11 react-hook-form: ^7.30.0 react-hotkeys-hook: ^4.4.1 + react-intersection-observer: ^9.15.1 react-live: ^3.1.1 react-scrollspy: ^3.4.0 - react-visibility-sensor: 5.1.1 remark-gfm: ^3.0.1 rollbar: ^2.26.2 sharp: ^0.32.5 @@ -26461,19 +26344,6 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:3.3.1": - version: 3.3.1 - resolution: "fast-glob@npm:3.3.1" - dependencies: - "@nodelib/fs.stat": ^2.0.2 - "@nodelib/fs.walk": ^1.2.3 - glob-parent: ^5.1.2 - merge2: ^1.3.0 - micromatch: ^4.0.4 - checksum: b6f3add6403e02cf3a798bfbb1183d0f6da2afd368f27456010c0bc1f9640aea308243d4cb2c0ab142f618276e65ecb8be1661d7c62a7b4e5ba774b9ce5432e5 - languageName: node - linkType: hard - "fast-glob@npm:^3.0.3, fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.2, fast-glob@npm:^3.2.9": version: 3.2.12 resolution: "fast-glob@npm:3.2.12" @@ -27936,6 +27806,21 @@ fsevents@^1.2.7: languageName: node linkType: hard +"glob@npm:10.3.10": + version: 10.3.10 + resolution: "glob@npm:10.3.10" + dependencies: + foreground-child: ^3.1.0 + jackspeak: ^2.3.5 + minimatch: ^9.0.1 + minipass: ^5.0.0 || ^6.0.2 || ^7.0.0 + path-scurry: ^1.10.1 + bin: + glob: dist/esm/bin.mjs + checksum: 4f2fe2511e157b5a3f525a54092169a5f92405f24d2aed3142f4411df328baca13059f4182f1db1bf933e2c69c0bd89e57ae87edd8950cba8c7ccbe84f721cf3 + languageName: node + linkType: hard + "glob@npm:7.1.2": version: 7.1.2 resolution: "glob@npm:7.1.2" @@ -30845,6 +30730,19 @@ fsevents@^1.2.7: languageName: node linkType: hard +"jackspeak@npm:^2.3.5": + version: 2.3.6 + resolution: "jackspeak@npm:2.3.6" + dependencies: + "@isaacs/cliui": ^8.0.2 + "@pkgjs/parseargs": ^0.11.0 + dependenciesMeta: + "@pkgjs/parseargs": + optional: true + checksum: 57d43ad11eadc98cdfe7496612f6bbb5255ea69fe51ea431162db302c2a11011642f50cfad57288bd0aea78384a0612b16e131944ad8ecd09d619041c8531b54 + languageName: node + linkType: hard + "jackspeak@npm:^3.1.2": version: 3.4.3 resolution: "jackspeak@npm:3.4.3" @@ -39953,6 +39851,19 @@ fsevents@^1.2.7: languageName: node linkType: hard +"react-intersection-observer@npm:^9.15.1": + version: 9.15.1 + resolution: "react-intersection-observer@npm:9.15.1" + peerDependencies: + react: ^17.0.0 || ^18.0.0 || ^19.0.0 + react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + react-dom: + optional: true + checksum: 9769b06f065a246c2e477ad6a4ffeeb66c0c00098f094980f123df4ef1e09067b8d4b9f88d5f8e3a6de747c384b02452d0ac8cb91fff7093c15b8375ae097166 + languageName: node + linkType: hard + "react-is@npm:18.0.0": version: 18.0.0 resolution: "react-is@npm:18.0.0" @@ -40328,18 +40239,6 @@ fsevents@^1.2.7: languageName: node linkType: hard -"react-visibility-sensor@npm:5.1.1": - version: 5.1.1 - resolution: "react-visibility-sensor@npm:5.1.1" - dependencies: - prop-types: ^15.7.2 - peerDependencies: - react: ">=16.0.0" - react-dom: ">=16.0.0" - checksum: ebce7bc743071930a2dd333a041c4a99aac24d5059c47a52eff25a8d81ab9307fadc87b8a6655ebb3154f5c1ceafcc309ae04ee07a7d5fad2949a6903d15acd5 - languageName: node - linkType: hard - "react@npm:^19.0.0": version: 19.0.0 resolution: "react@npm:19.0.0" @@ -43580,13 +43479,6 @@ resolve@^2.0.0-next.3: languageName: node linkType: hard -"stylis@npm:4.2.0": - version: 4.2.0 - resolution: "stylis@npm:4.2.0" - checksum: 0eb6cc1b866dc17a6037d0a82ac7fa877eba6a757443e79e7c4f35bacedbf6421fadcab4363b39667b43355cbaaa570a3cde850f776498e5450f32ed2f9b7584 - languageName: node - linkType: hard - "success-symbol@npm:^0.1.0": version: 0.1.0 resolution: "success-symbol@npm:0.1.0"