[WEB-2130] chore: list layout responsiveness improvement (#5276)

* chore: issue list layout responsiveness improvement

* fix: list layout item component improvement

* chore: cycle, module and view list layout responsiveness improvement
This commit is contained in:
Anmol Singh Bhatia 2024-07-31 17:10:16 +05:30 committed by GitHub
parent dd3df20319
commit 18df1530c1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 122 additions and 45 deletions

View file

@ -18,6 +18,9 @@ interface IListItemProps {
parentRef: React.RefObject<HTMLDivElement>;
disableLink?: boolean;
className?: string;
actionItemContainerClassName?: string;
isSidebarOpen?: boolean;
quickActionElement?: JSX.Element;
}
export const ListItem: FC<IListItemProps> = (props) => {
@ -32,6 +35,9 @@ export const ListItem: FC<IListItemProps> = (props) => {
parentRef,
disableLink = false,
className = "",
actionItemContainerClassName = "",
isSidebarOpen = false,
quickActionElement,
} = props;
// router
@ -45,34 +51,49 @@ export const ListItem: FC<IListItemProps> = (props) => {
return (
<div ref={parentRef} className="relative">
<ControlLink href={itemLink} target="_self" onClick={handleControlLinkClick} disabled={disableLink}>
<div
className={cn(
"group h-24 sm:h-[52px] flex w-full flex-col items-center justify-between gap-3 sm:gap-5 px-6 py-4 sm:py-0 text-sm border-b border-custom-border-200 bg-custom-background-100 hover:bg-custom-background-90 sm:flex-row",
className
)}
>
<div className="relative flex w-full items-center justify-between gap-3 overflow-hidden">
<div className="relative flex w-full items-center gap-3 overflow-hidden">
<div className="flex items-center gap-4 truncate">
{prependTitleElement && <span className="flex items-center flex-shrink-0">{prependTitleElement}</span>}
<Tooltip tooltipContent={title} position="top" isMobile={isMobile}>
<span className="truncate text-sm">{title}</span>
</Tooltip>
</div>
{appendTitleElement && <span className="flex items-center flex-shrink-0">{appendTitleElement}</span>}
</div>
<div
className={cn(
"group min-h-[52px] flex w-full flex-col items-center justify-between gap-3 px-6 py-4 text-sm border-b border-custom-border-200 bg-custom-background-100 hover:bg-custom-background-90 ",
{
"xl:gap-5 xl:py-0 xl:flex-row": isSidebarOpen,
"lg:gap-5 lg:py-0 lg:flex-row": !isSidebarOpen,
},
className
)}
>
<div className="relative flex w-full items-center justify-between gap-3 overflow-hidden">
<div className="relative flex w-full items-center gap-3 overflow-hidden">
<ControlLink
href={itemLink}
target="_self"
className="flex items-center gap-4 truncate"
onClick={handleControlLinkClick}
disabled={disableLink}
>
{prependTitleElement && <span className="flex items-center flex-shrink-0">{prependTitleElement}</span>}
<Tooltip tooltipContent={title} position="top" isMobile={isMobile}>
<span className="truncate text-sm">{title}</span>
</Tooltip>
</ControlLink>
{appendTitleElement && <span className="flex items-center flex-shrink-0">{appendTitleElement}</span>}
</div>
<span className="h-6 w-96 flex-shrink-0" />
{quickActionElement && quickActionElement}
</div>
</ControlLink>
{actionableItems && (
<div className="absolute right-5 bottom-4 flex items-center gap-1.5">
<div className="relative flex items-center gap-4 sm:w-auto sm:flex-shrink-0 sm:justify-end items-center">
{actionableItems && (
<div
className={cn(
"relative flex items-center justify-start gap-4 flex-wrap w-full",
{
"xl:flex-nowrap xl:w-auto xl:flex-shrink-0": isSidebarOpen,
"lg:flex-nowrap lg:w-auto lg:flex-shrink-0": !isSidebarOpen,
},
actionItemContainerClassName
)}
>
{actionableItems}
</div>
</div>
)}
)}
</div>
</div>
);
};

View file

@ -161,7 +161,14 @@ export const CycleListItemAction: FC<Props> = observer((props) => {
selected={!!cycleDetails.is_favorite}
/>
)}
<CycleQuickActions parentRef={parentRef} cycleId={cycleId} projectId={projectId} workspaceSlug={workspaceSlug} />
<div className="hidden md:block">
<CycleQuickActions
parentRef={parentRef}
cycleId={cycleId}
projectId={projectId}
workspaceSlug={workspaceSlug}
/>
</div>
</>
);
});

