Animated menu icons

This commit is contained in:
Vladyslav Matsiiako
2023-04-27 18:44:23 -07:00
parent 4ac13f61e0
commit 3b94ee42e9
9 changed files with 9048 additions and 9710 deletions
+8992 -9679
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -51,6 +51,7 @@
"classnames": "^2.3.1", "classnames": "^2.3.1",
"cookies": "^0.8.0", "cookies": "^0.8.0",
"cva": "npm:class-variance-authority@^0.4.0", "cva": "npm:class-variance-authority@^0.4.0",
"framer-motion": "^6.2.3",
"fs": "^0.0.1-security", "fs": "^0.0.1-security",
"gray-matter": "^4.0.3", "gray-matter": "^4.0.3",
"http-proxy": "^1.18.1", "http-proxy": "^1.18.1",
@@ -58,6 +59,7 @@
"infisical-node": "^1.0.37", "infisical-node": "^1.0.37",
"jspdf": "^2.5.1", "jspdf": "^2.5.1",
"jsrp": "^0.2.4", "jsrp": "^0.2.4",
"lottie-react": "^2.4.0",
"markdown-it": "^13.0.1", "markdown-it": "^13.0.1",
"next": "^12.3.4", "next": "^12.3.4",
"next-i18next": "^13.0.2", "next-i18next": "^13.0.2",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+43 -19
View File
@@ -1,4 +1,8 @@
import { ComponentPropsWithRef, ElementType, ReactNode, Ref } from 'react'; /* eslint-disable import/no-extraneous-dependencies */
/* eslint-disable global-require */
import { ComponentPropsWithRef, ElementType, ReactNode, Ref, useRef } from 'react';
import { motion } from 'framer-motion'
import Lottie from 'lottie-react'
import { twMerge } from 'tailwind-merge'; import { twMerge } from 'tailwind-merge';
export type MenuProps = { export type MenuProps = {
@@ -14,7 +18,7 @@ export type MenuItemProps<T extends ElementType> = {
// Kudos to https://itnext.io/react-polymorphic-components-with-typescript-f7ce72ea7af2 // Kudos to https://itnext.io/react-polymorphic-components-with-typescript-f7ce72ea7af2
as?: T; as?: T;
children: ReactNode; children: ReactNode;
icon?: ReactNode; icon?: string;
description?: ReactNode; description?: ReactNode;
isDisabled?: boolean; isDisabled?: boolean;
isSelected?: boolean; isSelected?: boolean;
@@ -33,23 +37,43 @@ export const MenuItem = <T extends ElementType = 'button'>({
// wrapping in forward ref with generic component causes the loss of ts definitions on props // wrapping in forward ref with generic component causes the loss of ts definitions on props
inputRef, inputRef,
...props ...props
}: MenuItemProps<T> & ComponentPropsWithRef<T>): JSX.Element => ( }: MenuItemProps<T> & ComponentPropsWithRef<T>): JSX.Element => {
<li const iconRef = useRef()
className={twMerge(
'px-1 py-2.5 mt-0.5 font-inter flex flex-col text-sm text-bunker-100 transition-all rounded cursor-pointer hover:bg-mineshaft-600 duration-50', return(
isSelected && 'bg-mineshaft-500', <a
isDisabled && 'hover:bg-transparent cursor-not-allowed', onMouseEnter={() => iconRef.current?.play()}
className onMouseLeave={() => iconRef.current?.stop()}
)} >
> <li
<Item type="button" role="menuitem" className="flex items-center relative" ref={inputRef} {...props}> className={twMerge(
<div className={`${isSelected ? "visisble" : "invisible"} absolute w-[0.25rem] rounded-md h-8 bg-primary`}/> 'group px-1 py-2.5 mt-0.5 font-inter flex flex-col text-sm text-bunker-100 transition-all rounded cursor-pointer hover:bg-mineshaft-700 duration-50',
{icon && <span className="mr-3 ml-4 w-5">{icon}</span>} isSelected && 'bg-mineshaft-600 hover:bg-mineshaft-600',
<span className="flex-grow text-left">{children}</span> isDisabled && 'hover:bg-transparent cursor-not-allowed',
</Item> className
{description && <span className="mt-2 text-xs">{description}</span>} )}
</li> >
); <motion.span className="w-full flex flex-row items-center justify-start rounded-sm">
<Item type="button" role="menuitem" className="flex items-center relative" ref={inputRef} {...props}>
<div className={`${isSelected ? "visisble" : "invisible"} absolute w-[0.25rem] rounded-md h-8 bg-primary`}/>
{/* {icon && <span className="mr-3 ml-4 w-5 block group-hover:hidden">{icon}</span>} */}
<Lottie
lottieRef={iconRef}
style={{ width: 24, height: 24 }}
// eslint-disable-next-line import/no-dynamic-require
animationData={require(`../../../../public/lotties/${icon}.json`)}
loop={false}
autoplay={false}
className="my-auto ml-3 mr-3"
/>
<span className="flex-grow text-left">{children}</span>
</Item>
{description && <span className="mt-2 text-xs">{description}</span>}
</motion.span>
</li>
</a>
)
};
MenuItem.displayName = 'MenuItem'; MenuItem.displayName = 'MenuItem';
+6 -12
View File
@@ -10,13 +10,8 @@ import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next'; import { useTranslation } from 'next-i18next';
import { import {
faBookOpen, faBookOpen,
faFileLines,
faGear,
faKey,
faMobile, faMobile,
faPlug,
faPlus, faPlus,
faUser
} from '@fortawesome/free-solid-svg-icons'; } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { yupResolver } from '@hookform/resolvers/yup'; import { yupResolver } from '@hookform/resolvers/yup';
@@ -309,7 +304,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
<a> <a>
<MenuItem <MenuItem
isSelected={router.asPath.includes(`/dashboard/${currentWorkspace?._id}`)} isSelected={router.asPath.includes(`/dashboard/${currentWorkspace?._id}`)}
icon={<FontAwesomeIcon icon={faKey} size="lg" />} icon="system-outline-90-lock-closed"
> >
{t('nav:menu.secrets')} {t('nav:menu.secrets')}
</MenuItem> </MenuItem>
@@ -319,7 +314,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
<a> <a>
<MenuItem <MenuItem
isSelected={router.asPath === `/users/${currentWorkspace?._id}`} isSelected={router.asPath === `/users/${currentWorkspace?._id}`}
icon={<FontAwesomeIcon icon={faUser} size="lg" />} icon="system-outline-96-groups"
> >
{t('nav:menu.members')} {t('nav:menu.members')}
</MenuItem> </MenuItem>
@@ -329,21 +324,20 @@ export const AppLayout = ({ children }: LayoutProps) => {
<a> <a>
<MenuItem <MenuItem
isSelected={router.asPath === `/integrations/${currentWorkspace?._id}`} isSelected={router.asPath === `/integrations/${currentWorkspace?._id}`}
icon={<FontAwesomeIcon icon={faPlug} size="lg" />} icon="system-outline-82-extension"
> >
{t('nav:menu.integrations')} {t('nav:menu.integrations')}
</MenuItem> </MenuItem>
</a> </a>
</Link> </Link>
<Link href={`/activity/${currentWorkspace?._id}`} passHref> <Link href={`/activity/${currentWorkspace?._id}`} passHref>
<a>
<MenuItem <MenuItem
isSelected={router.asPath === `/activity/${currentWorkspace?._id}`} isSelected={router.asPath === `/activity/${currentWorkspace?._id}`}
icon={<FontAwesomeIcon icon={faFileLines} size="lg" />} // icon={<FontAwesomeIcon icon={faFileLines} size="lg" />}
icon="system-outline-168-view-headline"
> >
Audit Logs Audit Logs
</MenuItem> </MenuItem>
</a>
</Link> </Link>
<Link href={`/settings/project/${currentWorkspace?._id}`} passHref> <Link href={`/settings/project/${currentWorkspace?._id}`} passHref>
<a> <a>
@@ -351,7 +345,7 @@ export const AppLayout = ({ children }: LayoutProps) => {
isSelected={ isSelected={
router.asPath === `/settings/project/${currentWorkspace?._id}` router.asPath === `/settings/project/${currentWorkspace?._id}`
} }
icon={<FontAwesomeIcon icon={faGear} size="lg" />} icon="system-outline-109-slider-toggle-settings"
> >
{t('nav:menu.project-settings')} {t('nav:menu.project-settings')}
</MenuItem> </MenuItem>