diff --git a/app/logo/page.tsx b/app/logo/page.tsx deleted file mode 100644 index 24e1259..0000000 --- a/app/logo/page.tsx +++ /dev/null @@ -1,77 +0,0 @@ -'use client' -import { useEffect, useState } from "react"; -import { DefaultColors } from "tailwindcss/types/generated/colors"; - -const LOOPING_ENABLED_ON_SECOND_LOGO = true; -const SHIFT_INTERVAL = 3000; - -export default function LogoPage() { - const [circleColors, setCircleColors] = useState<{ [key: string]: typeof colorList[number] | "" }>({ - firstColor: "", - secondColor: "", - thirdColor: "", - }) - - const colorList: (`bg-${keyof DefaultColors}` | `bg-${keyof DefaultColors}-${string}`)[] = [ - "bg-purple-400", - "bg-purple-700", - "bg-sky-400", - "bg-sky-700", - "bg-blue-400", - "bg-pink-400", - "bg-pink-700", - ]; - - function handleHover() { - const firstColor = colorList[Math.floor(Math.random() * colorList.length | 0)] - const secondColor = colorList[Math.floor(Math.random() * colorList.length | 0)] - const thirdColor = colorList[Math.floor(Math.random() * colorList.length | 0)] - - setCircleColors({ firstColor, secondColor, thirdColor }); - } - - useEffect(handleHover, []); - - useEffect(() => { - if (LOOPING_ENABLED_ON_SECOND_LOGO) { - const interval = setInterval(() => { - handleHover(); - }, SHIFT_INTERVAL); - - return () => clearInterval(interval); - } - }, []) - - return ( -
-

Logo

- -
-
-

M

-
-
-

C

-
-
-

D

-
-
- -
-
-

M

-
- -
-

C

-
- -
-

D

-
-
- -
- ) -} diff --git a/components/Navbar.tsx b/components/Navbar.tsx deleted file mode 100644 index 5f527f3..0000000 --- a/components/Navbar.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import Link from 'next/link' -import { InlineLogo } from './logo' - -export default function Navbar() { - return ( - - ) -} diff --git a/components/Navbar/index.tsx b/components/Navbar/index.tsx new file mode 100644 index 0000000..75a0be7 --- /dev/null +++ b/components/Navbar/index.tsx @@ -0,0 +1,94 @@ +import Link from 'next/link' +import { InlineLogo, useColorShift } from '../logo' +import { useEffect, useState } from 'react'; +import { UseColorShiftReturnType } from '../logo/useColorShift'; + +interface HoverState { + about: boolean + projects: boolean + contact: boolean +} + +const SHIFT_INTERVAL = 3000; + +export default function Navbar() { + const navbarColorShift = useColorShift(SHIFT_INTERVAL); + const { shift } = navbarColorShift; + + const [colors, setColors] = useState>({ + firstColor: 'bg-inherit', + secondColor: 'bg-inherit', + thirdColor: 'bg-inherit', + }); + const [hoverState, setHoverState] = useState({ + about: false, + projects: false, + contact: false, + }) + + function mouseOver(source: keyof HoverState) { + const { colorKeys, actualColorReferences, activeIndex } = identifyActiveButton(); + + setColors({ ...colors, [colorKeys[activeIndex]]: actualColorReferences[activeIndex] }); + setHoverState({ ...hoverState, [source]: true }) + } + + function mouseOut(source: keyof HoverState) { + setHoverState({ ...hoverState, [source]: false }) + setColors({ firstColor: 'bg-inherit', secondColor: 'bg-inherit', thirdColor: 'bg-inherit' }); + } + + function identifyActiveButton() { + const buttonKeys: (keyof HoverState)[] = ['about', 'projects', 'contact']; + const { firstColor, secondColor, thirdColor } = navbarColorShift; + const colorKeys = ['firstColor', 'secondColor', 'thirdColor']; + const actualColorReferences = [firstColor, secondColor, thirdColor]; + + const activeButton = buttonKeys.find(key => hoverState[key]); + const activeIndex = buttonKeys.indexOf(activeButton as keyof HoverState); + + return { colorKeys, actualColorReferences, activeIndex }; + } + + useEffect(() => { + const interval = setInterval(shift, SHIFT_INTERVAL); + return () => clearInterval(interval); + }, []) + + useEffect(() => { + const interval = setInterval(() => { + const { colorKeys, actualColorReferences, activeIndex } = identifyActiveButton(); + + for (const key in hoverState) { + if (hoverState[key as keyof HoverState]) { + setColors({ + ...colors, + [colorKeys[activeIndex]]: actualColorReferences[activeIndex] + }); + } + } + }, 1000); + + return () => clearInterval(interval); + }, [shift]) + + return ( + + ) +} diff --git a/components/logo/index.tsx b/components/logo/index.tsx index bc56625..f444eda 100644 --- a/components/logo/index.tsx +++ b/components/logo/index.tsx @@ -1,6 +1,6 @@ 'use client' import { FC } from "react"; -import useColorShift, { type ColorListType } from "./useColorShift"; +import useColorShift, { UseColorShiftReturnType, type ColorListType } from "./useColorShift"; import { useRouter } from "next/navigation"; export { default as useColorShift } from "./useColorShift"; @@ -10,33 +10,34 @@ interface LogoProps { shiftInterval?: number, customColorList?: ColorListType[], disableShift?: boolean, + customHookInstance?: UseColorShiftReturnType } -export const StackedLogo: FC = ({ shiftInterval, customColorList, disableShift = false }) => { +export const StackedLogo: FC = ({ shiftInterval, customColorList, customHookInstance, disableShift = false }) => { const hookProps = [ shiftInterval ?? DEFAULT_SHIFT_INTERVAL, disableShift, customColorList, ] as const; - const { firstColor, secondColor, thirdColor, handleHover } = useColorShift(...hookProps); + const { firstColor, secondColor, thirdColor, shift } = useColorShift(...hookProps); return (
-
+

M

-
+

C

-
+

D

) } -export const InlineLogo: FC = ({ shiftInterval, customColorList, disableShift = false }) => { +export const InlineLogo: FC = ({ shiftInterval, customColorList, customHookInstance, disableShift = false }) => { const router = useRouter(); const hookProps = [ @@ -45,19 +46,35 @@ export const InlineLogo: FC = ({ shiftInterval, customColorList, disa customColorList, ] as const; - const { firstColor, secondColor, thirdColor, handleHover } = useColorShift(...hookProps); + const { firstColor, secondColor, thirdColor, shift } = useColorShift(...hookProps); - return ( + if (customHookInstance) return ( + ) + + return ( + diff --git a/components/logo/useColorShift.tsx b/components/logo/useColorShift.tsx index d289c3f..aa76e1f 100644 --- a/components/logo/useColorShift.tsx +++ b/components/logo/useColorShift.tsx @@ -1,57 +1,63 @@ import { useEffect, useState } from "react"; import { DefaultColors } from "tailwindcss/types/generated/colors"; -export type ColorListType = (`bg-${keyof DefaultColors}` | `bg-${keyof DefaultColors}-${string}`); +export type ColorListType = (`bg-${keyof DefaultColors}` | `bg-${keyof DefaultColors}-${string}` | ""); const colorList: ColorListType[] = [ - "bg-purple-400", - "bg-purple-700", - "bg-sky-400", - "bg-sky-700", - "bg-blue-400", - "bg-pink-400", - "bg-pink-700", + "bg-purple-500", + "bg-purple-800", + "bg-sky-500", + "bg-sky-800", + "bg-blue-500", + "bg-pink-500", + "bg-pink-800", ]; -const useColorShift = (shiftInterval: number, disableShift = false, customColorList?: ColorListType[]): { - firstColor: ColorListType | "", - secondColor: ColorListType | "", - thirdColor: ColorListType | "", - handleHover: () => void, -} => { - if (shiftInterval <= 0) throw new Error("shiftInterval must be greater than 0") +export interface UseColorShiftReturnType { + firstColor: ColorListType + secondColor: ColorListType + thirdColor: ColorListType + shift: () => { firstColor: ColorListType, secondColor: ColorListType, thirdColor: ColorListType } + shiftInterval: number | undefined +} + +const useColorShift = (shiftInterval?: number, disableShift = false, customColorList?: ColorListType[]): UseColorShiftReturnType => { + if (shiftInterval && shiftInterval <= 0) throw new Error("shiftInterval must be greater than 0") + + const randomColor = () => (customColorList ?? colorList)[Math.floor(Math.random() * colorList.length | 0)]; const [circleColors, setCircleColors] = useState<{ firstColor: ColorListType | "", secondColor: ColorListType | "", thirdColor: ColorListType | "", }>({ - firstColor: "", - secondColor: "", - thirdColor: "", + firstColor: colorList[0], + secondColor: colorList[1], + thirdColor: colorList[2], }) - function handleHover() { - const firstColor = colorList[Math.floor(Math.random() * colorList.length | 0)] - const secondColor = colorList[Math.floor(Math.random() * colorList.length | 0)] - const thirdColor = colorList[Math.floor(Math.random() * colorList.length | 0)] + function shift() { + const firstColor = randomColor(); + const secondColor = randomColor(); + const thirdColor = randomColor(); setCircleColors({ firstColor, secondColor, thirdColor }); + return { firstColor, secondColor, thirdColor }; } // perform initial mount of color changing pattern - useEffect(disableShift ? handleHover : (() => { return }), []); + useEffect(disableShift ? shift : (() => { return }), []); // set this function to repeat useEffect(() => { const interval = setInterval(() => { - handleHover(); - }, shiftInterval); + shift(); + }, shiftInterval ?? 3000); return () => clearInterval(interval); }, []) - return { ...circleColors, handleHover }; + return { ...circleColors, shift, shiftInterval }; } export default useColorShift