[WEB-2182] chore: user favorites improvement (#5318)

* chore: favorite collapsible spacing

* chore: favorite collapsible tooltip added

* chore: user favorites icon improvement and code refactor

* chore: favorites empty state added

* chore: project identifier message updated

* chore: favorties collapsible improvement

* chore: code refactor

* fix: build error

* fix: app sidebar draft issue z-index
This commit is contained in:
Anmol Singh Bhatia 2024-08-07 15:28:25 +05:30 committed by GitHub
parent 91142659ca
commit 598846adc4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 99 additions and 63 deletions

View file

@ -1,9 +1,22 @@
type TLogoProps = {
in_use: "emoji" | "icon";
emoji?: {
value?: string;
url?: string;
};
icon?: {
name?: string;
color?: string;
};
};
export type IFavorite = {
id: string;
name: string;
entity_type: string;
entity_data: {
name: string;
logo_props?: TLogoProps | undefined;
};
is_folder: boolean;
sort_order: number;

View file

@ -294,7 +294,7 @@ export const CreateProjectForm: FC<Props> = observer((props) => {
/>
<Tooltip
isMobile={isMobile}
tooltipContent="Helps you identify issues in the project uniquely, (e.g. APP-123). Max 5 characters."
tooltipContent="Helps you identify issues in the project uniquely. Max 5 characters."
className="text-sm"
position="right-top"
>

View file

@ -298,7 +298,7 @@ export const ProjectDetailsForm: FC<IProjectDetailsForm> = (props) => {
/>
<Tooltip
isMobile={isMobile}
tooltipContent="Helps you identify issues in the project uniquely, (e.g. APP-123). Max 5 characters."
tooltipContent="Helps you identify issues in the project uniquely. Max 5 characters."
className="text-sm"
position="right-top"
>

View file

@ -9,7 +9,16 @@ import { useParams } from "next/navigation";
import { Briefcase, FileText, Layers, MoreHorizontal, Star } from "lucide-react";
// ui
import { IFavorite } from "@plane/types";
import { ContrastIcon, CustomMenu, DiceIcon, DragHandle, FavoriteFolderIcon, LayersIcon, Tooltip } from "@plane/ui";
import {
ContrastIcon,
CustomMenu,
DiceIcon,
DragHandle,
FavoriteFolderIcon,
LayersIcon,
Logo,
Tooltip,
} from "@plane/ui";
// components
import { SidebarNavItem } from "@/components/sidebar";
@ -20,6 +29,17 @@ import { useAppTheme } from "@/hooks/store";
import useOutsideClickDetector from "@/hooks/use-outside-click-detector";
import { usePlatformOS } from "@/hooks/use-platform-os";
const iconClassName = `flex-shrink-0 size-4 stroke-[1.5] m-auto`;
const ICONS: Record<string, JSX.Element> = {
page: <FileText className={iconClassName} />,
project: <Briefcase className={iconClassName} />,
view: <Layers className={iconClassName} />,
module: <DiceIcon className={iconClassName} />,
cycle: <ContrastIcon className={iconClassName} />,
issue: <LayersIcon className={iconClassName} />,
folder: <FavoriteFolderIcon className={iconClassName} />,
};
export const FavoriteItem = observer(
({
favoriteMap,
@ -48,28 +68,18 @@ export const FavoriteItem = observer(
const dragHandleRef = useRef<HTMLButtonElement | null>(null);
const actionSectionRef = useRef<HTMLDivElement | null>(null);
const getIcon = () => {
const className = `flex-shrink-0 size-4 stroke-[1.5] m-auto`;
switch (favorite.entity_type) {
case "page":
return <FileText className={className} />;
case "project":
return <Briefcase className={className} />;
case "view":
return <Layers className={className} />;
case "module":
return <DiceIcon className={className} />;
case "cycle":
return <ContrastIcon className={className} />;
case "issue":
return <LayersIcon className={className} />;
case "folder":
return <FavoriteFolderIcon className={className} />;
default:
return <FileText />;
}
};
const getIcon = () => (
<>
<div className="hidden group-hover:block">{ICONS[favorite.entity_type] || <FileText />}</div>
<div className="block group-hover:hidden">
{favorite.entity_data?.logo_props?.in_use ? (
<Logo logo={favorite.entity_data?.logo_props} size={16} type="lucide" />
) : (
ICONS[favorite.entity_type] || <FileText />
)}
</div>
</>
);
const getLink = () => {
switch (favorite.entity_type) {
@ -133,7 +143,10 @@ export const FavoriteItem = observer(
<div ref={elementRef} className="group/project-item">
<SidebarNavItem
key={favorite.id}
className={`${sidebarCollapsed ? "p-0 size-8 aspect-square justify-center mx-auto" : ""}`}
className={cn({
"bg-custom-sidebar-background-90": isMenuActive,
"p-0 size-8 aspect-square justify-center mx-auto": sidebarCollapsed,
})}
>
<div
className={cn("flex justify-between items-center gap-1.5 py-[1px]", {

View file

@ -133,14 +133,16 @@ export const SidebarFavoritesMenu = observer(() => {
<span onClick={() => toggleFavoriteMenu(!isFavoriteMenuOpen)} className="flex-1 text-start">
YOUR FAVORITES
</span>
<span className="flex gap-2 flex-shrink-0 opacity-0 pointer-events-none group-hover/workspace-button:opacity-100 group-hover/workspace-button:pointer-events-auto rounded p-0.5 ">
<FolderPlus
onClick={() => {
setCreateNewFolder(true);
!isFavoriteMenuOpen && toggleFavoriteMenu(!isFavoriteMenuOpen);
}}
className={cn("size-4 flex-shrink-0 text-custom-sidebar-text-400 transition-transform")}
/>
<span className="flex flex-shrink-0 opacity-0 pointer-events-none group-hover/workspace-button:opacity-100 group-hover/workspace-button:pointer-events-auto rounded p-0.5 ">
<Tooltip tooltipHeading="Create folder" tooltipContent="">
<FolderPlus
onClick={() => {
setCreateNewFolder(true);
!isFavoriteMenuOpen && toggleFavoriteMenu(!isFavoriteMenuOpen);
}}
className={cn("size-4 flex-shrink-0 text-custom-sidebar-text-400 transition-transform")}
/>
</Tooltip>
<ChevronRight
onClick={() => toggleFavoriteMenu(!isFavoriteMenuOpen)}
className={cn("size-4 flex-shrink-0 text-custom-sidebar-text-400 transition-transform", {
@ -168,34 +170,42 @@ export const SidebarFavoritesMenu = observer(() => {
static
>
{createNewFolder && <NewFavoriteFolder setCreateNewFolder={setCreateNewFolder} actionType="create" />}
{uniqBy(orderBy(Object.values(favoriteMap), "sequence", "desc"), "id")
.filter((fav) => !fav.parent)
.map((fav, index) => (
<Tooltip
key={fav.id}
tooltipContent={fav.entity_data ? fav.entity_data.name : fav.name}
position="right"
className="ml-2"
disabled={!sidebarCollapsed}
isMobile={isMobile}
>
{fav.is_folder ? (
<FavoriteFolder
favorite={fav}
isLastChild={index === favoriteIds.length - 1}
handleRemoveFromFavorites={handleRemoveFromFavorites}
handleRemoveFromFavoritesFolder={handleRemoveFromFavoritesFolder}
/>
) : (
<FavoriteItem
favorite={fav}
handleRemoveFromFavorites={handleRemoveFromFavorites}
handleRemoveFromFavoritesFolder={handleRemoveFromFavoritesFolder}
favoriteMap={favoriteMap}
/>
)}
</Tooltip>
))}
{Object.keys(favoriteMap).length === 0 ? (
<>
{!sidebarCollapsed && (
<span className="text-custom-text-400 text-xs text-center font-medium py-1">No favorites yet</span>
)}
</>
) : (
uniqBy(orderBy(Object.values(favoriteMap), "sequence", "desc"), "id")
.filter((fav) => !fav.parent)
.map((fav, index) => (
<Tooltip
key={fav.id}
tooltipContent={fav.entity_data ? fav.entity_data.name : fav.name}
position="right"
className="ml-2"
disabled={!sidebarCollapsed}
isMobile={isMobile}
>
{fav.is_folder ? (
<FavoriteFolder
favorite={fav}
isLastChild={index === favoriteIds.length - 1}
handleRemoveFromFavorites={handleRemoveFromFavorites}
handleRemoveFromFavoritesFolder={handleRemoveFromFavoritesFolder}
/>
) : (
<FavoriteItem
favorite={fav}
handleRemoveFromFavorites={handleRemoveFromFavorites}
handleRemoveFromFavoritesFolder={handleRemoveFromFavoritesFolder}
favoriteMap={favoriteMap}
/>
)}
</Tooltip>
))
)}
</Disclosure.Panel>
)}
</Transition>

View file

@ -108,7 +108,7 @@ export const SidebarQuickActions = observer(() => {
</button>
)}
{isDraftButtonOpen && (
<div className="absolute mt-0 h-10 w-[220px] pt-2 z-10 top-8 left-0">
<div className="absolute mt-0 h-10 w-[220px] pt-2 z-[16] top-8 left-0">
<div className="h-full w-full">
<button
onClick={() => setIsDraftIssueModalOpen(true)}