diff --git a/app/components/Button.tsx b/app/components/Button.tsx index 81c69ce7e4..0b2b5d1996 100644 --- a/app/components/Button.tsx +++ b/app/components/Button.tsx @@ -1,41 +1,41 @@ import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { twMerge } from "tailwind-merge"; -export interface ButtonPropsI extends React.ButtonHTMLAttributes { - icon?: IconDefinition; - variant?: "primary"|"secondary"; +export interface ButtonPropsI + extends React.ButtonHTMLAttributes { + icon?: IconDefinition; + variant?: "primary" | "secondary"; } export const Button = ({ icon, children, - className : propsClassName, - variant = 'primary', + className: propsClassName, + variant = "primary", ...rest -}:ButtonPropsI)=>{ - function getVariantClassNames(variant: string){ - switch(variant){ - case "secondary":{ +}: ButtonPropsI) => { + function getVariantClassNames(variant: string) { + switch (variant) { + case "secondary": { return " bg-brand-secondary hover:bg-brand-secondary-900 text-white focus-visible:outline-brand-secondary"; } case "primary": - default:{ + default: { return " bg-brand-primary hover:bg-brand-primary-400 text-white focus-visible:outline-brand-primary-600"; } } - }; - const className = "text-sm font-semibold rounded-md px-3.5 py-2.5 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2" + getVariantClassNames(variant) - + (propsClassName ? ` ${propsClassName}` : ""); + } + const className = twMerge( + "text-sm font-semibold rounded-md px-3 py-2 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 transition-all duration-150", + getVariantClassNames(variant), + propsClassName, + ); - return( - ); -} \ No newline at end of file +}; diff --git a/app/components/ButtonIcon.tsx b/app/components/ButtonIcon.tsx index 08d271a1e9..2db55e172f 100644 --- a/app/components/ButtonIcon.tsx +++ b/app/components/ButtonIcon.tsx @@ -1,35 +1,28 @@ import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; -import { - FontAwesomeIcon, - FontAwesomeIconProps -} from "@fortawesome/react-fontawesome"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { twMerge } from "tailwind-merge"; - -export interface ButtonIconPropsI extends React.ButtonHTMLAttributes { - icon: IconDefinition; - iconClass?: string; - iconProps?: FontAwesomeIconProps +interface ButtonIconProps { + icon: IconDefinition; + fill?: boolean; + onClick: () => void; } export const ButtonIcon = ({ icon, - iconClass, - iconProps, - className : propsClassName, - ...rest -}:ButtonIconPropsI)=>{ - return( - ); -} \ No newline at end of file +}; diff --git a/app/components/ButtonIconSelect.tsx b/app/components/ButtonIconSelect.tsx new file mode 100644 index 0000000000..971e86c127 --- /dev/null +++ b/app/components/ButtonIconSelect.tsx @@ -0,0 +1,49 @@ +import { useState } from "react"; +import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { twMerge } from "tailwind-merge"; + +interface Option { + value: string; + icon: IconDefinition; +} + +interface ButtonIconSelectProps { + options: Option[]; + onOptionChange?: (value: string) => void; +} + +export function ButtonIconSelect({ + options, + onOptionChange, +}: ButtonIconSelectProps) { + const [selectedOption, setSelectedOption] = useState( + options[0].value, + ); + + const handleOptionChange = (value: string) => { + setSelectedOption(value); + if (onOptionChange) { + onOptionChange(value); + } + }; + + return ( +
+ {options.map(({ value, icon }) => ( + + ))} +
+ ); +} diff --git a/app/components/ButtonLink.tsx b/app/components/ButtonLink.tsx index f7e6fcfdc9..abd605e357 100644 --- a/app/components/ButtonLink.tsx +++ b/app/components/ButtonLink.tsx @@ -1,41 +1,44 @@ import { Link, LinkProps } from "@remix-run/react"; import { IconDefinition } from "@fortawesome/fontawesome-svg-core"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { twMerge } from "tailwind-merge"; interface LinkButtonProps extends LinkProps { icon?: IconDefinition; - variant?: "primary"|"secondary"; - } + variant?: "primary" | "secondary"; +} - export const ButtonLink = ({ +export const ButtonLink = ({ icon, children, className: propsClassName, variant = "primary", ...rest - }:LinkButtonProps)=>{ +}: LinkButtonProps) => { //TODO: Duplicated from Button.tsx - function getVariantClassNames(variant: string){ - switch(variant){ - case "secondary":{ - return " bg-brand-secondary hover:bg-brand-secondary-900 text-white focus-visible:outline-brand-secondary"; + function getVariantClassNames(variant: string) { + switch (variant) { + case "secondary": { + return "bg-brand-secondary hover:bg-brand-secondary-900 text-white focus-visible:outline-brand-secondary"; } case "primary": - default:{ - return " bg-brand-primary hover:bg-brand-primary-400 text-white focus-visible:outline-brand-primary-600"; + default: { + return "bg-brand-primary hover:bg-brand-primary-400 text-white focus-visible:outline-brand-primary-600"; } } - }; - const className = "text-sm font-semibold rounded-md px-3.5 py-2.5 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2" + getVariantClassNames(variant) - + (propsClassName ? ` ${propsClassName}` : ""); + } + const baseClassName = + "text-sm font-semibold rounded-md px-3 py-2 shadow-sm focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 transition-all duration-150"; + const variantClassNames = getVariantClassNames(variant); + const className = twMerge(baseClassName, variantClassNames, propsClassName); // END TODO - return( + return ( ); - } \ No newline at end of file +}; diff --git a/app/components/index.tsx b/app/components/index.tsx index 5ddffb4ded..10671425e4 100644 --- a/app/components/index.tsx +++ b/app/components/index.tsx @@ -1,9 +1,6 @@ import { Button } from "./Button"; import { ButtonIcon } from "./ButtonIcon"; import { ButtonLink } from "./ButtonLink"; +import { ButtonIconSelect } from "./ButtonIconSelect"; -export { - Button, - ButtonIcon, - ButtonLink, -}; +export { Button, ButtonIcon, ButtonLink, ButtonIconSelect }; diff --git a/app/modules/LowerPanel/LowerPanel.tsx b/app/modules/LowerPanel/LowerPanel.tsx index dd04237b5e..2b0573ba72 100644 --- a/app/modules/LowerPanel/LowerPanel.tsx +++ b/app/modules/LowerPanel/LowerPanel.tsx @@ -1,20 +1,20 @@ -import { useState } from 'react' +import { useState } from "react"; -interface LowerPanelPropsI{ +interface LowerPanelPropsI { children: React.ReactNode; } -export const LowerPanel =({ - children, -}:LowerPanelPropsI)=>{ - const [open, setOpen] = useState(false) - const handleOpen = ()=>{ +export const LowerPanel = ({ children }: LowerPanelPropsI) => { + const [open, setOpen] = useState(false); + const handleOpen = () => { setOpen(true); - } + }; - return (<> -
- {children} -
- ); -} \ No newline at end of file + return ( + <> +
+ {children} +
+ + ); +}; diff --git a/app/modules/SidePanel/SidePanel.tsx b/app/modules/SidePanel/SidePanel.tsx index 085700f34f..f89429c848 100644 --- a/app/modules/SidePanel/SidePanel.tsx +++ b/app/modules/SidePanel/SidePanel.tsx @@ -1,67 +1,53 @@ +import { useState } from "react"; +import { Tabs } from "../Tabs"; +import { Transition } from "@headlessui/react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { - Fragment, - useState -} from 'react' -import { Dialog, Transition } from '@headlessui/react' -import { - faGears, -} from '@fortawesome/pro-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; + faChevronLeft, + faChevronRight, +} from "@fortawesome/pro-solid-svg-icons"; -import { Button } from '~/components/Button'; +export const SidePanel = () => { + const [isVisible, setIsVisible] = useState(true); -import { SidePanelInner } from './SidePanelInner'; - -interface SidePanelPropsI{ - title?: string; - children: React.ReactNode; -} - -export const SidePanel =({ - title, - children, -}:SidePanelPropsI)=>{ - - const [open, setOpen] = useState(false); - const handleOpen = ()=> setOpen(true); - const handleClose = ()=>setOpen(false); - - return (<> - - - -
- -
-
-
- - - - {children} - - - -
-
-
-
-
- ); -} \ No newline at end of file + return ( +
+ + + Animation Tab

, + }, + { + header: "Camera", + children:

Camera Tab

, + }, + { + header: "Audio", + children:

Audio Tab

, + }, + { + header: "Styling", + children:

Styling Tab

, + }, + ]} + /> +
+
+ ); +}; diff --git a/app/modules/SidePanel/SidePanelInner.tsx b/app/modules/SidePanelOld/SidePanelInnerOld.tsx similarity index 58% rename from app/modules/SidePanel/SidePanelInner.tsx rename to app/modules/SidePanelOld/SidePanelInnerOld.tsx index 260f98f1c7..3112e81c5d 100644 --- a/app/modules/SidePanel/SidePanelInner.tsx +++ b/app/modules/SidePanelOld/SidePanelInnerOld.tsx @@ -1,35 +1,29 @@ -import { - useCallback, - useLayoutEffect, - useState -} from 'react'; -import { Dialog } from '@headlessui/react' +import { useCallback, useLayoutEffect, useState } from "react"; +import { Dialog } from "@headlessui/react"; -import { - faXmark, -} from '@fortawesome/pro-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { faXmark } from "@fortawesome/pro-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; -import { TOP_BAR_HEIGHT } from '~/constants'; +import { TOP_BAR_HEIGHT } from "~/constants"; export const SidePanelInner = ({ title, children, - closeCallback -}:{ + closeCallback, +}: { title?: string; children: React.ReactNode; - closeCallback: ()=>void; -})=>{ + closeCallback: () => void; +}) => { const [height, setHeight] = useState(0); - const handleWindowResize = useCallback(()=>{ - if(window){ - setHeight (Math.ceil(window.innerHeight * 3 / 4) - TOP_BAR_HEIGHT); + const handleWindowResize = useCallback(() => { + if (window) { + setHeight(Math.ceil((window.innerHeight * 3) / 4) - TOP_BAR_HEIGHT); } return 0; - },[]) + }, []); - useLayoutEffect(()=>{ + useLayoutEffect(() => { handleWindowResize(); window.addEventListener("resize", handleWindowResize); return () => { @@ -37,19 +31,19 @@ export const SidePanelInner = ({ }; }, [handleWindowResize]); - return( + return (
- {!title && } - {title && + {!title && } + {title && ( {title} - } + )}
-
- {children} -
+
{children}
); -} \ No newline at end of file +}; diff --git a/app/modules/SidePanelOld/SidePanelOld.tsx b/app/modules/SidePanelOld/SidePanelOld.tsx new file mode 100644 index 0000000000..b46e9841c7 --- /dev/null +++ b/app/modules/SidePanelOld/SidePanelOld.tsx @@ -0,0 +1,54 @@ +import { Fragment, useState } from "react"; +import { Dialog, Transition } from "@headlessui/react"; +import { faGears } from "@fortawesome/pro-solid-svg-icons"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; + +import { Button } from "~/components/Button"; + +import { SidePanelInner } from "./SidePanelInnerOld"; + +interface SidePanelPropsI { + title?: string; + children: React.ReactNode; +} + +export const SidePanel = ({ title, children }: SidePanelPropsI) => { + const [open, setOpen] = useState(false); + const handleOpen = () => setOpen(true); + const handleClose = () => setOpen(false); + + return ( + <> + + + +
+ +
+
+
+ + + + {children} + + + +
+
+
+
+
+ + ); +}; diff --git a/app/modules/SidePanelOld/index.tsx b/app/modules/SidePanelOld/index.tsx new file mode 100644 index 0000000000..5f4f8914f6 --- /dev/null +++ b/app/modules/SidePanelOld/index.tsx @@ -0,0 +1 @@ +export { SidePanel } from "./SidePanelOld"; diff --git a/app/modules/Tabs/Tabs.tsx b/app/modules/Tabs/Tabs.tsx index ba5a258bf6..321d038e04 100644 --- a/app/modules/Tabs/Tabs.tsx +++ b/app/modules/Tabs/Tabs.tsx @@ -1,55 +1,44 @@ -import { useState } from 'react' -import { Tab } from '@headlessui/react' +import { useState } from "react"; +import { Tab } from "@headlessui/react"; +import { twMerge } from "tailwind-merge"; -import { joinClassNames } from '~/helpers'; - -export type Tab = { +export type TabType = { header: string; children: JSX.Element; -} +}; -export const Tabs = ({ - tabs: tabProps -}:{ - tabs:Tab[] -}) =>{ - const [tabs, setTabs] = useState(tabProps); +export const Tabs = ({ tabs: tabProps }: { tabs: TabType[] }) => { + const [tabs] = useState(tabProps); + + const tabHeaderClassName = (selected: boolean) => + twMerge( + "px-4 py-4 text-md font-medium leading-5 focus:outline-none transition duration-150 ease-in-out border-b-[3px] border-white/[.1]", + selected + ? "text-white border-brand-primary" + : "text-white/[0.5] hover:text-white hover:border-white/[.3]", + ); return ( -
+
- + {tabs.map((tab, idx) => ( - joinClassNames( - 'w-full rounded-lg py-2.5 text-sm font-medium leading-5', - 'ring-white/60 ring-offset-2 ring-offset-blue-400 focus:outline-none focus:ring-2', - selected - ? 'bg-white text-blue-700 shadow' - : 'text-blue-100 hover:bg-white/[0.12] hover:text-white' - ) - } + className={({ selected }) => tabHeaderClassName(selected)} > {tab.header} ))} - + {tabs.map((tab, idx) => ( - + {tab.children} ))}
- ) -} \ No newline at end of file + ); +}; diff --git a/app/modules/TopBar/TopBar.tsx b/app/modules/TopBar/TopBar.tsx index 0e7b0bca10..bdccc86076 100644 --- a/app/modules/TopBar/TopBar.tsx +++ b/app/modules/TopBar/TopBar.tsx @@ -1,32 +1,52 @@ -import { useContext } from 'react'; +import { useContext } from "react"; -import { Button } from '~/components/Button' -import { faRightToBracket } from '@fortawesome/pro-solid-svg-icons' -import { TopBarInnerContext } from '~/contexts/TopBarInner'; +import { Button } from "~/components/Button"; +import { + faChevronLeft, + faRightToBracket, +} from "@fortawesome/pro-solid-svg-icons"; +import { TopBarInnerContext } from "~/contexts/TopBarInner"; +import { ButtonLink } from "~/components"; export const TopBar = () => { return ( -
-