style/responsive sidebar (#3505)

* style: added sidebar toggle in all the screens for mobile responsive

* chore: close sidebar on click of empty space when opened

* chore: setting the sidebar collapsed in smaller screens
This commit is contained in:
Ramesh Kumar Chandra 2024-01-30 15:22:24 +05:30 committed by GitHub
parent 9debd81a50
commit c6d6b9a0e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
28 changed files with 195 additions and 89 deletions

View File

@ -0,0 +1,16 @@
import { FC } from "react";
import { Menu } from "lucide-react";
import { useApplication } from "hooks/store";
import { observer } from "mobx-react";
export const SidebarHamburgerToggle: FC = observer (() => {
const { theme: themStore } = useApplication();
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={() => themStore.toggleSidebar()}
>
<Menu size={14} className="text-custom-text-200 group-hover:text-custom-text-100 transition-all" />
</div>
);
});

View File

@ -63,34 +63,27 @@ export const OverviewStatsWidget: React.FC<WidgetProps> = observer((props) => {
if (!widgetStats) return <WidgetLoader widgetKey={WIDGET_KEY} />;
return (
<div className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full grid grid-cols-4 p-0.5 hover:shadow-custom-shadow-4xl duration-300">
{STATS_LIST.map((stat, index) => {
const isFirst = index === 0;
const isLast = index === STATS_LIST.length - 1;
const isMiddle = !isFirst && !isLast;
return (
<div key={stat.key} className="flex relative">
{!isLast && (
<div className="absolute right-0 top-1/2 -translate-y-1/2 h-3/5 w-[0.5px] bg-custom-border-200" />
)}
<Link
href={stat.link}
className={cn(
`py-4 hover:bg-custom-background-80 duration-300 rounded-[10px] w-full break-words flex flex-col justify-center`,
{
"pl-11 pr-[4.725rem] mr-0.5": isFirst,
"px-[4.725rem] mx-0.5": isMiddle,
"px-[4.725rem] ml-0.5": isLast,
}
)}
>
<h5 className="font-semibold text-xl">{stat.count}</h5>
<p className="text-custom-text-300 text-sm xl:text-base">{stat.title}</p>
</Link>
</div>
);
})}
<div
className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full grid lg:grid-cols-4 md:grid-cols-2 sm:grid-cols-2 grid-cols-2 p-0.5 hover:shadow-custom-shadow-4xl duration-300
[&>div>a>div]:border-r
[&>div:last-child>a>div]:border-0
[&>div>a>div]:border-custom-border-200
[&>div:nth-child(2)>a>div]:border-0
[&>div:nth-child(2)>a>div]:lg:border-r
"
>
{STATS_LIST.map((stat) => (
<div className="w-full flex flex-col gap-2 hover:bg-custom-background-80 rounded-[10px]">
<Link href={stat.link} className="py-4 duration-300 rounded-[10px] w-full ">
<div className={`relative flex justify-center items-center`}>
<div>
<h5 className="font-semibold text-xl">{stat.count}</h5>
<p className="text-custom-text-300 text-sm xl:text-base">{stat.title}</p>
</div>
</div>
</Link>
</div>
))}
</div>
);
});

View File

