From 60e96bcb726c4e059fc2688a4bbb15700a2fa8a5 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Thu, 13 Jul 2023 18:35:43 +0530 Subject: [PATCH] style: app sidebar revamp (#1120) * style: app sidebar, sidebar workspace dropdown and help section styling * style: consistent padding and spacing * feat: material icon global component * style: icons updated and tooltip added * style: project list spacing and project name truncate * style: sidebar padding and theming --------- Co-authored-by: Aaryan Khandelwal --- apps/app/components/onboarding/tour/root.tsx | 3 +- apps/app/components/project/sidebar-list.tsx | 10 +- .../project/single-sidebar-project.tsx | 146 +++++---- apps/app/components/ui/custom-menu.tsx | 6 +- .../app/components/workspace/help-section.tsx | 120 ++++---- .../components/workspace/sidebar-dropdown.tsx | 282 +++++++++--------- .../app/components/workspace/sidebar-menu.tsx | 55 ++-- apps/app/layouts/app-layout/app-sidebar.tsx | 10 +- apps/app/types/workspace.d.ts | 2 +- 9 files changed, 305 insertions(+), 329 deletions(-) diff --git a/apps/app/components/onboarding/tour/root.tsx b/apps/app/components/onboarding/tour/root.tsx index 30a720f8f..f537ebf94 100644 --- a/apps/app/components/onboarding/tour/root.tsx +++ b/apps/app/components/onboarding/tour/root.tsx @@ -70,8 +70,7 @@ const TOUR_STEPS: { { key: "pages", title: "Document with pages", - description: - "Modules break your big think into Projects or Features, to help you organize better.", + description: "Use Pages to quickly jot down issues when you're in a meeting or starting a day.", image: PagesTour, prevStep: "views", }, diff --git a/apps/app/components/project/sidebar-list.tsx b/apps/app/components/project/sidebar-list.tsx index a4125ffac..1225efe96 100644 --- a/apps/app/components/project/sidebar-list.tsx +++ b/apps/app/components/project/sidebar-list.tsx @@ -151,11 +151,11 @@ export const ProjectSidebarList: FC = () => { data={projectToDelete} user={user} /> -
+
{favoriteProjects && favoriteProjects.length > 0 && ( -
+
{!sidebarCollapse && ( -
Favorites
+
Favorites
)} {favoriteProjects.map((favoriteProject) => { const project = favoriteProject.project_detail; @@ -173,9 +173,9 @@ export const ProjectSidebarList: FC = () => { })}
)} -
+
{!sidebarCollapse && ( -
Projects
+
Projects
)} {projects ? ( <> diff --git a/apps/app/components/project/single-sidebar-project.tsx b/apps/app/components/project/single-sidebar-project.tsx index e87e52418..9ef6f7192 100644 --- a/apps/app/components/project/single-sidebar-project.tsx +++ b/apps/app/components/project/single-sidebar-project.tsx @@ -4,22 +4,9 @@ import { useRouter } from "next/router"; // headless ui import { Disclosure, Transition } from "@headlessui/react"; // ui -import { CustomMenu, Icon } from "components/ui"; +import { CustomMenu, Icon, Tooltip } from "components/ui"; // icons -import { - ChevronDownIcon, - DocumentTextIcon, - LinkIcon, - StarIcon, - TrashIcon, -} from "@heroicons/react/24/outline"; -import { - ContrastIcon, - LayerDiagonalIcon, - PeopleGroupIcon, - SettingIcon, - ViewListIcon, -} from "components/icons"; +import { LinkIcon, StarIcon, TrashIcon } from "@heroicons/react/24/outline"; // helpers import { truncateText } from "helpers/string.helper"; import { renderEmoji } from "helpers/emoji.helper"; @@ -39,32 +26,32 @@ const navigation = (workspaceSlug: string, projectId: string) => [ { name: "Issues", href: `/${workspaceSlug}/projects/${projectId}/issues`, - icon: LayerDiagonalIcon, + icon: "stack", }, { name: "Cycles", href: `/${workspaceSlug}/projects/${projectId}/cycles`, - icon: ContrastIcon, + icon: "contrast", }, { name: "Modules", href: `/${workspaceSlug}/projects/${projectId}/modules`, - icon: PeopleGroupIcon, + icon: "dataset", }, { name: "Views", href: `/${workspaceSlug}/projects/${projectId}/views`, - icon: ViewListIcon, + icon: "photo_filter", }, { name: "Pages", href: `/${workspaceSlug}/projects/${projectId}/pages`, - icon: DocumentTextIcon, + icon: "article", }, { name: "Settings", href: `/${workspaceSlug}/projects/${projectId}/settings`, - icon: SettingIcon, + icon: "settings", }, ]; @@ -84,44 +71,56 @@ export const SingleSidebarProject: React.FC = ({ {({ open }) => ( <>
- -
- {project.emoji ? ( - - {renderEmoji(project.emoji)} - - ) : project.icon_prop ? ( -
- - {project.icon_prop.name} + +
+ {project.emoji ? ( + + {renderEmoji(project.emoji)} -
- ) : ( - - {project?.name.charAt(0)} - - )} + ) : project.icon_prop ? ( +
+ + {project.icon_prop.name} + +
+ ) : ( + + {project?.name.charAt(0)} + + )} + {!sidebarCollapse && ( +

+ {truncateText(project?.name, 14)} +

+ )} +
{!sidebarCollapse && ( -
- {truncateText(project?.name, 20)} -
+ )} -
- {!sidebarCollapse && ( - - - - )} -
+ + {!sidebarCollapse && ( @@ -177,9 +176,7 @@ export const SingleSidebarProject: React.FC = ({ leaveFrom="transform scale-100 opacity-100" leaveTo="transform scale-95 opacity-0" > - + {navigation(workspaceSlug as string, project?.id).map((item) => { if ( (item.name === "Cycles" && !project.cycle_view) || @@ -191,25 +188,24 @@ export const SingleSidebarProject: React.FC = ({ return ( - -
- + + - {!sidebarCollapse && item.name} + ? "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" + } ${sidebarCollapse ? "justify-center" : ""}`} + > + + {!sidebarCollapse && item.name} +
+
); diff --git a/apps/app/components/ui/custom-menu.tsx b/apps/app/components/ui/custom-menu.tsx index e42e49d21..f4021b249 100644 --- a/apps/app/components/ui/custom-menu.tsx +++ b/apps/app/components/ui/custom-menu.tsx @@ -5,6 +5,7 @@ import Link from "next/link"; import { Menu, Transition } from "@headlessui/react"; // icons import { ChevronDownIcon, EllipsisHorizontalIcon } from "@heroicons/react/24/outline"; +import { Icon } from "./icon"; type Props = { children: React.ReactNode; @@ -61,8 +62,9 @@ const CustomMenu = ({ type="button" className="relative grid place-items-center rounded p-1 text-custom-text-200 hover:bg-custom-background-80 outline-none" > - ) : ( diff --git a/apps/app/components/workspace/help-section.tsx b/apps/app/components/workspace/help-section.tsx index 719d84d1a..41d0d033f 100644 --- a/apps/app/components/workspace/help-section.tsx +++ b/apps/app/components/workspace/help-section.tsx @@ -1,4 +1,4 @@ -import { useState, useRef, FC } from "react"; +import React, { useRef, useState } from "react"; import { useRouter } from "next/router"; @@ -8,9 +8,16 @@ import useSWR from "swr"; // headless ui import { Transition } from "@headlessui/react"; +// services +import workspaceService from "services/workspace.service"; // hooks import useTheme from "hooks/use-theme"; +import useUser from "hooks/use-user"; import useOutsideClickDetector from "hooks/use-outside-click-detector"; +// components +import UpgradeToProModal from "./upgrade-to-pro-modal"; +// ui +import { CircularProgress } from "components/ui"; // icons import { ArrowLongLeftIcon, @@ -20,15 +27,8 @@ import { XMarkIcon, } from "@heroicons/react/24/outline"; import { QuestionMarkCircleIcon, DocumentIcon, DiscordIcon, GithubIcon } from "components/icons"; -// services -import workspaceService from "services/workspace.service"; // fetch-keys import { WORKSPACE_DETAILS } from "constants/fetch-keys"; -// ui -import { CircularProgress } from "components/ui"; -// components -import UpgradeToProModal from "./upgrade-to-pro-modal"; -import useUser from "hooks/use-user"; const helpOptions = [ { @@ -58,36 +58,28 @@ export interface WorkspaceHelpSectionProps { setSidebarActive: React.Dispatch>; } -type progress = { - progress: number; -}; -export const WorkspaceHelpSection: FC = (props) => { - // router +export const WorkspaceHelpSection: React.FC = ({ setSidebarActive }) => { + const [alert, setAlert] = useState(false); + const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false); + + const helpOptionsRef = useRef(null); + const router = useRouter(); const { workspaceSlug } = router.query; - const { setSidebarActive } = props; - // theme const { collapsed: sidebarCollapse, toggleCollapsed } = useTheme(); - // states - const [isNeedHelpOpen, setIsNeedHelpOpen] = useState(false); - // refs - const helpOptionsRef = useRef(null); - // hooks + useOutsideClickDetector(helpOptionsRef, () => setIsNeedHelpOpen(false)); const { user } = useUser(); - const helpOptionMode = sidebarCollapse ? "left-full" : "left-[-75px]"; - - const [alert, setAlert] = useState(false); - const [upgradeModal, setUpgradeModal] = useState(false); const { data: workspaceDetails } = useSWR( workspaceSlug ? WORKSPACE_DETAILS(workspaceSlug as string) : null, workspaceSlug ? () => workspaceService.getWorkspace(workspaceSlug as string) : null ); + const issueNumber = workspaceDetails?.total_issues || 0; return ( @@ -98,61 +90,58 @@ export const WorkspaceHelpSection: FC = (props) => { user={user} issueNumber={issueNumber} /> - {!sidebarCollapse && (alert || (issueNumber && issueNumber >= 750)) ? ( - <> -
= 750 - ? "bg-red-50 text-red-600 border-red-200" - : issueNumber >= 500 - ? "bg-yellow-50 text-yellow-600 border-yellow-200" - : "text-green-600" - }`} - > -
- -
Free Plan
- {issueNumber < 750 && ( -
setAlert(false)}> - -
- )} -
-
- This workspace has used {issueNumber} of its 1024 issues creation limit ( - {((issueNumber / 1024) * 100).toFixed(0)} - %). -
+ {!sidebarCollapse && (alert || issueNumber >= 750) && ( +
= 750 + ? "bg-red-500/10 text-red-600" + : issueNumber >= 500 + ? "bg-yellow-500/10 text-yellow-600" + : "text-green-600" + }`} + > +
+ +
Free Plan
+ {issueNumber < 750 && ( +
setAlert(false)} + > + +
+ )}
- - ) : ( - "" +
+ This workspace has used {issueNumber} of its 1024 issues creation limit ( + {((issueNumber / 1024) * 100).toFixed(0)} + %). +
+
)}
- {alert || (issueNumber && issueNumber >= 750) ? ( + {alert || issueNumber >= 750 ? ( ) : ( )} - - )} - - )) - ) : ( -

No workspace found!

- )} - { - router.push("/create-workspace"); - }} - className="flex w-full items-center gap-1 text-sm text-custom-sidebar-text-200" - > - - Create Workspace - -
+
+ {activeWorkspace?.logo && activeWorkspace.logo !== "" ? ( + Workspace Logo ) : ( -
- - - - -
+ activeWorkspace?.name?.charAt(0) ?? "..." )}
-
- {userLinks(workspaceSlug as string).map((link, index) => ( + + {!sidebarCollapse && ( +

+ {activeWorkspace?.name ? truncateText(activeWorkspace.name, 14) : "Loading..."} +

+ )} +
+ + + {!sidebarCollapse && ( + + +
+ +
+
+ + )} +
+ + + +
+
{user?.email}
+ Workspace + {workspaces ? ( +
+ {workspaces.length > 0 ? ( + workspaces.map((workspace) => ( + + {({ active }) => ( + + )} + + )) + ) : ( +

No workspace found!

+ )} { + router.push("/create-workspace"); + }} + className="flex w-full items-center gap-1 text-sm text-custom-sidebar-text-200" > - - {link.name} - + + Create Workspace - ))} -
-
+
+ ) : ( +
+ + + + +
+ )} +
+
+ {userLinks(workspaceSlug as string).map((link, index) => ( - Sign out + + {link.name} + -
-
-
- -
+ ))} +
+
+ + Sign out + +
+ + + ); }; diff --git a/apps/app/components/workspace/sidebar-menu.tsx b/apps/app/components/workspace/sidebar-menu.tsx index b86aa6610..6a0683926 100644 --- a/apps/app/components/workspace/sidebar-menu.tsx +++ b/apps/app/components/workspace/sidebar-menu.tsx @@ -5,9 +5,8 @@ import Link from "next/link"; // hooks import useTheme from "hooks/use-theme"; -// icons -import { ChartBarIcon } from "@heroicons/react/24/outline"; -import { GridViewIcon, AssignmentClipboardIcon, TickMarkIcon, SettingIcon } from "components/icons"; +// components +import { Icon, Tooltip } from "components/ui"; export const WorkspaceSidebarMenu = () => { const router = useRouter(); @@ -18,34 +17,34 @@ export const WorkspaceSidebarMenu = () => { const workspaceLinks = (workspaceSlug: string) => [ { - icon: GridViewIcon, + icon: "grid_view", name: "Dashboard", href: `/${workspaceSlug}`, }, { - icon: ChartBarIcon, + icon: "bar_chart", name: "Analytics", href: `/${workspaceSlug}/analytics`, }, { - icon: AssignmentClipboardIcon, + icon: "work", name: "Projects", href: `/${workspaceSlug}/projects`, }, { - icon: TickMarkIcon, + icon: "task_alt", name: "My Issues", href: `/${workspaceSlug}/me/my-issues`, }, { - icon: SettingIcon, + icon: "settings", name: "Settings", href: `/${workspaceSlug}/settings`, }, ]; return ( -
+
{workspaceLinks(workspaceSlug as string).map((link, index) => { const isActive = link.name === "Settings" @@ -54,28 +53,24 @@ export const WorkspaceSidebarMenu = () => { return ( - - - + + + ); diff --git a/apps/app/layouts/app-layout/app-sidebar.tsx b/apps/app/layouts/app-layout/app-sidebar.tsx index 3c3976959..22f515905 100644 --- a/apps/app/layouts/app-layout/app-sidebar.tsx +++ b/apps/app/layouts/app-layout/app-sidebar.tsx @@ -19,13 +19,11 @@ const Sidebar: React.FC = ({ toggleSidebar, setToggleSidebar }) => return (
-
+
diff --git a/apps/app/types/workspace.d.ts b/apps/app/types/workspace.d.ts index 5dbcc1ff2..adc7b359d 100644 --- a/apps/app/types/workspace.d.ts +++ b/apps/app/types/workspace.d.ts @@ -14,7 +14,7 @@ export interface IWorkspace { readonly created_by: string; readonly updated_by: string; organization_size: string; - total_issues: number | null; + total_issues: number; } export interface IWorkspaceLite {