chore: sidebar responsiveness.

This commit is contained in:
Prateek Shourya 2024-02-22 15:20:12 +05:30
parent 5ebd64d729
commit 496a2340c5
6 changed files with 87 additions and 18 deletions

View File

@ -8,6 +8,8 @@ import { observer } from "mobx-react-lite";
import { Breadcrumbs } from "@plane/ui"; import { Breadcrumbs } from "@plane/ui";
// icons // icons
import { Settings } from "lucide-react"; import { Settings } from "lucide-react";
// components
import { SidebarHamburgerToggle } from "components/sidebar/sidebar-menu-hamburger-toogle";
export const InstanceHeader: FC = observer(() => { export const InstanceHeader: FC = observer(() => {
const pathName = usePathname(); const pathName = usePathname();
@ -35,6 +37,7 @@ export const InstanceHeader: FC = observer(() => {
return ( return (
<div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-sidebar-border-200 bg-custom-sidebar-background-100 p-4"> <div className="relative z-10 flex h-[3.75rem] w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-sidebar-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap"> <div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle />
{title && ( {title && (
<div> <div>
<Breadcrumbs> <Breadcrumbs>
@ -42,7 +45,6 @@ export const InstanceHeader: FC = observer(() => {
type="text" type="text"
icon={<Settings className="h-4 w-4 text-custom-text-300" />} icon={<Settings className="h-4 w-4 text-custom-text-300" />}
label="Settings" label="Settings"
link="/"
/> />
<Breadcrumbs.BreadcrumbItem type="text" label={title} /> <Breadcrumbs.BreadcrumbItem type="text" label={title} />
</Breadcrumbs> </Breadcrumbs>

View File

@ -1,9 +1,10 @@
"use client"; "use client";
import { FC } from "react"; import { FC, useEffect, useRef } from "react";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
// hooks // hooks
import useAppTheme from "hooks/use-theme"; import useAppTheme from "hooks/use-theme";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
// components // components
import { HelpSection, SidebarMenu, SidebarDropdown } from "components/sidebar"; import { HelpSection, SidebarMenu, SidebarDropdown } from "components/sidebar";
@ -11,15 +12,42 @@ export interface IInstanceSidebar {}
export const InstanceSidebar: FC<IInstanceSidebar> = observer(() => { export const InstanceSidebar: FC<IInstanceSidebar> = observer(() => {
// store // store
const { sidebarCollapsed } = useAppTheme(); const themeStore = useAppTheme();
const ref = useRef<HTMLDivElement>(null);
useOutsideClickDetector(ref, () => {
if (themeStore.sidebarCollapsed === false) {
if (window.innerWidth < 768) {
themeStore.toggleSidebar();
}
}
});
useEffect(() => {
const handleResize = () => {
if (window.innerWidth <= 768) {
themeStore.toggleSidebar(true);
}
};
handleResize();
window.addEventListener("resize", handleResize);
return () => {
window.removeEventListener("resize", handleResize);
};
}, [themeStore]);
return ( return (
<div <div
className={`inset-y-0 z-20 flex h-full flex-shrink-0 flex-grow-0 flex-col border-r border-custom-sidebar-border-200 bg-custom-sidebar-background-100 duration-300 md:relative ${ className={`inset-y-0 z-20 flex h-full flex-shrink-0 flex-grow-0 flex-col border-r border-custom-sidebar-border-200 bg-custom-sidebar-background-100 duration-300
sidebarCollapsed ? "" : "md:w-[280px]" fixed md:relative
} ${sidebarCollapsed ? "left-0" : "-left-full md:left-0"}`} ${themeStore.sidebarCollapsed ? "-ml-[280px]" : ""}
sm:${themeStore.sidebarCollapsed ? "-ml-[280px]" : ""}
md:ml-0 ${themeStore.sidebarCollapsed ? "w-[80px]" : "w-[280px]"}
lg:ml-0 ${themeStore.sidebarCollapsed ? "w-[80px]" : "w-[280px]"}
`}
> >
<div className="flex h-full w-full flex-1 flex-col"> <div ref={ref} className="flex h-full w-full flex-1 flex-col">
<SidebarDropdown /> <SidebarDropdown />
<SidebarMenu /> <SidebarMenu />
<HelpSection /> <HelpSection />

View File

@ -1,7 +1,7 @@
import { FC, useState, useRef } from "react"; import { FC, useState, useRef } from "react";
import { Transition } from "@headlessui/react"; import { Transition } from "@headlessui/react";
import Link from "next/link"; import Link from "next/link";
import { FileText, HelpCircle, MessagesSquare, MoveLeft } from "lucide-react"; import { FileText, HelpCircle, MoveLeft } from "lucide-react";
// hooks // hooks
import { useAppTheme } from "hooks/use-theme"; import { useAppTheme } from "hooks/use-theme";
// icons // icons
@ -25,12 +25,6 @@ const helpOptions = [
href: "https://github.com/makeplane/plane/issues/new/choose", href: "https://github.com/makeplane/plane/issues/new/choose",
Icon: GithubIcon, Icon: GithubIcon,
}, },
{
name: "Chat with us",
href: null,
onClick: () => (window as any).$crisp.push(["do", "chat:show"]),
Icon: MessagesSquare,
},
]; ];
export const HelpSection: FC = () => { export const HelpSection: FC = () => {
@ -100,7 +94,7 @@ export const HelpSection: FC = () => {
ref={helpOptionsRef} ref={helpOptionsRef}
> >
<div className="space-y-1 pb-2"> <div className="space-y-1 pb-2">
{helpOptions.map(({ name, Icon, href, onClick }) => { {helpOptions.map(({ name, Icon, href }) => {
if (href) if (href)
return ( return (
<Link href={href} key={name} target="_blank"> <Link href={href} key={name} target="_blank">
@ -120,7 +114,6 @@ export const HelpSection: FC = () => {
<button <button
key={name} key={name}
type="button" type="button"
onClick={onClick ?? undefined}
className="flex w-full items-center gap-x-2 rounded px-2 py-1 text-xs hover:bg-custom-background-80" className="flex w-full items-center gap-x-2 rounded px-2 py-1 text-xs hover:bg-custom-background-80"
> >
<div className="grid flex-shrink-0 place-items-center"> <div className="grid flex-shrink-0 place-items-center">

View File

@ -0,0 +1,21 @@
import { FC } from "react";
import { observer } from "mobx-react";
// hooks
import { useAppTheme } from "hooks/use-theme";
// icons
import { Menu } from "lucide-react";
export const SidebarHamburgerToggle: FC = observer(() => {
const { toggleSidebar } = useAppTheme();
return (
<div
className="w-7 h-7 rounded flex justify-center items-center bg-custom-background-80 transition-all hover:bg-custom-background-90 cursor-pointer group md:hidden"
onClick={() => toggleSidebar()}
>
<Menu
size={14}
className="text-custom-text-200 group-hover:text-custom-text-100 transition-all"
/>
</div>
);
});

View File

@ -42,10 +42,16 @@ const INSTANCE_ADMIN_LINKS = [
export const SidebarMenu = observer(() => { export const SidebarMenu = observer(() => {
// store hooks // store hooks
const { sidebarCollapsed } = useAppTheme(); const { sidebarCollapsed, toggleSidebar } = useAppTheme();
// router // router
const pathName = usePathname(); const pathName = usePathname();
const handleItemClick = () => {
if (window.innerWidth < 768) {
toggleSidebar();
}
};
return ( return (
<div className="flex h-full w-full flex-col gap-2.5 overflow-y-auto px-4 py-6"> <div className="flex h-full w-full flex-col gap-2.5 overflow-y-auto px-4 py-6">
{INSTANCE_ADMIN_LINKS.map((item, index) => { {INSTANCE_ADMIN_LINKS.map((item, index) => {
@ -55,7 +61,7 @@ export const SidebarMenu = observer(() => {
: pathName === item.href; : pathName === item.href;
return ( return (
<Link key={index} href={item.href}> <Link key={index} href={item.href} onClick={handleItemClick}>
<div> <div>
<Tooltip <Tooltip
tooltipContent={item.name} tooltipContent={item.name}

View File

@ -0,0 +1,19 @@
import React, { useEffect } from "react";
const useOutsideClickDetector = (ref: React.RefObject<HTMLElement>, callback: () => void) => {
const handleClick = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target as Node)) {
callback();
}
};
useEffect(() => {
document.addEventListener("mousedown", handleClick);
return () => {
document.removeEventListener("mousedown", handleClick);
};
});
};
export default useOutsideClickDetector;