@ -17,6 +17,7 @@ import useLocalStorage from "hooks/use-local-storage";
// components
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues";
import { ProjectAnalyticsModal } from "components/analytics";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// ui
import { Breadcrumbs, Button, ContrastIcon, CustomMenu } from "@plane/ui";
// icons
@ -146,6 +147,7 @@ export const CycleIssuesHeader: React.FC = observer(() => {
/>
<div className="relative z-10 flex h-[3.75rem] w-full items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex items-center gap-2">
<SidebarHamburgerToggle />
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem
type="text"

View File

@ -9,6 +9,8 @@ import { Breadcrumbs, Button, ContrastIcon } from "@plane/ui";
// helpers
import { renderEmoji } from "helpers/emoji.helper";
import { EUserProjectRoles } from "constants/project";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export const CyclesHeader: FC = observer(() => {
// router
@ -30,6 +32,7 @@ export const CyclesHeader: FC = observer(() => {
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -7,6 +7,7 @@ import { useLabel, useMember, useUser, useIssues } from "hooks/store";
// components
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection } from "components/issues";
import { CreateUpdateWorkspaceViewModal } from "components/workspace";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// ui
import { Breadcrumbs, Button, LayersIcon, PhotoFilterIcon, Tooltip } from "@plane/ui";
// icons
@ -106,7 +107,8 @@ export const GlobalIssuesHeader: React.FC<Props> = observer((props) => {
<>
<CreateUpdateWorkspaceViewModal isOpen={createViewModal} onClose={() => setCreateViewModal(false)} />
<div className="relative z-10 flex h-[3.75rem] w-full items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
<div>
<div className="relative flex gap-2">
<SidebarHamburgerToggle/>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem
type="text"

View File

@ -17,6 +17,7 @@ import useLocalStorage from "hooks/use-local-storage";
// components
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues";
import { ProjectAnalyticsModal } from "components/analytics";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// ui
import { Breadcrumbs, Button, CustomMenu, DiceIcon } from "@plane/ui";
// icons
@ -149,6 +150,7 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
/>
<div className="relative z-10 flex h-[3.75rem] w-full items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex items-center gap-2">
<SidebarHamburgerToggle />
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem
type="text"

View File

@ -11,6 +11,8 @@ import { renderEmoji } from "helpers/emoji.helper";
// constants
import { MODULE_VIEW_LAYOUTS } from "constants/module";
import { EUserProjectRoles } from "constants/project";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export const ModulesListHeader: React.FC = observer(() => {
// router
@ -31,6 +33,7 @@ export const ModulesListHeader: React.FC = observer(() => {
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -8,6 +8,8 @@ import { useApplication, usePage, useProject } from "hooks/store";
import { Breadcrumbs, Button } from "@plane/ui";
// helpers
import { renderEmoji } from "helpers/emoji.helper";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export interface IPagesHeaderProps {
showButton?: boolean;
@ -27,6 +29,7 @@ export const PageDetailsHeader: FC<IPagesHeaderProps> = observer((props) => {
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -9,6 +9,8 @@ import { Breadcrumbs, Button } from "@plane/ui";
import { renderEmoji } from "helpers/emoji.helper";
// constants
import { EUserProjectRoles } from "constants/project";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export const PagesHeader = observer(() => {
// router
@ -29,6 +31,7 @@ export const PagesHeader = observer(() => {
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -14,6 +14,8 @@ import { ISSUE_DETAILS } from "constants/fetch-keys";
import { IssueArchiveService } from "services/issue";
// helpers
import { renderEmoji } from "helpers/emoji.helper";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
const issueArchiveService = new IssueArchiveService();
@ -39,6 +41,7 @@ export const ProjectArchivedIssueDetailsHeader: FC = observer(() => {
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -10,6 +10,7 @@ import { EIssueFilterType, EIssuesStoreType, ISSUE_DISPLAY_FILTERS_BY_LAYOUT } f
import { Breadcrumbs, LayersIcon } from "@plane/ui";
// components
import { DisplayFiltersSelection, FilterSelection, FiltersDropdown } from "components/issues";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// helpers
import { renderEmoji } from "helpers/emoji.helper";
// types
@ -70,6 +71,7 @@ export const ProjectArchivedIssuesHeader: FC = observer(() => {
return (
<div className="relative z-10 flex h-14 w-full flex-shrink-0 flex-row items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div className="block md:hidden">
<button
type="button"

View File

@ -5,6 +5,7 @@ import { observer } from "mobx-react-lite";
import { useIssues, useLabel, useMember, useProject, useProjectState } from "hooks/store";
// components
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// ui
import { Breadcrumbs, LayersIcon } from "@plane/ui";
// helper
@ -74,6 +75,7 @@ export const ProjectDraftIssueHeader: FC = observer(() => {
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -8,6 +8,7 @@ import { useProject } from "hooks/store";
import { Breadcrumbs, Button, LayersIcon } from "@plane/ui";
// components
import { CreateInboxIssueModal } from "components/inbox";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// helper
import { renderEmoji } from "helpers/emoji.helper";
@ -23,6 +24,7 @@ export const ProjectInboxHeader: FC = observer(() => {
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -12,6 +12,8 @@ import { renderEmoji } from "helpers/emoji.helper";
import { IssueService } from "services/issue";
// constants
import { ISSUE_DETAILS } from "constants/fetch-keys";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// services
const issueService = new IssueService();
@ -33,6 +35,7 @@ export const ProjectIssueDetailsHeader: FC = observer(() => {
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -8,6 +8,7 @@ import { useApplication, useLabel, useProject, useProjectState, useUser, useInbo
// components
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues";
import { ProjectAnalyticsModal } from "components/analytics";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// ui
import { Breadcrumbs, Button, LayersIcon } from "@plane/ui";
// types
@ -105,6 +106,7 @@ export const ProjectIssuesHeader: React.FC = observer(() => {
/>
<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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div className="block md:hidden">
<button
type="button"

View File

@ -9,6 +9,8 @@ import { renderEmoji } from "helpers/emoji.helper";
import { useProject, useUser } from "hooks/store";
// constants
import { EUserProjectRoles } from "constants/project";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export interface IProjectSettingHeader {
title: string;
@ -30,6 +32,7 @@ export const ProjectSettingHeader: FC<IProjectSettingHeader> = observer((props)
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -16,6 +16,7 @@ import {
} from "hooks/store";
// components
import { DisplayFiltersSelection, FiltersDropdown, FilterSelection, LayoutSelection } from "components/issues";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// ui
import { Breadcrumbs, Button, CustomMenu, PhotoFilterIcon } from "@plane/ui";
// helpers
@ -107,6 +108,7 @@ export const ProjectViewIssuesHeader: React.FC = observer(() => {
return (
<div className="relative z-10 flex h-[3.75rem] w-full items-center justify-between gap-x-2 gap-y-4 border-b border-custom-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex items-center gap-2">
<SidebarHamburgerToggle />
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem
type="text"

View File

@ -5,6 +5,7 @@ import { Plus } from "lucide-react";
import { useApplication, useProject, useUser } from "hooks/store";
// components
import { Breadcrumbs, PhotoFilterIcon, Button } from "@plane/ui";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
// helpers
import { renderEmoji } from "helpers/emoji.helper";
// constants
@ -30,6 +31,7 @@ export const ProjectViewsHeader: React.FC = observer(() => {
<>
<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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -6,6 +6,8 @@ import { useApplication, useProject, useUser } from "hooks/store";
import { Breadcrumbs, Button } from "@plane/ui";
// constants
import { EUserWorkspaceRoles } from "constants/workspace";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export const ProjectsHeader = observer(() => {
// store hooks
@ -23,6 +25,7 @@ export const ProjectsHeader = observer(() => {
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -1,9 +1,12 @@
// ui
import { Breadcrumbs } from "@plane/ui";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export const UserProfileHeader = () => (
<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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem type="text" label="Activity Overview" link="/profile" />

View File

@ -3,10 +3,12 @@ import { observer } from "mobx-react-lite";
import { Breadcrumbs, ContrastIcon } from "@plane/ui";
// icons
import { Crown } from "lucide-react";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export const WorkspaceActiveCycleHeader = observer(() => (
<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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle />
<div className="flex items-center gap-2">
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -2,6 +2,8 @@ import { useRouter } from "next/router";
import { ArrowLeft, BarChart2 } from "lucide-react";
// ui
import { Breadcrumbs } from "@plane/ui";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export const WorkspaceAnalyticsHeader = () => {
const router = useRouter();
@ -12,6 +14,7 @@ export const WorkspaceAnalyticsHeader = () => {
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-border-200 bg-custom-sidebar-background-100 p-4`}
>
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle />
<div className="block md:hidden">
<button
type="button"

View File

@ -8,10 +8,11 @@ import githubWhiteImage from "/public/logos/github-white.png";
// components
import { ProductUpdatesModal } from "components/common";
import { Breadcrumbs } from "@plane/ui";
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export const WorkspaceDashboardHeader = () => {
const [isProductUpdatesModalOpen, setIsProductUpdatesModalOpen] = useState(false);
// theme
// hooks
const { resolvedTheme } = useTheme();
return (
@ -19,6 +20,7 @@ export const WorkspaceDashboardHeader = () => {
<ProductUpdatesModal isOpen={isProductUpdatesModalOpen} setIsOpen={setIsProductUpdatesModalOpen} />
<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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle />
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -1,13 +1,12 @@
import { FC } from "react";
import { useRouter } from "next/router";
// ui
import { Breadcrumbs } from "@plane/ui";
import { Settings } from "lucide-react";
// hooks
import { observer } from "mobx-react-lite";
// components
import { SidebarHamburgerToggle } from "components/core/sidebar/sidebar-menu-hamburger-toggle";
export interface IWorkspaceSettingHeader {
title: string;
@ -22,6 +21,7 @@ export const WorkspaceSettingHeader: FC<IWorkspaceSettingHeader> = observer((pro
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-border-200 bg-custom-sidebar-background-100 p-4">
<div className="flex w-full flex-grow items-center gap-2 overflow-ellipsis whitespace-nowrap">
<SidebarHamburgerToggle/>
<div>
<Breadcrumbs>
<Breadcrumbs.BreadcrumbItem

View File

@ -131,6 +131,12 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
setLeaveProjectModal(false);
};
const handleProjectClick = () => {
if (window.innerWidth < 768) {
themeStore.toggleSidebar();
}
};
useOutsideClickDetector(actionSectionRef, () => setIsMenuActive(false));
if (!project) return null;
@ -143,9 +149,8 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
{({ open }) => (
<>
<div
className={`group relative flex w-full items-center rounded-md px-2 py-1 text-custom-sidebar-text-10 hover:bg-custom-sidebar-background-80 ${
snapshot?.isDragging ? "opacity-60" : ""
} ${isMenuActive ? "!bg-custom-sidebar-background-80" : ""}`}
className={`group relative flex w-full items-center rounded-md px-2 py-1 text-custom-sidebar-text-10 hover:bg-custom-sidebar-background-80 ${snapshot?.isDragging ? "opacity-60" : ""
} ${isMenuActive ? "!bg-custom-sidebar-background-80" : ""}`}
>
{provided && (
<Tooltip
@ -154,11 +159,9 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
>
<button
type="button"
className={`absolute -left-2.5 top-1/2 hidden -translate-y-1/2 rounded p-0.5 text-custom-sidebar-text-400 ${
isCollapsed ? "" : "group-hover:!flex"
} ${project.sort_order === null ? "cursor-not-allowed opacity-60" : ""} ${
isMenuActive ? "!flex" : ""
}`}
className={`absolute -left-2.5 top-1/2 hidden -translate-y-1/2 rounded p-0.5 text-custom-sidebar-text-400 ${isCollapsed ? "" : "group-hover:!flex"
} ${project.sort_order === null ? "cursor-not-allowed opacity-60" : ""} ${isMenuActive ? "!flex" : ""
}`}
{...provided?.dragHandleProps}
>
<MoreVertical className="h-3.5" />
@ -169,14 +172,12 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
<Tooltip tooltipContent={`${project.name}`} position="right" className="ml-2" disabled={!isCollapsed}>
<Disclosure.Button
as="div"
className={`flex flex-grow cursor-pointer select-none items-center truncate text-left text-sm font-medium ${
isCollapsed ? "justify-center" : `justify-between`
}`}
className={`flex flex-grow cursor-pointer select-none items-center truncate text-left text-sm font-medium ${isCollapsed ? "justify-center" : `justify-between`
}`}
>
<div
className={`flex w-full flex-grow items-center gap-x-2 truncate ${
isCollapsed ? "justify-center" : ""
}`}
className={`flex w-full flex-grow items-center gap-x-2 truncate ${isCollapsed ? "justify-center" : ""
}`}
>
{project.emoji ? (
<span className="grid h-7 w-7 flex-shrink-0 place-items-center rounded uppercase">
@ -196,9 +197,8 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
</div>
{!isCollapsed && (
<ChevronDown
className={`hidden h-4 w-4 flex-shrink-0 ${open ? "rotate-180" : ""} ${
isMenuActive ? "!block" : ""
} mb-0.5 text-custom-sidebar-text-400 duration-300 group-hover:!block`}
className={`hidden h-4 w-4 flex-shrink-0 ${open ? "rotate-180" : ""} ${isMenuActive ? "!block" : ""
} mb-0.5 text-custom-sidebar-text-400 duration-300 group-hover:!block`}
/>
)}
</Disclosure.Button>
@ -313,7 +313,7 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
return;
return (
<Link key={item.name} href={item.href}>
<Link key={item.name} href={item.href} onClick={handleProjectClick}>
<span className="block w-full">
<Tooltip
tooltipContent={`${project?.name}: ${item.name}`}
@ -322,11 +322,10 @@ export const ProjectSidebarListItem: React.FC<Props> = observer((props) => {
disabled={!isCollapsed}
>
<div
className={`group flex items-center gap-2.5 rounded-md px-2 py-1.5 text-xs font-medium outline-none ${
router.asPath.includes(item.href)
? "bg-custom-primary-100/10 text-custom-primary-100"
: "text-custom-sidebar-text-300 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
} ${isCollapsed ? "justify-center" : ""}`}
className={`group flex items-center gap-2.5 rounded-md px-2 py-1.5 text-xs font-medium outline-none ${router.asPath.includes(item.href)
? "bg-custom-primary-100/10 text-custom-primary-100"
: "text-custom-sidebar-text-300 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
} ${isCollapsed ? "justify-center" : ""}`}
>
<item.Icon className="h-4 w-4 stroke-[1.5]" />
{!isCollapsed && item.name}

View File

@ -56,7 +56,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
const { workspaceSlug } = router.query;
// store hooks
const {
theme: { sidebarCollapsed },
theme: { sidebarCollapsed, toggleSidebar },
eventTracker: { setTrackElement },
} = useApplication();
const { currentUser, updateCurrentUser, isUserInstanceAdmin, signOut } = useUser();
@ -86,6 +86,13 @@ export const WorkspaceSidebarDropdown = observer(() => {
);
};
const handleItemClick = () => {
console.log('CLICKED')
if (window.innerWidth < 768) {
toggleSidebar();
}
};
const workspacesList = Object.values(workspaces ?? {});
// TODO: fix workspaces list scroll
@ -96,15 +103,13 @@ export const WorkspaceSidebarDropdown = observer(() => {
<>
<Menu.Button className="group/menu-button h-full w-full truncate rounded-md text-sm font-medium text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:outline-none">
<div
className={`flex items-center gap-x-2 truncate rounded p-1 ${
sidebarCollapsed ? "justify-center" : "justify-between"
}`}
className={`flex items-center gap-x-2 truncate rounded p-1 ${sidebarCollapsed ? "justify-center" : "justify-between"
}`}
>
<div className="flex items-center gap-2 truncate">
<div
className={`relative grid h-6 w-6 flex-shrink-0 place-items-center uppercase ${
!activeWorkspace?.logo && "rounded bg-custom-primary-500 text-white"
}`}
className={`relative grid h-6 w-6 flex-shrink-0 place-items-center uppercase ${!activeWorkspace?.logo && "rounded bg-custom-primary-500 text-white"
}`}
>
{activeWorkspace?.logo && activeWorkspace.logo !== "" ? (
<img
@ -126,9 +131,8 @@ export const WorkspaceSidebarDropdown = observer(() => {
{!sidebarCollapsed && (
<ChevronDown
className={`mx-1 hidden h-4 w-4 flex-shrink-0 group-hover/menu-button:block ${
open ? "rotate-180" : ""
} text-custom-sidebar-text-400 duration-300`}
className={`mx-1 hidden h-4 w-4 flex-shrink-0 group-hover/menu-button:block ${open ? "rotate-180" : ""
} text-custom-sidebar-text-400 duration-300`}
/>
)}
</div>
@ -156,7 +160,10 @@ export const WorkspaceSidebarDropdown = observer(() => {
<Link
key={workspace.id}
href={`/${workspace.slug}`}
onClick={() => handleWorkspaceNavigation(workspace)}
onClick={() => {
handleWorkspaceNavigation(workspace);
handleItemClick();
}}
className="w-full"
>
<Menu.Item
@ -165,9 +172,8 @@ export const WorkspaceSidebarDropdown = observer(() => {
>
<div className="flex items-center justify-start gap-2.5 truncate">
<span
className={`relative flex h-6 w-6 flex-shrink-0 items-center justify-center p-2 text-xs uppercase ${
!workspace?.logo && "rounded bg-custom-primary-500 text-white"
}`}
className={`relative flex h-6 w-6 flex-shrink-0 items-center justify-center p-2 text-xs uppercase ${!workspace?.logo && "rounded bg-custom-primary-500 text-white"
}`}
>
{workspace?.logo && workspace.logo !== "" ? (
<img
@ -181,9 +187,8 @@ export const WorkspaceSidebarDropdown = observer(() => {
</span>
<h5
className={`truncate text-sm font-medium ${
workspaceSlug === workspace.slug ? "" : "text-custom-text-200"
}`}
className={`truncate text-sm font-medium ${workspaceSlug === workspace.slug ? "" : "text-custom-text-200"
}`}
>
{workspace.name}
</h5>
@ -220,8 +225,10 @@ export const WorkspaceSidebarDropdown = observer(() => {
Create workspace
</Menu.Item>
</Link>
{userLinks(workspaceSlug?.toString() ?? "", currentUser?.id ?? "").map((link) => (
<Link key={link.key} href={link.href} className="w-full">
{userLinks(workspaceSlug?.toString() ?? "", currentUser?.id ?? "").map((link, index) => (
<Link key={link.key} href={link.href} className="w-full" onClick={() => {
if (index > 0) handleItemClick();
}}>
<Menu.Item
as="div"
className="flex items-center gap-2 rounded px-2 py-1 text-sm text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 font-medium"
@ -278,7 +285,7 @@ export const WorkspaceSidebarDropdown = observer(() => {
<div className="flex flex-col gap-2.5 pb-2">
<span className="px-2 text-custom-sidebar-text-200">{currentUser?.email}</span>
{profileLinks(workspaceSlug?.toString() ?? "", currentUser?.id ?? "").map((link, index) => (
<Link key={index} href={link.link}>
<Link key={index} href={link.link} onClick={() => { if (index == 0) handleItemClick(); }}>
<Menu.Item key={index} as="div">
<span className="flex w-full items-center gap-2 rounded px-2 py-1 hover:bg-custom-sidebar-background-80">
<link.icon className="h-4 w-4 stroke-[1.5]" />

View File

@ -27,12 +27,21 @@ export const WorkspaceSidebarMenu = observer(() => {
// computed
const workspaceMemberInfo = currentWorkspaceRole || EUserWorkspaceRoles.GUEST;
const handleLinkClick = () => {
if (window.innerWidth < 768) {
themeStore.toggleSidebar();
}
};
return (
<div className="w-full cursor-pointer space-y-2 p-4">
{SIDEBAR_MENU_ITEMS.map(
(link) =>
workspaceMemberInfo >= link.access && (
<Link key={link.key} href={`/${workspaceSlug}${link.href}`}>
<Link key={link.key}
href={`/${workspaceSlug}${link.href}`}
onClick={handleLinkClick}
>
<span className="block w-full my-1">
<Tooltip
tooltipContent={link.label}
@ -41,11 +50,10 @@ export const WorkspaceSidebarMenu = observer(() => {
disabled={!themeStore?.sidebarCollapsed}
>
<div
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${
link.highlight(router.asPath, `/${workspaceSlug}`)
? "bg-custom-primary-100/10 text-custom-primary-100"
: "text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
} ${themeStore?.sidebarCollapsed ? "justify-center" : ""}`}
className={`group flex w-full items-center gap-2.5 rounded-md px-3 py-2 text-sm font-medium outline-none ${link.highlight(router.asPath, `/${workspaceSlug}`)
? "bg-custom-primary-100/10 text-custom-primary-100"
: "text-custom-sidebar-text-200 hover:bg-custom-sidebar-background-80 focus:bg-custom-sidebar-background-80"
} ${themeStore?.sidebarCollapsed ? "justify-center" : ""}`}
>
{
<link.Icon

View File

@ -1,4 +1,4 @@
import { FC } from "react";
import { FC, useEffect, useRef } from "react";
import { observer } from "mobx-react-lite";
// components
import {
@ -10,20 +10,48 @@ import {
import { ProjectSidebarList } from "components/project";
// hooks
import { useApplication } from "hooks/store";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
export interface IAppSidebar {}
export interface IAppSidebar { }
export const AppSidebar: FC<IAppSidebar> = observer(() => {
// store hooks
const { theme: themStore } = useApplication();
const ref = useRef<HTMLDivElement>(null);
useOutsideClickDetector(ref, () => {
if (themStore.sidebarCollapsed === false) {
if (window.innerWidth < 768) {
themStore.toggleSidebar();
}
}
});
useEffect(() => {
const handleResize = () => {
if (window.innerWidth <= 768) {
themStore.toggleSidebar(true);
}
};
handleResize();
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, [themStore]);
return (
<div
className={`fixed 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 ${
themStore?.sidebarCollapsed ? "" : "md:w-[280px]"
} ${themStore?.sidebarCollapsed ? "left-0" : "-left-full md:left-0"}`}
>
<div className="flex h-full w-full flex-1 flex-col">
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
fixed md:relative
${themStore.sidebarCollapsed ? "-ml-[280px]" : ""}
sm:${themStore.sidebarCollapsed ? "-ml-[280px]" : ""}
md:ml-0 ${themStore.sidebarCollapsed ? 'w-[80px]' : 'w-[280px]'}
lg:ml-0 ${themStore.sidebarCollapsed ? 'w-[80px]' : 'w-[280px]'}
`} >
<div
ref={ref}
className="flex h-full w-full flex-1 flex-col">
<WorkspaceSidebarDropdown />
<WorkspaceSidebarQuickAction />
<WorkspaceSidebarMenu />
@ -33,3 +61,6 @@ export const AppSidebar: FC<IAppSidebar> = observer(() => {
</div>
);
});