Skip to content

Commit

Permalink
Create a mobile sidebar component
Browse files Browse the repository at this point in the history
  • Loading branch information
aidoskanapyanov committed Jul 2, 2023
1 parent 819eff3 commit 2353677
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 1 deletion.
2 changes: 2 additions & 0 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,11 @@
"preview": "vite preview"
},
"dependencies": {
"clsx": "^1.2.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.13.0",
"tailwind-merge": "^1.13.2",
"vite-tsconfig-paths": "^4.2.0"
},
"devDependencies": {
Expand Down
5 changes: 4 additions & 1 deletion frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { BrowserRouter } from "react-router-dom";
import { SidebarMobile } from "./components/SidebarMobile";

function App() {
return (
<BrowserRouter>
<div>Hello, World!</div>
<div className="p-4">
<SidebarMobile />
</div>
</BrowserRouter>
);
}
Expand Down
58 changes: 58 additions & 0 deletions frontend/src/components/SidebarMobile.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { cn } from "@/lib/utils";
import * as React from "react";

interface Props {
children?: React.ReactNode;
}

function useCloseOnOutsideTouch(ref: any, setIsOpen: any) {
React.useEffect(() => {
/**
* Alert if clicked on outside of element
*/
function handleClickOutside(event: any) {
if (ref.current && !ref.current.contains(event.target)) {
setIsOpen(false);
}
}
// Bind the event listener
document.addEventListener("mousedown", handleClickOutside);
return () => {
// Unbind the event listener on clean up
document.removeEventListener("mousedown", handleClickOutside);
};
}, [ref, setIsOpen]);
}

function SidebarToggle(props) {
return (
<button
className="border-2 p-2 rounded-lg mb-4 block"
onClick={() => props.setIsOpen(props.open ? true : false)}
>
{props.open ? "open" : "close"}
</button>
);
}

export const SidebarMobile = ({ children }: Props) => {
const [isOpen, setIsOpen] = React.useState(false);
const wrapperRef = React.useRef(null);
useCloseOnOutsideTouch(wrapperRef, setIsOpen);

return (
<div className="block sm:hidden">
<SidebarToggle setIsOpen={setIsOpen} open={true}></SidebarToggle>
<div
className={cn(
"bg-slate-600 w-60 absolute inset-0 p-4 transition ease-in-out duration-200",
isOpen ? "transform translate-x-0" : "transform -translate-x-full"
)}
ref={wrapperRef}
>
<SidebarToggle setIsOpen={setIsOpen}></SidebarToggle>
{children ? children : "SidebarMobile"}
</div>
</div>
);
};
1 change: 1 addition & 0 deletions frontend/src/components/index.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as React from "react";

// component exports
export * from "./SidebarMobile";
6 changes: 6 additions & 0 deletions frontend/src/lib/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";

export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
15 changes: 15 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 2353677

Please sign in to comment.