[WEB-1716] fix: sidebar UI inconsistencies (#4933)
* fix: sidebar UI inconsistencies * fix: minor UI fixes
This commit is contained in:
parent
245962d5a5
commit
711494b72e
6 changed files with 160 additions and 126 deletions
|
|
@ -53,19 +53,19 @@ export const AppSidebar: FC<IAppSidebar> = observer(() => {
|
|||
<SidebarAppSwitcher />
|
||||
<SidebarQuickActions />
|
||||
<hr
|
||||
className={cn("flex-shrink-0 border-custom-sidebar-border-200 h-[0.5px] w-3/5 mx-auto my-2", {
|
||||
className={cn("flex-shrink-0 border-custom-sidebar-border-300 h-[0.5px] w-3/5 mx-auto my-2", {
|
||||
"opacity-0": !sidebarCollapsed,
|
||||
})}
|
||||
/>
|
||||
<SidebarUserMenu />
|
||||
<hr
|
||||
className={cn("flex-shrink-0 border-custom-sidebar-border-200 h-[0.5px] w-3/5 mx-auto my-2", {
|
||||
className={cn("flex-shrink-0 border-custom-sidebar-border-300 h-[0.5px] w-3/5 mx-auto my-2", {
|
||||
"opacity-0": !sidebarCollapsed,
|
||||
})}
|
||||
/>
|
||||
<SidebarWorkspaceMenu />
|
||||
<hr
|
||||
className={cn("flex-shrink-0 border-custom-sidebar-border-200 h-[0.5px] w-3/5 mx-auto my-2", {
|
||||
className={cn("flex-shrink-0 border-custom-sidebar-border-300 h-[0.5px] w-3/5 mx-auto my-2", {
|
||||
"opacity-0": !sidebarCollapsed,
|
||||
})}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -288,7 +288,7 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
|||
"group/project-item relative w-full px-2 py-1.5 flex items-center rounded-md text-custom-sidebar-text-100 hover:bg-custom-sidebar-background-90",
|
||||
{
|
||||
"bg-custom-sidebar-background-90": isMenuActive,
|
||||
"p-0 size-7 aspect-square justify-center mx-auto": isSidebarCollapsed,
|
||||
"p-0 size-8 aspect-square justify-center mx-auto": isSidebarCollapsed,
|
||||
}
|
||||
)}
|
||||
>
|
||||
|
|
@ -317,7 +317,7 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
|||
</Tooltip>
|
||||
)}
|
||||
{isSidebarCollapsed ? (
|
||||
<Disclosure.Button as="button" className="grid place-items-center">
|
||||
<Disclosure.Button as="button" className="size-8 aspect-square flex-shrink-0 grid place-items-center">
|
||||
<div className="size-4 grid place-items-center flex-shrink-0">
|
||||
<Logo logo={project.logo_props} size={16} />
|
||||
</div>
|
||||
|
|
@ -344,21 +344,6 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
|||
)}
|
||||
</Link>
|
||||
</Tooltip>
|
||||
<Disclosure.Button
|
||||
as="button"
|
||||
className={cn(
|
||||
"hidden group-hover/project-item:inline-block p-0.5 rounded hover:bg-custom-sidebar-background-80",
|
||||
{
|
||||
"inline-block": isMenuActive,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChevronRight
|
||||
className={cn("size-3.5 flex-shrink-0 text-custom-sidebar-text-400 transition-transform", {
|
||||
"rotate-90": open,
|
||||
})}
|
||||
/>
|
||||
</Disclosure.Button>
|
||||
<CustomMenu
|
||||
customButton={
|
||||
<span
|
||||
|
|
@ -448,6 +433,22 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
|||
</CustomMenu.MenuItem>
|
||||
)}
|
||||
</CustomMenu>
|
||||
<Disclosure.Button
|
||||
as="button"
|
||||
type="button"
|
||||
className={cn(
|
||||
"hidden group-hover/project-item:inline-block p-0.5 rounded hover:bg-custom-sidebar-background-80",
|
||||
{
|
||||
"inline-block": isMenuActive,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<ChevronRight
|
||||
className={cn("size-3.5 flex-shrink-0 text-custom-sidebar-text-400 transition-transform", {
|
||||
"rotate-90": open,
|
||||
})}
|
||||
/>
|
||||
</Disclosure.Button>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
|
@ -482,7 +483,7 @@ export const SidebarProjectsListItem: React.FC<Props> = observer((props) => {
|
|||
>
|
||||
<div
|
||||
className={cn(
|
||||
"flex items-center gap-1.5 rounded-md pl-[30px] pr-2 py-1.5 outline-none text-custom-sidebar-text-300 hover:bg-custom-sidebar-background-90 focus:bg-custom-sidebar-background-90",
|
||||
"flex items-center gap-1.5 rounded-md pl-[18px] pr-2 py-1.5 outline-none text-custom-sidebar-text-300 hover:bg-custom-sidebar-background-90 focus:bg-custom-sidebar-background-90",
|
||||
{
|
||||
"text-custom-primary-100 bg-custom-primary-100/10 hover:bg-custom-primary-100/10":
|
||||
pathname.includes(item.href),
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { combine } from "@atlaskit/pragmatic-drag-and-drop/combine";
|
|||
import { autoScrollForElements } from "@atlaskit/pragmatic-drag-and-drop-auto-scroll/element";
|
||||
import { observer } from "mobx-react";
|
||||
import { useParams } from "next/navigation";
|
||||
import { ChevronRight, Plus } from "lucide-react";
|
||||
import { Briefcase, ChevronRight, LucideIcon, Plus, Star } from "lucide-react";
|
||||
import { Disclosure, Transition } from "@headlessui/react";
|
||||
// types
|
||||
import { IProject } from "@plane/types";
|
||||
|
|
@ -146,7 +146,7 @@ export const SidebarProjectsList: FC = observer(() => {
|
|||
key: "all" | "favorite";
|
||||
type: "FAVORITES" | "JOINED";
|
||||
title: string;
|
||||
shortTitle: string;
|
||||
icon: LucideIcon;
|
||||
projects: string[];
|
||||
isOpen: boolean;
|
||||
}[] = [
|
||||
|
|
@ -154,7 +154,7 @@ export const SidebarProjectsList: FC = observer(() => {
|
|||
key: "favorite",
|
||||
type: "FAVORITES",
|
||||
title: "Favorites",
|
||||
shortTitle: "FP",
|
||||
icon: Star,
|
||||
projects: favoriteProjects,
|
||||
isOpen: isFavoriteProjectsListOpen,
|
||||
},
|
||||
|
|
@ -162,7 +162,7 @@ export const SidebarProjectsList: FC = observer(() => {
|
|||
key: "all",
|
||||
type: "JOINED",
|
||||
title: "My projects",
|
||||
shortTitle: "MP",
|
||||
icon: Briefcase,
|
||||
projects: joinedProjects,
|
||||
isOpen: isAllProjectsListOpen,
|
||||
},
|
||||
|
|
@ -180,90 +180,117 @@ export const SidebarProjectsList: FC = observer(() => {
|
|||
)}
|
||||
<div
|
||||
ref={containerRef}
|
||||
className={cn("vertical-scrollbar h-full space-y-2 !overflow-y-scroll scrollbar-sm -mr-3 -ml-4 pl-4", {
|
||||
className={cn("vertical-scrollbar h-full !overflow-y-scroll scrollbar-sm -mr-3 -ml-4 pl-4", {
|
||||
"border-t border-custom-sidebar-border-300": isScrolled,
|
||||
})}
|
||||
>
|
||||
{projectSections.map((section) => {
|
||||
{projectSections.map((section, index) => {
|
||||
if (!section.projects || section.projects.length === 0) return;
|
||||
|
||||
return (
|
||||
<Disclosure key={section.title} as="div" className="flex flex-col" defaultOpen={section.isOpen}>
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
"group w-full flex items-center justify-between px-2 py-0.5 rounded text-custom-sidebar-text-400 hover:bg-custom-sidebar-background-90",
|
||||
{
|
||||
"p-0 justify-center w-fit mx-auto bg-custom-sidebar-background-90 hover:bg-custom-sidebar-background-80":
|
||||
isCollapsed,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<Disclosure.Button
|
||||
as="button"
|
||||
type="button"
|
||||
<>
|
||||
<Disclosure key={section.title} as="div" className="flex flex-col" defaultOpen={section.isOpen}>
|
||||
<>
|
||||
<div
|
||||
className={cn(
|
||||
"group w-full flex items-center gap-1 whitespace-nowrap text-left text-sm font-medium text-custom-sidebar-text-400",
|
||||
"group w-full flex items-center justify-between px-2 py-0.5 rounded text-custom-sidebar-text-400 hover:bg-custom-sidebar-background-90",
|
||||
{
|
||||
"!text-center w-8 px-2 py-0.5 justify-center": isCollapsed,
|
||||
"p-0 justify-center w-fit mx-auto bg-custom-sidebar-background-90 hover:bg-custom-sidebar-background-80":
|
||||
isCollapsed,
|
||||
}
|
||||
)}
|
||||
onClick={() => toggleListDisclosure(!section.isOpen, section.key)}
|
||||
>
|
||||
<Tooltip tooltipHeading={section.title} tooltipContent="">
|
||||
<span>{isCollapsed ? section.shortTitle : section.title}</span>
|
||||
</Tooltip>
|
||||
{!isCollapsed && (
|
||||
<ChevronRight
|
||||
className={cn("flex-shrink-0 size-3.5 transition-all", {
|
||||
"rotate-90": section.isOpen,
|
||||
})}
|
||||
/>
|
||||
)}
|
||||
</Disclosure.Button>
|
||||
{!isCollapsed && isAuthorizedUser && (
|
||||
<Tooltip tooltipHeading="Create project" tooltipContent="">
|
||||
<button
|
||||
className="opacity-0 group-hover:opacity-100 p-0.5 rounded hover:bg-custom-sidebar-background-80 flex-shrink-0"
|
||||
onClick={() => {
|
||||
setTrackElement(`APP_SIDEBAR_${section.type}_BLOCK`);
|
||||
setIsFavoriteProjectCreate(section.key === "favorite");
|
||||
setIsProjectModalOpen(true);
|
||||
}}
|
||||
<Disclosure.Button
|
||||
as="button"
|
||||
type="button"
|
||||
className={cn(
|
||||
"group w-full flex items-center gap-1 whitespace-nowrap text-left text-sm font-semibold text-custom-sidebar-text-400",
|
||||
{
|
||||
"!text-center w-8 px-2 py-1.5 justify-center": isCollapsed,
|
||||
}
|
||||
)}
|
||||
onClick={() => toggleListDisclosure(!section.isOpen, section.key)}
|
||||
>
|
||||
<Tooltip
|
||||
tooltipHeading={section.title}
|
||||
tooltipContent=""
|
||||
position="right"
|
||||
disabled={!isCollapsed}
|
||||
>
|
||||
<Plus className="size-3" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
</div>
|
||||
<Transition
|
||||
show={section.isOpen}
|
||||
enter="transition duration-100 ease-out"
|
||||
enterFrom="transform scale-95 opacity-0"
|
||||
enterTo="transform scale-100 opacity-100"
|
||||
leave="transition duration-75 ease-out"
|
||||
leaveFrom="transform scale-100 opacity-100"
|
||||
leaveTo="transform scale-95 opacity-0"
|
||||
>
|
||||
{section.isOpen && (
|
||||
<Disclosure.Panel as="div" className="mt-3" static>
|
||||
{section.projects.map((projectId, index) => (
|
||||
<SidebarProjectsListItem
|
||||
key={projectId}
|
||||
projectId={projectId}
|
||||
handleCopyText={() => handleCopyText(projectId)}
|
||||
projectListType={section.type}
|
||||
disableDrag={section.key === "favorite"}
|
||||
disableDrop={section.key === "favorite"}
|
||||
isLastChild={index === section.projects.length - 1}
|
||||
handleOnProjectDrop={handleOnProjectDrop}
|
||||
/>
|
||||
))}
|
||||
</Disclosure.Panel>
|
||||
)}
|
||||
</Transition>
|
||||
</>
|
||||
</Disclosure>
|
||||
<span>{isCollapsed ? <section.icon className="flex-shrink-0 size-3" /> : section.title}</span>
|
||||
</Tooltip>
|
||||
</Disclosure.Button>
|
||||
{!isCollapsed && isAuthorizedUser && (
|
||||
<div className="flex items-center opacity-0 group-hover:opacity-100">
|
||||
<Tooltip tooltipHeading="Create project" tooltipContent="">
|
||||
<button
|
||||
type="button"
|
||||
className="p-0.5 rounded hover:bg-custom-sidebar-background-80 flex-shrink-0"
|
||||
onClick={() => {
|
||||
setTrackElement(`APP_SIDEBAR_${section.type}_BLOCK`);
|
||||
setIsFavoriteProjectCreate(section.key === "favorite");
|
||||
setIsProjectModalOpen(true);
|
||||
}}
|
||||
>
|
||||
<Plus className="size-3" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Disclosure.Button
|
||||
as="button"
|
||||
type="button"
|
||||
className="p-0.5 rounded hover:bg-custom-sidebar-background-80 flex-shrink-0"
|
||||
onClick={() => toggleListDisclosure(!section.isOpen, section.key)}
|
||||
>
|
||||
<ChevronRight
|
||||
className={cn("flex-shrink-0 size-3.5 transition-all", {
|
||||
"rotate-90": section.isOpen,
|
||||
})}
|
||||
/>
|
||||
</Disclosure.Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Transition
|
||||
show={section.isOpen}
|
||||
enter="transition duration-100 ease-out"
|
||||
enterFrom="transform scale-95 opacity-0"
|
||||
enterTo="transform scale-100 opacity-100"
|
||||
leave="transition duration-75 ease-out"
|
||||
leaveFrom="transform scale-100 opacity-100"
|
||||
leaveTo="transform scale-95 opacity-0"
|
||||
>
|
||||
{section.isOpen && (
|
||||
<Disclosure.Panel
|
||||
as="div"
|
||||
className={cn("mt-2 ml-1 space-y-1", {
|
||||
"space-y-0 ml-0": isCollapsed,
|
||||
})}
|
||||
static
|
||||
>
|
||||
{section.projects.map((projectId, index) => (
|
||||
<SidebarProjectsListItem
|
||||
key={projectId}
|
||||
projectId={projectId}
|
||||
handleCopyText={() => handleCopyText(projectId)}
|
||||
projectListType={section.type}
|
||||
disableDrag={section.key === "favorite"}
|
||||
disableDrop={section.key === "favorite"}
|
||||
isLastChild={index === section.projects.length - 1}
|
||||
handleOnProjectDrop={handleOnProjectDrop}
|
||||
/>
|
||||
))}
|
||||
</Disclosure.Panel>
|
||||
)}
|
||||
</Transition>
|
||||
</>
|
||||
</Disclosure>
|
||||
<hr
|
||||
className={cn("flex-shrink-0 border-custom-sidebar-border-300 h-[0.5px] w-3/5 mx-auto my-2", {
|
||||
"opacity-0": !sidebarCollapsed,
|
||||
hidden: index === projectSections.length - 1,
|
||||
})}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
{isAuthorizedUser && joinedProjects?.length === 0 && (
|
||||
|
|
|
|||
|
|
@ -71,7 +71,9 @@ export const SidebarUserMenu = observer(() => {
|
|||
}
|
||||
)}
|
||||
>
|
||||
{<link.Icon className="size-4" />}
|
||||
<span className="flex-shrink-0 size-4 grid place-items-center">
|
||||
<link.Icon className="size-4" />
|
||||
</span>
|
||||
{!sidebarCollapsed && <p className="text-sm leading-5 font-medium">{link.label}</p>}
|
||||
</div>
|
||||
</Tooltip>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import React, { useEffect, useState } from "react";
|
|||
import { observer } from "mobx-react";
|
||||
import Link from "next/link";
|
||||
import { useParams, usePathname } from "next/navigation";
|
||||
import { ChevronRight, Crown, Settings } from "lucide-react";
|
||||
import { ChevronRight, Crown } from "lucide-react";
|
||||
import { Disclosure, Transition } from "@headlessui/react";
|
||||
// ui
|
||||
import { Tooltip } from "@plane/ui";
|
||||
|
|
@ -51,28 +51,24 @@ export const SidebarWorkspaceMenu = observer(() => {
|
|||
return (
|
||||
<Disclosure as="div" defaultOpen>
|
||||
{!sidebarCollapsed && (
|
||||
<div className="group/workspace-button flex items-center justify-between text-custom-sidebar-text-400 px-2 py-0.5 hover:bg-custom-sidebar-background-90 rounded">
|
||||
<Disclosure.Button
|
||||
as="button"
|
||||
className="flex-grow flex items-center gap-1 text-sm font-medium"
|
||||
onClick={() => setIsWorkspaceMenuOpen((prev) => !prev)}
|
||||
>
|
||||
<span>Workspace</span>
|
||||
<ChevronRight
|
||||
className={cn("flex-shrink-0 size-3.5 transition-all", {
|
||||
"rotate-90": isWorkspaceMenuOpen,
|
||||
})}
|
||||
/>
|
||||
</Disclosure.Button>
|
||||
<Link
|
||||
href={`/${workspaceSlug}/settings`}
|
||||
className="flex-shrink-0 hidden group-hover/workspace-button:block rounded p-0.5 hover:bg-custom-sidebar-background-80"
|
||||
>
|
||||
<Tooltip tooltipHeading="Workspace settings" tooltipContent="">
|
||||
<Settings className="size-3" />
|
||||
</Tooltip>
|
||||
</Link>
|
||||
</div>
|
||||
<Disclosure.Button
|
||||
as="button"
|
||||
className="group/workspace-button w-full px-2 py-0.5 flex items-center justify-between gap-1 text-custom-sidebar-text-400 hover:bg-custom-sidebar-background-90 rounded text-sm font-semibold"
|
||||
onClick={() => setIsWorkspaceMenuOpen((prev) => !prev)}
|
||||
>
|
||||
{({ open }) => (
|
||||
<>
|
||||
<span>Workspace</span>
|
||||
<span className="flex-shrink-0 hidden group-hover/workspace-button:inline-block rounded p-0.5 hover:bg-custom-sidebar-background-80">
|
||||
<ChevronRight
|
||||
className={cn("size-3.5 flex-shrink-0 text-custom-sidebar-text-400 transition-transform", {
|
||||
"rotate-90": open,
|
||||
})}
|
||||
/>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</Disclosure.Button>
|
||||
)}
|
||||
<Transition
|
||||
show={isWorkspaceMenuOpen}
|
||||
|
|
@ -86,8 +82,8 @@ export const SidebarWorkspaceMenu = observer(() => {
|
|||
{isWorkspaceMenuOpen && (
|
||||
<Disclosure.Panel
|
||||
as="div"
|
||||
className={cn("mt-3 space-y-1", {
|
||||
"space-y-0 mt-0": sidebarCollapsed,
|
||||
className={cn("mt-2 ml-1 space-y-1", {
|
||||
"space-y-0 mt-0 ml-0": sidebarCollapsed,
|
||||
})}
|
||||
static
|
||||
>
|
||||
|
|
@ -117,13 +113,13 @@ export const SidebarWorkspaceMenu = observer(() => {
|
|||
}
|
||||
)}
|
||||
>
|
||||
{
|
||||
<span className="flex-shrink-0 size-4 grid place-items-center">
|
||||
<link.Icon
|
||||
className={cn("size-4", {
|
||||
"rotate-180": link.key === "active-cycles",
|
||||
})}
|
||||
/>
|
||||
}
|
||||
</span>
|
||||
{!sidebarCollapsed && <p className="text-sm leading-5 font-medium">{link.label}</p>}
|
||||
{!sidebarCollapsed && link.key === "active-cycles" && (
|
||||
<Crown className="size-3.5 text-amber-400" />
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
import { linearGradientDef } from "@nivo/core";
|
||||
// icons
|
||||
import { BarChart2, Briefcase, CheckCircle, Home } from "lucide-react";
|
||||
import { BarChart2, Briefcase, CheckCircle, Home, Settings } from "lucide-react";
|
||||
// types
|
||||
import { TIssuesListTypes, TStateGroups } from "@plane/types";
|
||||
// ui
|
||||
|
|
@ -291,6 +291,14 @@ export const SIDEBAR_WORKSPACE_MENU_ITEMS: {
|
|||
highlight: (pathname: string, baseUrl: string) => pathname.includes(`${baseUrl}/analytics/`),
|
||||
Icon: BarChart2,
|
||||
},
|
||||
{
|
||||
key: "settings",
|
||||
label: "Settings",
|
||||
href: `/settings`,
|
||||
access: EUserWorkspaceRoles.GUEST,
|
||||
highlight: (pathname: string, baseUrl: string) => pathname.includes(`${baseUrl}/analytics/`),
|
||||
Icon: Settings,
|
||||
},
|
||||
];
|
||||
|
||||
export const SIDEBAR_USER_MENU_ITEMS: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue