[WEB-1517] chore: remove drag handle from list drag block (#4698)

* remove drag handle from list drag block

* align list group header with list item

* rearrange chevron for list subissues and rearrange spaces

* adding default draggable property to control link

* remove unnecessary dependencies for useEffect
This commit is contained in:
rahulramesha 2024-06-05 14:03:49 +05:30 committed by GitHub
parent 93a22034bd
commit 52d8d6e7ce
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 42 additions and 31 deletions

View File

@ -7,10 +7,11 @@ export type TControlLink = React.AnchorHTMLAttributes<HTMLAnchorElement> & {
target?: string; target?: string;
disabled?: boolean; disabled?: boolean;
className?: string; className?: string;
draggable?: boolean;
}; };
export const ControlLink = React.forwardRef<HTMLAnchorElement, TControlLink>((props, ref) => { export const ControlLink = React.forwardRef<HTMLAnchorElement, TControlLink>((props, ref) => {
const { href, onClick, children, target = "_self", disabled = false, className, ...rest } = props; const { href, onClick, children, target = "_self", disabled = false, className, draggable = false, ...rest } = props;
const LEFT_CLICK_EVENT_CODE = 0; const LEFT_CLICK_EVENT_CODE = 0;
const handleOnClick = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => { const handleOnClick = (event: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
@ -33,7 +34,15 @@ export const ControlLink = React.forwardRef<HTMLAnchorElement, TControlLink>((pr
if (disabled) return <>{children}</>; if (disabled) return <>{children}</>;
return ( return (
<a href={href} target={target} onClick={handleOnClick} {...rest} ref={ref} className={className}> <a
href={href}
target={target}
onClick={handleOnClick}
{...rest}
ref={ref}
className={className}
draggable={draggable}
>
{children} {children}
</a> </a>
); );

View File

@ -6,7 +6,7 @@ import { ChevronRight } from "lucide-react";
// types // types
import { TIssue, IIssueDisplayProperties, TIssueMap } from "@plane/types"; import { TIssue, IIssueDisplayProperties, TIssueMap } from "@plane/types";
// ui // ui
import { Spinner, Tooltip, ControlLink, DragHandle } from "@plane/ui"; import { Spinner, Tooltip, ControlLink, setToast, TOAST_TYPE } from "@plane/ui";
// components // components
import { MultipleSelectEntityAction } from "@/components/core"; import { MultipleSelectEntityAction } from "@/components/core";
import { IssueProperties } from "@/components/issues/issue-layouts/properties"; import { IssueProperties } from "@/components/issues/issue-layouts/properties";
@ -57,7 +57,6 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
} = props; } = props;
// ref // ref
const issueRef = useRef<HTMLDivElement | null>(null); const issueRef = useRef<HTMLDivElement | null>(null);
const dragHandleRef = useRef(null);
// hooks // hooks
const { workspaceSlug, projectId } = useAppRouter(); const { workspaceSlug, projectId } = useAppRouter();
const { getProjectIdentifierById } = useProject(); const { getProjectIdentifierById } = useProject();
@ -78,14 +77,12 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
useEffect(() => { useEffect(() => {
const element = issueRef.current; const element = issueRef.current;
const dragHandleElement = dragHandleRef.current;
if (!element || !dragHandleElement) return; if (!element) return;
return combine( return combine(
draggable({ draggable({
element, element,
dragHandle: dragHandleElement,
canDrag: () => canDrag, canDrag: () => canDrag,
getInitialData: () => ({ id: issueId, type: "ISSUE", groupId }), getInitialData: () => ({ id: issueId, type: "ISSUE", groupId }),
onDragStart: () => { onDragStart: () => {
@ -96,7 +93,7 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
}, },
}) })
); );
}, [issueRef?.current, canDrag, issueId, groupId, dragHandleRef?.current, setIsCurrentBlockDragging]); }, [canDrag, issueId, groupId, setIsCurrentBlockDragging]);
if (!issue) return null; if (!issue) return null;
@ -135,20 +132,19 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
"bg-custom-background-80": isCurrentBlockDragging, "bg-custom-background-80": isCurrentBlockDragging,
} }
)} )}
onDragStart={() => {
if (!canDrag) {
setToast({
type: TOAST_TYPE.WARNING,
title: "Cannot move issue",
message: "Drag and drop is disabled for the current grouping",
});
}
}}
> >
<div className="flex w-full truncate"> <div className="flex w-full truncate">
<div className="flex flex-grow items-center gap-3 truncate"> <div className="flex flex-grow items-center gap-1.5 truncate">
<div className="flex items-center gap-0.5"> <div className="flex items-center gap-2" style={isSubIssue ? { marginLeft } : {}}>
{/* drag handle */}
<div className="size-4 flex items-center group/drag-handle">
<DragHandle
ref={dragHandleRef}
disabled={!canDrag}
className={cn("opacity-0 group-hover/drag-handle:opacity-100", {
"opacity-100": isCurrentBlockDragging,
})}
/>
</div>
{/* select checkbox */} {/* select checkbox */}
{projectId && canEditIssueProperties && ( {projectId && canEditIssueProperties && (
<Tooltip <Tooltip
@ -177,8 +173,14 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
</div> </div>
</Tooltip> </Tooltip>
)} )}
{displayProperties && displayProperties?.key && (
<div className="flex-shrink-0 text-xs font-medium text-custom-text-300">
{projectIdentifier}-{issue.sequence_id}
</div>
)}
{/* sub-issues chevron */} {/* sub-issues chevron */}
<div className="size-4 grid place-items-center flex-shrink-0" style={isSubIssue ? { marginLeft } : {}}> <div className="size-4 grid place-items-center flex-shrink-0">
{subIssuesCount > 0 && ( {subIssuesCount > 0 && (
<button <button
type="button" type="button"
@ -194,11 +196,6 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
</button> </button>
)} )}
</div> </div>
{displayProperties && displayProperties?.key && (
<div className="flex-shrink-0 text-xs font-medium text-custom-text-300">
{projectIdentifier}-{issue.sequence_id}
</div>
)}
{issue?.tempId !== undefined && ( {issue?.tempId !== undefined && (
<div className="absolute left-0 top-0 z-[99999] h-full w-full animate-pulse bg-custom-background-100/20" /> <div className="absolute left-0 top-0 z-[99999] h-full w-full animate-pulse bg-custom-background-100/20" />
@ -206,7 +203,12 @@ export const IssueBlock = observer((props: IssueBlockProps) => {
</div> </div>
{issue?.is_draft ? ( {issue?.is_draft ? (
<Tooltip tooltipContent={issue.name} isMobile={isMobile} position="top-left"> <Tooltip
tooltipContent={issue.name}
isMobile={isMobile}
position="top-left"
disabled={isCurrentBlockDragging}
>
<p className="truncate">{issue.name}</p> <p className="truncate">{issue.name}</p>
</Tooltip> </Tooltip>
) : ( ) : (

View File

@ -83,7 +83,7 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => {
return ( return (
<> <>
<div className="group/list-header relative w-full flex-shrink-0 flex items-center gap-2.5 py-1.5 pl-3.5"> <div className="group/list-header relative w-full flex-shrink-0 flex items-center gap-2 py-1.5">
{canSelectIssues && ( {canSelectIssues && (
<div className="flex-shrink-0 flex items-center w-3.5"> <div className="flex-shrink-0 flex items-center w-3.5">
<MultipleSelectGroupAction <MultipleSelectGroupAction
@ -98,7 +98,7 @@ export const HeaderGroupByCard = observer((props: IHeaderGroupByCard) => {
/> />
</div> </div>
)} )}
<div className="flex-shrink-0 grid place-items-center overflow-hidden pl-3"> <div className="flex-shrink-0 grid place-items-center overflow-hidden">
{icon ?? <CircleDashed className="size-3.5" strokeWidth={2} />} {icon ?? <CircleDashed className="size-3.5" strokeWidth={2} />}
</div> </div>

View File

@ -193,7 +193,7 @@ export const ListGroup = observer((props: Props) => {
"border-custom-error-200": isDraggingOverColumn && !!group.isDropDisabled, "border-custom-error-200": isDraggingOverColumn && !!group.isDropDisabled,
})} })}
> >
<div className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 px-3 py-1"> <div className="sticky top-0 z-[2] w-full flex-shrink-0 border-b border-custom-border-200 bg-custom-background-90 pl-2 pr-3 py-1">
<HeaderGroupByCard <HeaderGroupByCard
groupID={group.id} groupID={group.id}
icon={group.icon} icon={group.icon}

View File

@ -152,7 +152,7 @@ export const ListQuickAddIssueForm: FC<IListQuickAddIssueForm> = observer((props
</div> </div>
) : ( ) : (
<div <div
className="flex w-full cursor-pointer items-center gap-2.5 p-6 py-3 text-custom-text-350 hover:text-custom-text-300" className="flex w-full cursor-pointer items-center gap-2 px-2 py-3 text-custom-text-350 hover:text-custom-text-300"
onClick={() => setIsOpen(true)} onClick={() => setIsOpen(true)}
> >
<PlusIcon className="h-3.5 w-3.5 stroke-2" /> <PlusIcon className="h-3.5 w-3.5 stroke-2" />