Przeglądaj źródła

deprecate animate-height in favor of framer motion (#4094)

ianedwards 2 lat temu
rodzic
commit
d2dd07c2dd

+ 75 - 0
dashboard/package-lock.json

@@ -47,6 +47,7 @@
         "dayjs": "^1.11.5",
         "deep-diff": "^1.0.2",
         "dotenv": "^8.2.0",
+        "framer-motion": "^10.16.16",
         "fuse.js": "^6.6.2",
         "ini": ">=1.3.6",
         "js-base64": "^3.6.0",
@@ -9095,6 +9096,49 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/framer-motion": {
+      "version": "10.16.16",
+      "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.16.16.tgz",
+      "integrity": "sha512-je6j91rd7NmUX7L1XHouwJ4v3R+SO4umso2LUcgOct3rHZ0PajZ80ETYZTajzEXEl9DlKyzjyt4AvGQ+lrebOw==",
+      "dependencies": {
+        "tslib": "^2.4.0"
+      },
+      "optionalDependencies": {
+        "@emotion/is-prop-valid": "^0.8.2"
+      },
+      "peerDependencies": {
+        "react": "^18.0.0",
+        "react-dom": "^18.0.0"
+      },
+      "peerDependenciesMeta": {
+        "react": {
+          "optional": true
+        },
+        "react-dom": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/framer-motion/node_modules/@emotion/is-prop-valid": {
+      "version": "0.8.8",
+      "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
+      "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
+      "optional": true,
+      "dependencies": {
+        "@emotion/memoize": "0.7.4"
+      }
+    },
+    "node_modules/framer-motion/node_modules/@emotion/memoize": {
+      "version": "0.7.4",
+      "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
+      "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==",
+      "optional": true
+    },
+    "node_modules/framer-motion/node_modules/tslib": {
+      "version": "2.6.2",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+      "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+    },
     "node_modules/fresh": {
       "version": "0.5.2",
       "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
@@ -25042,6 +25086,37 @@
         "map-cache": "^0.2.2"
       }
     },
+    "framer-motion": {
+      "version": "10.16.16",
+      "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.16.16.tgz",
+      "integrity": "sha512-je6j91rd7NmUX7L1XHouwJ4v3R+SO4umso2LUcgOct3rHZ0PajZ80ETYZTajzEXEl9DlKyzjyt4AvGQ+lrebOw==",
+      "requires": {
+        "@emotion/is-prop-valid": "^0.8.2",
+        "tslib": "^2.4.0"
+      },
+      "dependencies": {
+        "@emotion/is-prop-valid": {
+          "version": "0.8.8",
+          "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz",
+          "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==",
+          "optional": true,
+          "requires": {
+            "@emotion/memoize": "0.7.4"
+          }
+        },
+        "@emotion/memoize": {
+          "version": "0.7.4",
+          "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz",
+          "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==",
+          "optional": true
+        },
+        "tslib": {
+          "version": "2.6.2",
+          "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+          "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+        }
+      }
+    },
     "fresh": {
       "version": "0.5.2",
       "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",

+ 1 - 0
dashboard/package.json

@@ -42,6 +42,7 @@
     "dayjs": "^1.11.5",
     "deep-diff": "^1.0.2",
     "dotenv": "^8.2.0",
+    "framer-motion": "^10.16.16",
     "fuse.js": "^6.6.2",
     "ini": ">=1.3.6",
     "js-base64": "^3.6.0",

+ 32 - 40
dashboard/src/main/home/app-dashboard/validate-apply/services-settings/ServiceContainer.tsx

@@ -1,13 +1,12 @@
-import React, { useCallback, useEffect, useState } from "react";
+import React from "react";
+import { AnimatePresence, motion } from "framer-motion";
 import _ from "lodash";
-import AnimateHeight, { type Height } from "react-animate-height";
 import { type UseFieldArrayUpdate } from "react-hook-form";
 import styled, { keyframes } from "styled-components";
 import { match } from "ts-pattern";
 
 import Spacer from "components/porter/Spacer";
 import { type PorterAppVersionStatus } from "lib/hooks/useAppStatus";
-import useResizeObserver from "lib/hooks/useResizeObserver";
 import { type PorterAppFormData } from "lib/porter-apps";
 import { type ClientService } from "lib/porter-apps/services";
 
@@ -54,28 +53,6 @@ const ServiceContainer: React.FC<ServiceProps> = ({
   clusterIngressIp,
   showDisableTls,
 }) => {
-  const [height, setHeight] = useState<Height>(service.expanded ? "auto" : 0);
-
-  // onResize is called when the height of the service container changes
-  // used to set the height of the AnimateHeight component on tab swtich
-  const onResize = useCallback(
-    (elt: HTMLDivElement) => {
-      if (elt.clientHeight === 0) {
-        return;
-      }
-
-      setHeight(elt.clientHeight ?? "auto");
-    },
-    [setHeight]
-  );
-  const ref = useResizeObserver(onResize);
-
-  useEffect(() => {
-    if (!service.expanded) {
-      setHeight(0);
-    }
-  }, [service.expanded]);
-
   const renderTabs = (service: ClientService): JSX.Element => {
     return match(service)
       .with({ config: { type: "web" } }, (svc) => (
@@ -176,21 +153,39 @@ const ServiceContainer: React.FC<ServiceProps> = ({
           </ActionButton>
         )}
       </ServiceHeader>
-      <AnimateHeight
-        height={height}
-        contentRef={ref}
-        contentClassName="auto-content"
-        duration={300}
-      >
-        {height !== 0 && (
+      <AnimatePresence>
+        {service.expanded && (
           <StyledSourceBox
+            key={service.name.value}
+            initial={{
+              height: 0,
+            }}
+            animate={{
+              height: "auto",
+              transition: {
+                duration: 0.3,
+              },
+            }}
+            exit={{
+              height: 0,
+              transition: {
+                duration: 0.3,
+              },
+            }}
             showExpanded={service.expanded}
             hasFooter={status != null}
           >
-            {renderTabs(service)}
+            <div
+              style={{
+                padding: "14px 25px 30px",
+                border: "1px solid #494b4f",
+              }}
+            >
+              {renderTabs(service)}
+            </div>
           </StyledSourceBox>
         )}
-      </AnimateHeight>
+      </AnimatePresence>
       {status && (
         <ServiceStatusFooter
           serviceName={service.name.value}
@@ -210,17 +205,14 @@ const ServiceTitle = styled.div`
   align-items: center;
 `;
 
-const StyledSourceBox = styled.div<{
+const StyledSourceBox = styled(motion.div)<{
   showExpanded?: boolean;
   hasFooter?: boolean;
 }>`
-  width: 100%;
+  overflow: hidden;
   color: #ffffff;
-  padding: 14px 25px 30px;
-  position: relative;
   font-size: 13px;
   background: ${(props) => props.theme.fg};
-  border: 1px solid #494b4f;
   border-top: 0;
   border-bottom-left-radius: ${(props) => (props.hasFooter ? "0" : "5px")};
   border-bottom-right-radius: ${(props) => (props.hasFooter ? "0" : "5px")};
@@ -276,7 +268,7 @@ const ServiceHeader = styled.div<{
     border-radius: 20px;
     margin-left: -10px;
     transform: ${(props: { showExpanded?: boolean }) =>
-    props.showExpanded ? "" : "rotate(-90deg)"};
+      props.showExpanded ? "" : "rotate(-90deg)"};
   }
 `;
 

+ 7 - 2
dashboard/webpack.config.js

@@ -5,8 +5,8 @@ const ReactRefreshWebpackPlugin = require("@pmmmwh/react-refresh-webpack-plugin"
 
 const dotenv = require("dotenv");
 
-const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
-  .BundleAnalyzerPlugin;
+const BundleAnalyzerPlugin =
+  require("webpack-bundle-analyzer").BundleAnalyzerPlugin;
 
 const TerserPlugin = require("terser-webpack-plugin");
 
@@ -87,6 +87,11 @@ module.exports = () => {
             },
           ],
         },
+        {
+          test: /\.mjs/,
+          include: /node_modules/,
+          type: "javascript/auto",
+        },
         {
           enforce: "pre",
           test: /\.js$/,