From 8972268fae6961a49279e36c84869e4c54fe3142 Mon Sep 17 00:00:00 2001 From: rojonaitor Date: Wed, 3 Jan 2024 19:42:34 -0600 Subject: [PATCH] feat: animation menu, select, create/edit modal --- package-lock.json | 39 +++ package.json | 1 + src/app/cubes/page.tsx | 3 +- src/components/cubes/ModalCreate.tsx | 12 +- src/components/menu-settings/Menu.tsx | 297 +++++++++++---------- src/components/select/SelectOptionList.tsx | 19 +- 6 files changed, 225 insertions(+), 146 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5dbb1744..757d8df8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "eslint": "8.49.0", "eslint-config-next": "13.4.19", "fast-sort": "3.4.0", + "framer-motion": "^10.17.4", "lightweight-charts": "^4.1.0", "next": "13.5.1", "postcss": "8.4.31", @@ -67,6 +68,21 @@ "node": ">=6.9.0" } }, + "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/@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/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2248,6 +2264,29 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/framer-motion": { + "version": "10.17.4", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.17.4.tgz", + "integrity": "sha512-CYBSs6cWfzcasAX8aofgKFZootmkQtR4qxbfTOksBLny/lbUfkGbQAFOS3qnl6Uau1N9y8tUpI7mVIrHgkFjLQ==", + "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/fs-constants": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", diff --git a/package.json b/package.json index 8a2db96e..fc5a8ae8 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "eslint": "8.49.0", "eslint-config-next": "13.4.19", "fast-sort": "3.4.0", + "framer-motion": "^10.17.4", "lightweight-charts": "^4.1.0", "next": "13.5.1", "postcss": "8.4.31", diff --git a/src/app/cubes/page.tsx b/src/app/cubes/page.tsx index 4775ccdd..64755096 100644 --- a/src/app/cubes/page.tsx +++ b/src/app/cubes/page.tsx @@ -9,6 +9,7 @@ import { CubesContent } from "@/components/cubes/CubesContent"; import { OverallHeader } from "@/components/OverallHeader"; import { OptionsContainer } from "@/components/cubes/OptionsContainer"; import { useCubes } from "@/hooks/useCubes"; +import { AnimatePresence } from "framer-motion"; export default function CubesPage() { const { filterCubes, modalOpen, setModalOpen, lang, handleSearchFilter } = @@ -34,7 +35,7 @@ export default function CubesPage() { - {modalOpen && } + {modalOpen && } ); diff --git a/src/components/cubes/ModalCreate.tsx b/src/components/cubes/ModalCreate.tsx index cbb14139..24796136 100644 --- a/src/components/cubes/ModalCreate.tsx +++ b/src/components/cubes/ModalCreate.tsx @@ -7,6 +7,7 @@ import useModalCube from "@/hooks/useModalCube"; import { useCubesModalStore } from "@/store/CubesModalStore"; import DeleteModal from "@/components/cubes/DeleteModal"; import CloseModal from "@/icons/CloseModal"; +import { motion } from "framer-motion"; export default function ModalCreate() { const { editingCube } = useCubesModalStore(); @@ -33,14 +34,19 @@ export default function ModalCreate() { id="defaultModal" tabIndex={2} aria-hidden={false} - className={`fixed bg-opacity-75 bg-black top-0 left-0 z-50 w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-screen flex flex-col items-center`} + className={`absolute bg-opacity-10 bg-black top-0 left-0 z-50 w-full p-4 overflow-x-hidden overflow-y-auto md:inset-0 h-screen flex flex-col items-center`} onClick={(e) => { if (e.target === e.currentTarget) handleCloseModal(); }} >
{/* */} -
+ {/* */}

@@ -140,7 +146,7 @@ export default function ModalCreate() { : translation.inputs["create"][lang]}

-
+
{showDeleteConfirmation && ( diff --git a/src/components/menu-settings/Menu.tsx b/src/components/menu-settings/Menu.tsx index f2983ee5..a22b1506 100644 --- a/src/components/menu-settings/Menu.tsx +++ b/src/components/menu-settings/Menu.tsx @@ -20,6 +20,7 @@ import Shield from "@/icons/Shield"; import Link from "next/link"; import useEscape from "@/hooks/useEscape"; import Image from "next/image"; +import { AnimatePresence, motion } from "framer-motion"; export default function MenuSettings() { const { settingsOpen, setSettingsOpen, settings, setSettings, lang } = @@ -34,152 +35,174 @@ export default function MenuSettings() { useEscape(() => setSettingsOpen(false)); - return settingsOpen && !isSolving ? ( + return ( <> -
-
-
- setSettingsOpen(false)} - className="flex items-center cursor-pointer ms-3" + + {settingsOpen && !isSolving ? ( +
+ - - -
- {translation.settings["settings"][lang]} -
-
- - } - title={translation.settings["locale"][lang]} - > -
-
- {translation.settings["language"][lang]} -
-
- + + +
+ {translation.settings["settings"][lang]} +
-
-
- } - title={translation.settings["timer"][lang]} - > - {Object.values(settings.timer).map((item) => ( - - ))} - - } - title={translation.settings["features"][lang]} - > - {Object.values(settings.features).map((item) => ( - - ))} - + } + title={translation.settings["locale"][lang]} + > +
+
+ {translation.settings["language"][lang]} +
+
+ +
+
+
+ } + title={translation.settings["timer"][lang]} + > + {Object.values(settings.timer).map((item) => ( + + ))} + - } - title={translation.settings["alerts"][lang]} - > - {Object.values(settings.alerts).map((item) => ( - - ))} - + } + title={translation.settings["features"][lang]} + > + {Object.values(settings.features).map((item) => ( + + ))} + - } - title={translation.settings["theme"][lang]} - > - - + } + title={translation.settings["alerts"][lang]} + > + {Object.values(settings.alerts).map((item) => ( + + ))} + - } - title={translation.settings["data"][lang]} - > - - - } - title={translation.settings["about"][lang]} - > -
- logo + } + title={translation.settings["theme"][lang]} + > + + -
- ”{translation.settings["legend"][lang]}” -
+ } + title={translation.settings["data"][lang]} + > + + + } + title={translation.settings["about"][lang]} + > +
+ logo -
- - {translation.settings["suggest"][lang]} - - - {translation.settings["report-bug"][lang]} - -
-
-
-
- {/* Area to the right -> Its a transparent layer next to menu */} - { - setSettingsOpen(false); - }} - className="sm:grow cursor-default" - > -
+
+ ”{translation.settings["legend"][lang]}” +
+ +
+ + {translation.settings["suggest"][lang]} + + + {translation.settings["report-bug"][lang]} + +
+
+ + + {/* Area to the right -> Its a transparent layer next to menu */} + { + setSettingsOpen(false); + }} + className="sm:grow cursor-default" + > +
+ ) : null} + - ) : null; + ); } diff --git a/src/components/select/SelectOptionList.tsx b/src/components/select/SelectOptionList.tsx index 61efb559..64c5220a 100644 --- a/src/components/select/SelectOptionList.tsx +++ b/src/components/select/SelectOptionList.tsx @@ -1,3 +1,5 @@ +import { AnimatePresence, motion } from "framer-motion"; + interface SelectOptionList { isOpen: boolean; children: React.ReactNode; @@ -6,11 +8,18 @@ interface SelectOptionList { export function SelectOptionList({ isOpen, children }: SelectOptionList) { return ( <> - {isOpen ? ( -
- {children} -
- ) : null} + + {isOpen ? ( + + {children} + + ) : null} + ); }