diff --git a/package.json b/package.json index c656f26..f05fbf9 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "@babel/preset-react": "^7.18.6", "@babel/preset-typescript": "^7.21.4", "@types/jest": "^29.5.0", - "@types/react": "^18.0.27", + "@types/react": "^18.2.51", "@types/react-dom": "^18.0.10", "@types/react-test-renderer": "^18.0.0", "@vitejs/plugin-react": "^3.1.0", diff --git a/src/App.tsx b/src/App.tsx index 8b85226..55607a2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,10 +2,10 @@ import { createBrowserRouter, RouterProvider, } from "react-router-dom"; - -// routes +import Test from "./routes/Test"; +import DropdownItem from "./components/DropdownItem"; +import SortDropdownListTestRoute from "./routes/SortDropdownListTestRoute"; import NavigaionTest from "./routes/NavigationTest"; -import Test from "@/routes/Test"; const router = createBrowserRouter([ { @@ -16,10 +16,15 @@ const router = createBrowserRouter([ path: "/test", element: , }, + { + path: "/SortDropdownListTestRoute", + element: , + }, { path: "/nav-test", element: , }, + ]); function App() { diff --git a/src/components/DropdownItem.tsx b/src/components/DropdownItem.tsx new file mode 100644 index 0000000..d740fe4 --- /dev/null +++ b/src/components/DropdownItem.tsx @@ -0,0 +1,18 @@ +// As shown in TestSquareProps +export interface DropdownItemProps { + text: string; + isSelected: boolean; + onSelect: () => void; +} + +function DropdownItem({ text, isSelected, onSelect }:DropdownItemProps) { + return ( +
  • + + {text} +
  • + ); +} + +export default DropdownItem; diff --git a/src/components/SortDropdownList.tsx b/src/components/SortDropdownList.tsx new file mode 100644 index 0000000..575d421 --- /dev/null +++ b/src/components/SortDropdownList.tsx @@ -0,0 +1,82 @@ +import { useEffect, useRef, useState } from "react"; +import DropdownItem from "./DropdownItem"; +import { CaretDown } from "@phosphor-icons/react"; + +function SortDropdownList() { + // Options that can be later add in + const items = [ + "Newest to Oldest", + "Oldest to Newest", + "Most-Least Storage", + "Recently Updated", + ]; + + // State to keep track of the currently selected option + const [selectedItem, setSelectedItem] = useState( + null + ); // useState expect either string or null var + + // State to keep track of the menu is being open or not + const [open, setOpen] = useState(false); + + // Check if user click outside of the menu to close it + let menuRef = useRef(null); // Typescript like this + + useEffect(() => { + let handler = (e: any) => { + if (menuRef.current && !menuRef.current.contains(e.target)) { + // Check menuRef.current is not null before calling .contains + setOpen(false); + } + }; + + document.addEventListener("mousedown", handler); + + return () => { + // Clean up to prevent memory leaks and avoid running outdated event handlers + document.removeEventListener("mousedown", handler); + }; + }, []); + + return ( +
    + {/* For the menu trigger */} +
    setOpen(!open)} + > + Sort + {/* The arrow symbol */} + +
    + + {/* For the dropdown options */} +
    +
    +
      + {items.map((item, index) => ( + setSelectedItem(item)} // set the selectedItem to that option and when it re-render it will be check by the line above + /> + ))} +
    + {/* for fun */} + +
    +
    +
    + ); +} + +export default SortDropdownList; diff --git a/src/routes/SortDropdownListTestRoute.tsx b/src/routes/SortDropdownListTestRoute.tsx new file mode 100644 index 0000000..6d359ea --- /dev/null +++ b/src/routes/SortDropdownListTestRoute.tsx @@ -0,0 +1,19 @@ +import DropdownItem from "../components/DropdownItem"; +import SortDropdownList from "../components/SortDropdownList"; + +function SortDropdownListTestRoute() { + return ( +
    +
    Hello
    +
    + Is this the sort dropdown list that you looking for?😩 +
    +
    + +
    +
    What happen If I do this?
    +
    + ); +} + +export default SortDropdownListTestRoute;