[WEB-823] fix: quick add flicker and dropdown placement in calendar layout (#4054)

* chore: placement prop added in quick action menu

* fix: calenar layout quick action menu placement

* fix: calendar quick add flicker
This commit is contained in:
Anmol Singh Bhatia 2024-03-25 14:17:34 +05:30 committed by GitHub
parent 9f9e508bb7
commit 7e0037b06b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 29 additions and 12 deletions

View File

@ -89,7 +89,7 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
groupedIssueIds={groupedIssueIds} groupedIssueIds={groupedIssueIds}
layout={displayFilters?.calendar?.layout} layout={displayFilters?.calendar?.layout}
showWeekends={displayFilters?.calendar?.show_weekends ?? false} showWeekends={displayFilters?.calendar?.show_weekends ?? false}
quickActions={(issue, customActionButton) => ( quickActions={(issue, customActionButton, placement) => (
<QuickActions <QuickActions
customActionButton={customActionButton} customActionButton={customActionButton}
issue={issue} issue={issue}
@ -101,6 +101,7 @@ export const BaseCalendarRoot = observer((props: IBaseCalendarRoot) => {
handleArchive={async () => archiveIssue && archiveIssue(issue.project_id, issue.id)} handleArchive={async () => archiveIssue && archiveIssue(issue.project_id, issue.id)}
handleRestore={async () => restoreIssue && restoreIssue(issue.project_id, issue.id)} handleRestore={async () => restoreIssue && restoreIssue(issue.project_id, issue.id)}
readOnly={!isEditingAllowed || isCompletedCycle} readOnly={!isEditingAllowed || isCompletedCycle}
placements={placement}
/> />
)} )}
addIssuesToView={addIssuesToView} addIssuesToView={addIssuesToView}

View File

@ -1,4 +1,5 @@
import { useState } from "react"; import { useState } from "react";
import { Placement } from "@popperjs/core";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import type { import type {
IIssueDisplayFilterOptions, IIssueDisplayFilterOptions,
@ -37,7 +38,7 @@ type Props = {
groupedIssueIds: TGroupedIssues; groupedIssueIds: TGroupedIssues;
layout: "month" | "week" | undefined; layout: "month" | "week" | undefined;
showWeekends: boolean; showWeekends: boolean;
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode; quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
quickAddCallback?: ( quickAddCallback?: (
workspaceSlug: string, workspaceSlug: string,
projectId: string, projectId: string,

View File

@ -1,4 +1,5 @@
import { Droppable } from "@hello-pangea/dnd"; import { Droppable } from "@hello-pangea/dnd";
import { Placement } from "@popperjs/core";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { TGroupedIssues, TIssue, TIssueMap } from "@plane/types"; import { TGroupedIssues, TIssue, TIssueMap } from "@plane/types";
// components // components
@ -19,7 +20,7 @@ type Props = {
date: ICalendarDate; date: ICalendarDate;
issues: TIssueMap | undefined; issues: TIssueMap | undefined;
groupedIssueIds: TGroupedIssues; groupedIssueIds: TGroupedIssues;
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode; quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
enableQuickIssueCreate?: boolean; enableQuickIssueCreate?: boolean;
disableIssueCreation?: boolean; disableIssueCreation?: boolean;
quickAddCallback?: ( quickAddCallback?: (

View File

@ -1,4 +1,5 @@
import React from "react"; import React from "react";
import { Placement } from "@popperjs/core";
// components // components
import { TIssue, TIssueMap } from "@plane/types"; import { TIssue, TIssueMap } from "@plane/types";
import { CalendarIssueBlock } from "@/components/issues"; import { CalendarIssueBlock } from "@/components/issues";
@ -7,7 +8,7 @@ import { CalendarIssueBlock } from "@/components/issues";
type Props = { type Props = {
issues: TIssueMap | undefined; issues: TIssueMap | undefined;
issueId: string; issueId: string;
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode; quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
isDragging?: boolean; isDragging?: boolean;
}; };

View File

@ -1,4 +1,5 @@
import { useState, useRef } from "react"; import { useState, useRef } from "react";
import { Placement } from "@popperjs/core";
import { observer } from "mobx-react"; import { observer } from "mobx-react";
import { MoreHorizontal } from "lucide-react"; import { MoreHorizontal } from "lucide-react";
import { TIssue } from "@plane/types"; import { TIssue } from "@plane/types";
@ -14,7 +15,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
type Props = { type Props = {
issue: TIssue; issue: TIssue;
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode; quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
isDragging?: boolean; isDragging?: boolean;
}; };
@ -56,6 +57,11 @@ export const CalendarIssueBlock: React.FC<Props> = observer((props) => {
</div> </div>
); );
const isMenuActionRefAboveScreenBottom =
menuActionRef?.current && menuActionRef?.current?.getBoundingClientRect().bottom < window.innerHeight - 220;
const placement = isMenuActionRefAboveScreenBottom ? "bottom-end" : "top-end";
return ( return (
<ControlLink <ControlLink
href={`/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`} href={`/${workspaceSlug}/projects/${projectId}/issues/${issue.id}`}
@ -104,7 +110,7 @@ export const CalendarIssueBlock: React.FC<Props> = observer((props) => {
e.stopPropagation(); e.stopPropagation();
}} }}
> >
{quickActions(issue, customActionButton)} {quickActions(issue, customActionButton, placement)}
</div> </div>
</div> </div>
</> </>

View File

@ -1,5 +1,6 @@
import { useState } from "react"; import { useState } from "react";
import { Draggable } from "@hello-pangea/dnd"; import { Draggable } from "@hello-pangea/dnd";
import { Placement } from "@popperjs/core";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { TIssue, TIssueMap } from "@plane/types"; import { TIssue, TIssueMap } from "@plane/types";
// components // components
@ -12,7 +13,7 @@ type Props = {
date: Date; date: Date;
issues: TIssueMap | undefined; issues: TIssueMap | undefined;
issueIdList: string[] | null; issueIdList: string[] | null;
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode; quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
isDragDisabled?: boolean; isDragDisabled?: boolean;
enableQuickIssueCreate?: boolean; enableQuickIssueCreate?: boolean;
disableIssueCreation?: boolean; disableIssueCreation?: boolean;

View File

@ -230,7 +230,7 @@ export const CalendarQuickAddIssueForm: React.FC<Props> = observer((props) => {
{!isOpen && ( {!isOpen && (
<div <div
className={cn("md:hidden rounded md:border-[0.5px] border-custom-border-200 md:group-hover:block", { className={cn("md:opacity-0 rounded md:border-[0.5px] border-custom-border-200 md:group-hover:opacity-100", {
block: isMenuOpen, block: isMenuOpen,
})} })}
> >

View File

@ -1,3 +1,4 @@
import { Placement } from "@popperjs/core";
import { observer } from "mobx-react-lite"; import { observer } from "mobx-react-lite";
import { TGroupedIssues, TIssue, TIssueMap } from "@plane/types"; import { TGroupedIssues, TIssue, TIssueMap } from "@plane/types";
// components // components
@ -16,7 +17,7 @@ type Props = {
issues: TIssueMap | undefined; issues: TIssueMap | undefined;
groupedIssueIds: TGroupedIssues; groupedIssueIds: TGroupedIssues;
week: ICalendarWeek | undefined; week: ICalendarWeek | undefined;
quickActions: (issue: TIssue, customActionButton?: React.ReactElement) => React.ReactNode; quickActions: (issue: TIssue, customActionButton?: React.ReactElement, placement?: Placement) => React.ReactNode;
enableQuickIssueCreate?: boolean; enableQuickIssueCreate?: boolean;
disableIssueCreation?: boolean; disableIssueCreation?: boolean;
quickAddCallback?: ( quickAddCallback?: (

View File

@ -1,3 +1,4 @@
import { Placement } from "@popperjs/core";
import { TIssue } from "@plane/types"; import { TIssue } from "@plane/types";
export interface IQuickActionProps { export interface IQuickActionProps {
@ -10,4 +11,5 @@ export interface IQuickActionProps {
customActionButton?: React.ReactElement; customActionButton?: React.ReactElement;
portalElement?: HTMLDivElement | null; portalElement?: HTMLDivElement | null;
readOnly?: boolean; readOnly?: boolean;
placements?: Placement;
} }

View File

@ -31,6 +31,7 @@ export const CycleIssueQuickActions: React.FC<IQuickActionProps> = observer((pro
customActionButton, customActionButton,
portalElement, portalElement,
readOnly = false, readOnly = false,
placements = "bottom-start",
} = props; } = props;
// states // states
const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false); const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false);
@ -107,7 +108,7 @@ export const CycleIssueQuickActions: React.FC<IQuickActionProps> = observer((pro
/> />
<CustomMenu <CustomMenu
menuItemsClassName="z-[14]" menuItemsClassName="z-[14]"
placement="bottom-start" placement={placements}
customButton={customActionButton} customButton={customActionButton}
portalElement={portalElement} portalElement={portalElement}
maxHeight="lg" maxHeight="lg"

View File

@ -30,6 +30,7 @@ export const ModuleIssueQuickActions: React.FC<IQuickActionProps> = observer((pr
customActionButton, customActionButton,
portalElement, portalElement,
readOnly = false, readOnly = false,
placements = "bottom-start",
} = props; } = props;
// states // states
const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false); const [createUpdateIssueModal, setCreateUpdateIssueModal] = useState(false);
@ -106,7 +107,7 @@ export const ModuleIssueQuickActions: React.FC<IQuickActionProps> = observer((pr
/> />
<CustomMenu <CustomMenu
menuItemsClassName="z-[14]" menuItemsClassName="z-[14]"
placement="bottom-start" placement={placements}
customButton={customActionButton} customButton={customActionButton}
portalElement={portalElement} portalElement={portalElement}
maxHeight="lg" maxHeight="lg"

View File

@ -28,6 +28,7 @@ export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = observer((p
customActionButton, customActionButton,
portalElement, portalElement,
readOnly = false, readOnly = false,
placements = "bottom-start",
} = props; } = props;
// router // router
const router = useRouter(); const router = useRouter();
@ -107,7 +108,7 @@ export const ProjectIssueQuickActions: React.FC<IQuickActionProps> = observer((p
/> />
<CustomMenu <CustomMenu
menuItemsClassName="z-[14]" menuItemsClassName="z-[14]"
placement="bottom-start" placement={placements}
customButton={customActionButton} customButton={customActionButton}
portalElement={portalElement} portalElement={portalElement}
maxHeight="lg" maxHeight="lg"