View file

@ -18,6 +18,7 @@ import { generateQueryParams } from "@/helpers/router.helper";
import { useCycle } from "@/hooks/store";
import { useAppRouter } from "@/hooks/use-app-router";
import { usePlatformOS } from "@/hooks/use-platform-os";
import { CycleQuickActions } from "../quick-actions";
type TCyclesListItem = {
cycleId: string;
@ -122,8 +123,19 @@ export const CyclesListItem: FC<TCyclesListItem> = observer((props) => {
parentRef={parentRef}
/>
}
quickActionElement={
<div className="block md:hidden">
<CycleQuickActions
parentRef={parentRef}
cycleId={cycleId}
projectId={projectId}
workspaceSlug={workspaceSlug}
/>
</div>
}
isMobile={isMobile}
parentRef={parentRef}
isSidebarOpen={searchParams.has("peekCycle")}
/>
);
});

View file

@ -16,7 +16,7 @@ import { IssueProperties } from "@/components/issues/issue-layouts/properties";
// helpers
import { cn } from "@/helpers/common.helper";
// hooks
import { useIssueDetail, useProject } from "@/hooks/store";
import { useAppTheme, useIssueDetail, useProject } from "@/hooks/store";
import { TSelectionHelper } from "@/hooks/use-multiple-select";
import { usePlatformOS } from "@/hooks/use-platform-os";
// types
@ -65,6 +65,7 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
const workspaceSlug = routerWorkspaceSlug?.toString();
const projectId = routerProjectId?.toString();
// hooks
const { sidebarCollapsed: isSidebarCollapsed } = useAppTheme();
const { getProjectIdentifierById } = useProject();
const { getIsIssuePeeked, peekIssue, setPeekIssue, subIssues: subIssuesStore } = useIssueDetail();
@ -133,13 +134,15 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
<div
ref={issueRef}
className={cn(
"group/list-block min-h-11 relative flex flex-col md:flex-row md:items-center gap-3 bg-custom-background-100 hover:bg-custom-background-90 p-3 pl-1.5 text-sm transition-colors border border-transparent",
"group/list-block min-h-11 relative flex flex-col gap-3 bg-custom-background-100 hover:bg-custom-background-90 p-3 pl-1.5 text-sm transition-colors border border-transparent",
{
"border-custom-primary-70": getIsIssuePeeked(issue.id) && peekIssue?.nestingLevel === nestingLevel,
"border-custom-border-400": isIssueActive,
"last:border-b-transparent": !getIsIssuePeeked(issue.id) && !isIssueActive,
"bg-custom-primary-100/5 hover:bg-custom-primary-100/10": isIssueSelected,
"bg-custom-background-80": isCurrentBlockDragging,
"md:flex-row md:items-center": isSidebarCollapsed,
"lg:flex-row lg:items-center": !isSidebarCollapsed,
}
)}
onDragStart={() => {
@ -229,7 +232,7 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
id={`issue-${issue.id}`}
href={`/${workspaceSlug}/projects/${issue.project_id}/${issue.archived_at ? "archives/" : ""}issues/${
issue.id
}`}
}`}
onClick={() => handleIssuePeekOverview(issue)}
className="w-full truncate cursor-pointer text-sm text-custom-text-100"
disabled={!!issue?.tempId}
@ -241,7 +244,12 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
)}
</div>
{!issue?.tempId && (
<div className="block md:hidden border border-custom-border-300 rounded">
<div
className={cn("block border border-custom-border-300 rounded", {
"md:hidden": isSidebarCollapsed,
"lg:hidden": !isSidebarCollapsed,
})}
>
{quickActions({
issue,
parentRef: issueRef,
@ -253,14 +261,19 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
{!issue?.tempId ? (
<>
<IssueProperties
className="relative flex flex-wrap md:flex-grow md:flex-shrink-0 items-center gap-2 whitespace-nowrap"
className={`relative flex flex-wrap ${isSidebarCollapsed ? "md:flex-grow md:flex-shrink-0" : "lg:flex-grow lg:flex-shrink-0"} items-center gap-2 whitespace-nowrap`}
issue={issue}
isReadOnly={!canEditIssueProperties}
updateIssue={updateIssue}
displayProperties={displayProperties}
activeLayout="List"
/>
<div className="hidden md:block">
<div
className={cn("hidden", {
"md:flex": isSidebarCollapsed,
"lg:flex": !isSidebarCollapsed,
})}
>
{quickActions({
issue,
parentRef: issueRef,

View file

@ -154,12 +154,14 @@ export const ModuleListItemAction: FC<Props> = observer((props) => {
/>
)}
{workspaceSlug && projectId && (
<ModuleQuickActions
parentRef={parentRef}
moduleId={moduleId}
projectId={projectId.toString()}
workspaceSlug={workspaceSlug.toString()}
/>
<div className="hidden md:block">
<ModuleQuickActions
parentRef={parentRef}
moduleId={moduleId}
projectId={projectId.toString()}
workspaceSlug={workspaceSlug.toString()}
/>
</div>
)}
</>
);

View file

@ -9,7 +9,7 @@ import { Check, Info } from "lucide-react";
import { CircularProgressIndicator } from "@plane/ui";
// components
import { ListItem } from "@/components/core/list";
import { ModuleListItemAction } from "@/components/modules";
import { ModuleListItemAction, ModuleQuickActions } from "@/components/modules";
// helpers
import { generateQueryParams } from "@/helpers/router.helper";
// hooks
@ -109,6 +109,16 @@ export const ModuleListItem: React.FC<Props> = observer((props) => {
</button>
}
actionableItems={<ModuleListItemAction moduleId={moduleId} moduleDetails={moduleDetails} parentRef={parentRef} />}
quickActionElement={
<div className="block md:hidden">
<ModuleQuickActions
parentRef={parentRef}
moduleId={moduleId}
projectId={projectId.toString()}
workspaceSlug={workspaceSlug.toString()}
/>
</div>
}
isMobile={isMobile}
parentRef={parentRef}
/>

View file

@ -95,12 +95,14 @@ export const ViewListItemAction: FC<Props> = observer((props) => {
/>
)}
{projectId && workspaceSlug && (
<ViewQuickActions
parentRef={parentRef}
projectId={projectId.toString()}
view={view}
workspaceSlug={workspaceSlug.toString()}
/>
<div className="hidden md:block">
<ViewQuickActions
parentRef={parentRef}
projectId={projectId.toString()}
view={view}
workspaceSlug={workspaceSlug.toString()}
/>
</div>
)}
</>
);

View file

@ -9,7 +9,7 @@ import { IProjectView } from "@plane/types";
// components
import { Logo } from "@/components/common";
import { ListItem } from "@/components/core/list";
import { ViewListItemAction } from "@/components/views";
import { ViewListItemAction, ViewQuickActions } from "@/components/views";
// hooks
import { usePlatformOS } from "@/hooks/use-platform-os";
@ -40,6 +40,16 @@ export const ProjectViewListItem: FC<Props> = observer((props) => {
title={view.name}
itemLink={`/${workspaceSlug}/projects/${projectId}/views/${view.id}`}
actionableItems={<ViewListItemAction parentRef={parentRef} view={view} />}
quickActionElement={
<div className="block md:hidden">
<ViewQuickActions
parentRef={parentRef}
projectId={projectId.toString()}
view={view}
workspaceSlug={workspaceSlug.toString()}
/>
</div>
}
isMobile={isMobile}
parentRef={parentRef}
/>