From 58ea4d6ec9c53134fe4b5a20bd5d5630ed389300 Mon Sep 17 00:00:00 2001 From: Anmol Singh Bhatia <121005188+anmolsinghbhatia@users.noreply.github.com> Date: Wed, 11 Oct 2023 12:05:53 +0530 Subject: [PATCH] chore: integrate popper js (#2398) * chore: react-popper-js added * chore: integrate popper js in issue properties dropdown * chore: integrate popper js in custom menu component * chore: integrate popper js in custom select component * chore: integrate popper js in custom search select component * chore: popper js placement type added * chore: popper js placement type added --- .../automation/auto-archive-automation.tsx | 1 - web/components/core/theme/theme-switch.tsx | 1 - .../core/views/board-view/single-board.tsx | 8 +- .../core/views/board-view/single-issue.tsx | 4 +- .../core/views/list-view/single-list.tsx | 1 - .../spreadsheet-view/spreadsheet-view.tsx | 10 +- .../integration/github/select-repository.tsx | 1 - .../integration/jira/give-details.tsx | 1 - web/components/issues/main-content.tsx | 2 +- .../issues/peek-overview/header.tsx | 1 - web/components/issues/select/estimate.tsx | 1 - .../issues/sidebar-select/cycle.tsx | 1 - .../issues/sidebar-select/estimate.tsx | 7 +- .../issues/sidebar-select/module.tsx | 1 - .../issues/sidebar-select/priority.tsx | 5 +- .../issues/sidebar-select/state.tsx | 5 +- web/components/issues/sub-issues/root.tsx | 2 - .../issues/view-select/assignee.tsx | 2 - .../issues/view-select/estimate.tsx | 2 - web/components/issues/view-select/label.tsx | 2 - .../issues/view-select/priority.tsx | 7 +- .../modules/sidebar-select/select-lead.tsx | 1 - .../modules/sidebar-select/select-members.tsx | 1 - .../notifications/notification-card.tsx | 7 +- web/components/onboarding/user-details.tsx | 2 - web/components/pages/single-page-block.tsx | 4 +- .../project/create-project-modal.tsx | 1 - web/components/project/label-select.tsx | 72 +++---- web/components/project/member-select.tsx | 1 - web/components/project/members-select.tsx | 66 ++++--- web/components/project/priority-select.tsx | 156 ++++++++------- .../project/send-project-invitation-modal.tsx | 5 +- web/components/states/state-select.tsx | 67 ++++--- web/components/ui/dropdowns/custom-menu.tsx | 187 +++++++++--------- .../ui/dropdowns/custom-search-select.tsx | 91 +++++---- web/components/ui/dropdowns/custom-select.tsx | 137 +++++++------ web/components/ui/dropdowns/types.d.ts | 7 +- web/package.json | 2 + .../[workspaceSlug]/me/profile/index.tsx | 3 - .../projects/[projectId]/pages/[pageId].tsx | 7 +- .../projects/[projectId]/settings/members.tsx | 5 +- .../[workspaceSlug]/settings/members.tsx | 5 +- yarn.lock | 9 +- 43 files changed, 449 insertions(+), 452 deletions(-) diff --git a/web/components/automation/auto-archive-automation.tsx b/web/components/automation/auto-archive-automation.tsx index d0c9a1be6..5aed7e852 100644 --- a/web/components/automation/auto-archive-automation.tsx +++ b/web/components/automation/auto-archive-automation.tsx @@ -74,7 +74,6 @@ export const AutoArchiveAutomation: React.FC = ({ handleChange({ archive_in: val }); }} input - verticalPosition="bottom" width="w-full" disabled={disabled} > diff --git a/web/components/core/theme/theme-switch.tsx b/web/components/core/theme/theme-switch.tsx index 687998c25..56d07fbad 100644 --- a/web/components/core/theme/theme-switch.tsx +++ b/web/components/core/theme/theme-switch.tsx @@ -100,7 +100,6 @@ export const ThemeSwitch: React.FC = observer( }} input width="w-full" - position="right" > {THEMES_OBJ.map(({ value, label, type, icon }) => ( diff --git a/web/components/core/views/board-view/single-board.tsx b/web/components/core/views/board-view/single-board.tsx index 6d583e772..1325f8cab 100644 --- a/web/components/core/views/board-view/single-board.tsx +++ b/web/components/core/views/board-view/single-board.tsx @@ -255,15 +255,11 @@ export const SingleBoard: React.FC = (props) => { !isDraftIssuesPage && ( +
Add Issue - +
} - position="left" noBorder > = ({ {type && !isNotAllowed && ( setIsMenuActive(!isMenuActive)} > - + } > = (props) => { } - position="right" noBorder > setIsCreateIssueFormOpen(true)}> diff --git a/web/components/core/views/spreadsheet-view/spreadsheet-view.tsx b/web/components/core/views/spreadsheet-view/spreadsheet-view.tsx index 0d9214a36..3a5108410 100644 --- a/web/components/core/views/spreadsheet-view/spreadsheet-view.tsx +++ b/web/components/core/views/spreadsheet-view/spreadsheet-view.tsx @@ -255,7 +255,6 @@ export const SpreadsheetView: React.FC = ({ = ({ +
New Issue - +
} - position="left" - verticalPosition="top" optionsClassName="left-5 !w-36" noBorder > diff --git a/web/components/integration/github/select-repository.tsx b/web/components/integration/github/select-repository.tsx index b46942e6d..ddc5e3a8a 100644 --- a/web/components/integration/github/select-repository.tsx +++ b/web/components/integration/github/select-repository.tsx @@ -92,7 +92,6 @@ export const SelectRepository: React.FC = ({ )} } - position="right" optionsClassName="w-full" /> ); diff --git a/web/components/integration/jira/give-details.tsx b/web/components/integration/jira/give-details.tsx index 3fc5d9641..fa04c3404 100644 --- a/web/components/integration/jira/give-details.tsx +++ b/web/components/integration/jira/give-details.tsx @@ -143,7 +143,6 @@ export const JiraGetImportDetail: React.FC = () => { )} } - verticalPosition="top" > {projects && projects.length > 0 ? ( projects.map((project) => ( diff --git a/web/components/issues/main-content.tsx b/web/components/issues/main-content.tsx index c4c9a780a..810f8fc95 100644 --- a/web/components/issues/main-content.tsx +++ b/web/components/issues/main-content.tsx @@ -158,7 +158,7 @@ export const IssueMainContent: React.FC = ({ - + {siblingIssuesList ? ( siblingIssuesList.length > 0 ? ( <> diff --git a/web/components/issues/peek-overview/header.tsx b/web/components/issues/peek-overview/header.tsx index 266b2edb8..b607e4089 100644 --- a/web/components/issues/peek-overview/header.tsx +++ b/web/components/issues/peek-overview/header.tsx @@ -93,7 +93,6 @@ export const PeekOverviewHeader: React.FC = ({ m.key === mode)?.icon ?? ""} /> } - position="left" > {peekModes.map((mode) => ( diff --git a/web/components/issues/select/estimate.tsx b/web/components/issues/select/estimate.tsx index 0d910013b..7ac86f6b9 100644 --- a/web/components/issues/select/estimate.tsx +++ b/web/components/issues/select/estimate.tsx @@ -33,7 +33,6 @@ export const IssueEstimateSelect: React.FC = ({ value, onChange }) => { } onChange={onChange} - position="right" width="w-full min-w-[8rem]" noChevron > diff --git a/web/components/issues/sidebar-select/cycle.tsx b/web/components/issues/sidebar-select/cycle.tsx index 8fbfcf707..a8dffabce 100644 --- a/web/components/issues/sidebar-select/cycle.tsx +++ b/web/components/issues/sidebar-select/cycle.tsx @@ -91,7 +91,6 @@ export const SidebarCycleSelect: React.FC = ({ : handleCycleChange(incompleteCycles?.find((c) => c.id === value) as ICycle); }} width="w-full" - position="right" maxHeight="rg" disabled={disabled} > diff --git a/web/components/issues/sidebar-select/estimate.tsx b/web/components/issues/sidebar-select/estimate.tsx index 7ebdfe2b9..75c168853 100644 --- a/web/components/issues/sidebar-select/estimate.tsx +++ b/web/components/issues/sidebar-select/estimate.tsx @@ -20,17 +20,14 @@ export const SidebarEstimateSelect: React.FC = ({ value, onChange, disabl +
{estimatePoints?.find((e) => e.key === value)?.value ?? "No estimate"} - +
} onChange={onChange} disabled={disabled} diff --git a/web/components/issues/sidebar-select/module.tsx b/web/components/issues/sidebar-select/module.tsx index c9599bdf4..edb95b983 100644 --- a/web/components/issues/sidebar-select/module.tsx +++ b/web/components/issues/sidebar-select/module.tsx @@ -87,7 +87,6 @@ export const SidebarModuleSelect: React.FC = ({ : handleModuleChange(modules?.find((m) => m.id === value) as IModule); }} width="w-full" - position="right" maxHeight="rg" disabled={disabled} > diff --git a/web/components/issues/sidebar-select/priority.tsx b/web/components/issues/sidebar-select/priority.tsx index 543f79707..512aba5c6 100644 --- a/web/components/issues/sidebar-select/priority.tsx +++ b/web/components/issues/sidebar-select/priority.tsx @@ -18,8 +18,7 @@ type Props = { export const SidebarPrioritySelect: React.FC = ({ value, onChange, disabled = false }) => ( = ({ value, onChange, disabl {value ?? "None"} - + } value={value} onChange={onChange} diff --git a/web/components/issues/sidebar-select/state.tsx b/web/components/issues/sidebar-select/state.tsx index cf2cfe3b2..7ff4f13b8 100644 --- a/web/components/issues/sidebar-select/state.tsx +++ b/web/components/issues/sidebar-select/state.tsx @@ -39,7 +39,7 @@ export const SidebarStateSelect: React.FC = ({ value, onChange, disabled return ( +
{selectedState ? (
@@ -53,12 +53,11 @@ export const SidebarStateSelect: React.FC = ({ value, onChange, disabled ) : ( "None" )} - +
} value={value} onChange={onChange} optionsClassName="w-min" - position="left" disabled={disabled} > {states ? ( diff --git a/web/components/issues/sub-issues/root.tsx b/web/components/issues/sub-issues/root.tsx index 4b29b97c9..a2c6c81a4 100644 --- a/web/components/issues/sub-issues/root.tsx +++ b/web/components/issues/sub-issues/root.tsx @@ -247,7 +247,6 @@ export const SubIssuesRoot: React.FC = ({ parentIssue, user }) = } buttonClassName="whitespace-nowrap" - position="left" noBorder noChevron > @@ -283,7 +282,6 @@ export const SubIssuesRoot: React.FC = ({ parentIssue, user }) = } buttonClassName="whitespace-nowrap" - position="left" noBorder noChevron > diff --git a/web/components/issues/view-select/assignee.tsx b/web/components/issues/view-select/assignee.tsx index 1026f240d..807d343e2 100644 --- a/web/components/issues/view-select/assignee.tsx +++ b/web/components/issues/view-select/assignee.tsx @@ -113,10 +113,8 @@ export const ViewAssigneeSelect: React.FC = ({ {...(customButton ? { customButton: assigneeLabel } : { label: assigneeLabel })} multiple noChevron - position={position} disabled={isNotAllowed} onOpen={() => setFetchAssignees(true)} - selfPositioned={selfPositioned} width="w-full min-w-[12rem]" /> ); diff --git a/web/components/issues/view-select/estimate.tsx b/web/components/issues/view-select/estimate.tsx index bef060e77..0edf5e33f 100644 --- a/web/components/issues/view-select/estimate.tsx +++ b/web/components/issues/view-select/estimate.tsx @@ -74,8 +74,6 @@ export const ViewEstimateSelect: React.FC = ({ maxHeight="md" noChevron disabled={isNotAllowed} - position={position} - selfPositioned={selfPositioned} width="w-full min-w-[8rem]" > diff --git a/web/components/issues/view-select/label.tsx b/web/components/issues/view-select/label.tsx index 3a75763b2..ae3fe1f50 100644 --- a/web/components/issues/view-select/label.tsx +++ b/web/components/issues/view-select/label.tsx @@ -146,9 +146,7 @@ export const ViewLabelSelect: React.FC = ({ {...(customButton ? { customButton: labelsLabel } : { label: labelsLabel })} multiple noChevron - position={position} disabled={isNotAllowed} - selfPositioned={selfPositioned} footerOption={footerOption} width="w-full min-w-[12rem]" /> diff --git a/web/components/issues/view-select/priority.tsx b/web/components/issues/view-select/priority.tsx index 1bdbf3428..f19b682fc 100644 --- a/web/components/issues/view-select/priority.tsx +++ b/web/components/issues/view-select/priority.tsx @@ -59,8 +59,7 @@ export const ViewPrioritySelect: React.FC = ({ }} maxHeight="md" customButton={ - +
} noChevron disabled={isNotAllowed} - position={position} - selfPositioned={selfPositioned} > {PRIORITIES?.map((priority) => ( diff --git a/web/components/modules/sidebar-select/select-lead.tsx b/web/components/modules/sidebar-select/select-lead.tsx index e00a5db25..46e08af0b 100644 --- a/web/components/modules/sidebar-select/select-lead.tsx +++ b/web/components/modules/sidebar-select/select-lead.tsx @@ -65,7 +65,6 @@ export const SidebarLeadSelect: React.FC = ({ value, onChange }) => { } options={options} maxHeight="md" - position="right" onChange={onChange} /> diff --git a/web/components/modules/sidebar-select/select-members.tsx b/web/components/modules/sidebar-select/select-members.tsx index 185f70cec..7aa1e8e5e 100644 --- a/web/components/modules/sidebar-select/select-members.tsx +++ b/web/components/modules/sidebar-select/select-members.tsx @@ -64,7 +64,6 @@ export const SidebarMembersSelect: React.FC = ({ value, onChange }) => { options={options} onChange={onChange} maxHeight="md" - position="right" multiple /> diff --git a/web/components/notifications/notification-card.tsx b/web/components/notifications/notification-card.tsx index 29fe579a8..acbd1c0c9 100644 --- a/web/components/notifications/notification-card.tsx +++ b/web/components/notifications/notification-card.tsx @@ -214,12 +214,9 @@ export const NotificationCard: React.FC = (props) => { e.stopPropagation(); }} customButton={ - + } optionsClassName="!z-20" > diff --git a/web/components/onboarding/user-details.tsx b/web/components/onboarding/user-details.tsx index 2911bbc80..8ac8b2070 100644 --- a/web/components/onboarding/user-details.tsx +++ b/web/components/onboarding/user-details.tsx @@ -167,7 +167,6 @@ export const UserDetails: React.FC = ({ user }) => { } input width="w-full" - verticalPosition="top" > {USER_ROLES.map((item) => ( @@ -197,7 +196,6 @@ export const UserDetails: React.FC = ({ user }) => { } options={timeZoneOptions} onChange={onChange} - verticalPosition="top" optionsClassName="w-full" input /> diff --git a/web/components/pages/single-page-block.tsx b/web/components/pages/single-page-block.tsx index e4c1d94ac..18fba83bc 100644 --- a/web/components/pages/single-page-block.tsx +++ b/web/components/pages/single-page-block.tsx @@ -384,12 +384,12 @@ export const SinglePageBlock: React.FC = ({ setIsMenuActive(!isMenuActive)} > - + } > {block.issue ? ( diff --git a/web/components/project/create-project-modal.tsx b/web/components/project/create-project-modal.tsx index 5593d8c7c..e0afea1ce 100644 --- a/web/components/project/create-project-modal.tsx +++ b/web/components/project/create-project-modal.tsx @@ -418,7 +418,6 @@ export const CreateProjectModal: React.FC = ({ )} } - verticalPosition="top" noChevron /> ); diff --git a/web/components/project/label-select.tsx b/web/components/project/label-select.tsx index c155dea14..a34d778f9 100644 --- a/web/components/project/label-select.tsx +++ b/web/components/project/label-select.tsx @@ -1,13 +1,13 @@ -import React, { useRef, useState } from "react"; +import React, { useState } from "react"; import useSWR from "swr"; import { useRouter } from "next/router"; +// react-popper +import { usePopper } from "react-popper"; // services import issuesService from "services/issues.service"; -// hooks -import useDynamicDropdownPosition from "hooks/use-dynamic-dropdown"; // headless ui import { Combobox } from "@headlessui/react"; // component @@ -19,6 +19,7 @@ import { PlusIcon } from "lucide-react"; // types import { Tooltip } from "components/ui"; import { ICurrentUserResponse, IIssueLabels } from "types"; +import { Placement } from "@popperjs/core"; // constants import { PROJECT_ISSUE_LABELS } from "constants/fetch-keys"; @@ -31,6 +32,7 @@ type Props = { buttonClassName?: string; optionsClassName?: string; maxRender?: number; + placement?: Placement; hideDropdownArrow?: boolean; disabled?: boolean; user: ICurrentUserResponse | undefined; @@ -45,21 +47,25 @@ export const LabelSelect: React.FC = ({ buttonClassName = "", optionsClassName = "", maxRender = 2, + placement, hideDropdownArrow = false, disabled = false, user, }) => { const [query, setQuery] = useState(""); - const [isOpen, setIsOpen] = useState(false); const [fetchStates, setFetchStates] = useState(false); + const [referenceElement, setReferenceElement] = useState(null); + const [popperElement, setPopperElement] = useState(null); + const [labelModal, setLabelModal] = useState(false); const router = useRouter(); const { workspaceSlug } = router.query; - const dropdownBtn = useRef(null); - const dropdownOptions = useRef(null); + const { styles, attributes } = usePopper(referenceElement, popperElement, { + placement: placement ?? "bottom-start", + }); const { data: issueLabels } = useSWR( projectId && fetchStates ? PROJECT_ISSUE_LABELS(projectId) : null, @@ -131,8 +137,6 @@ export const LabelSelect: React.FC = ({ ); - useDynamicDropdownPosition(isOpen, () => setIsOpen(false), dropdownBtn, dropdownOptions); - const footerOption = ( -
- +
@@ -234,8 +240,8 @@ export const LabelSelect: React.FC = ({ )}
{footerOption} - -
+
+ ); }} diff --git a/web/components/project/member-select.tsx b/web/components/project/member-select.tsx index 4fcb04268..0d29e8e8d 100644 --- a/web/components/project/member-select.tsx +++ b/web/components/project/member-select.tsx @@ -77,7 +77,6 @@ export const MemberSelect: React.FC = ({ value, onChange, isDisabled = fa ] } maxHeight="md" - position="right" width="w-full" onChange={onChange} disabled={isDisabled} diff --git a/web/components/project/members-select.tsx b/web/components/project/members-select.tsx index 57523df8d..42dd89ef4 100644 --- a/web/components/project/members-select.tsx +++ b/web/components/project/members-select.tsx @@ -1,9 +1,10 @@ -import React, { useRef, useState } from "react"; +import React, { useState } from "react"; import { useRouter } from "next/router"; +// react-popper +import { usePopper } from "react-popper"; // hooks -import useDynamicDropdownPosition from "hooks/use-dynamic-dropdown"; import useProjectMembers from "hooks/use-project-members"; import useWorkspaceMembers from "hooks/use-workspace-members"; // headless ui @@ -15,6 +16,7 @@ import { ChevronDownIcon } from "@heroicons/react/20/solid"; import { CheckIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline"; // types import { IUser } from "types"; +import { Placement } from "@popperjs/core"; type Props = { value: string | string[]; @@ -25,6 +27,7 @@ type Props = { className?: string; buttonClassName?: string; optionsClassName?: string; + placement?: Placement; hideDropdownArrow?: boolean; disabled?: boolean; }; @@ -38,18 +41,22 @@ export const MembersSelect: React.FC = ({ className = "", buttonClassName = "", optionsClassName = "", + placement, hideDropdownArrow = false, disabled = false, }) => { const [query, setQuery] = useState(""); - const [isOpen, setIsOpen] = useState(false); const [fetchStates, setFetchStates] = useState(false); + const [referenceElement, setReferenceElement] = useState(null); + const [popperElement, setPopperElement] = useState(null); + const router = useRouter(); const { workspaceSlug } = router.query; - const dropdownBtn = useRef(null); - const dropdownOptions = useRef(null); + const { styles, attributes } = usePopper(referenceElement, popperElement, { + placement: placement ?? "bottom-start", + }); const { members } = useProjectMembers( workspaceSlug?.toString(), @@ -105,8 +112,6 @@ export const MembersSelect: React.FC = ({ ); - useDynamicDropdownPosition(isOpen, () => setIsOpen(false), dropdownBtn, dropdownOptions); - return ( = ({ multiple > {({ open }: { open: boolean }) => { - if (open) { - if (!isOpen) setIsOpen(true); - setFetchStates(true); - } else if (isOpen) setIsOpen(false); + if (open) setFetchStates(true); return ( <> - - {label} - {!hideDropdownArrow && !disabled && ( -