diff --git a/packages/ui/src/dropdowns/custom-menu.tsx b/packages/ui/src/dropdowns/custom-menu.tsx
index df2e99a3d..7ef99370f 100644
--- a/packages/ui/src/dropdowns/custom-menu.tsx
+++ b/packages/ui/src/dropdowns/custom-menu.tsx
@@ -1,17 +1,15 @@
import * as React from "react";
import ReactDOM from "react-dom";
-// react-popper
+import { Menu } from "@headlessui/react";
import { usePopper } from "react-popper";
+import { ChevronDown, MoreHorizontal } from "lucide-react";
// hooks
import { useDropdownKeyDown } from "../hooks/use-dropdown-key-down";
import useOutsideClickDetector from "../hooks/use-outside-click-detector";
-// headless ui
-import { Menu } from "@headlessui/react";
-// type
-import { ICustomMenuDropdownProps, ICustomMenuItemProps } from "./helper";
-// icons
-import { ChevronDown, MoreHorizontal } from "lucide-react";
+// helpers
import { cn } from "../../helpers";
+// types
+import { ICustomMenuDropdownProps, ICustomMenuItemProps } from "./helper";
const CustomMenu = (props: ICustomMenuDropdownProps) => {
const {
@@ -29,7 +27,6 @@ const CustomMenu = (props: ICustomMenuDropdownProps) => {
noChevron = false,
optionsClassName = "",
verticalEllipsis = false,
- width = "auto",
portalElement,
menuButtonOnClick,
tabIndex,
@@ -63,17 +60,16 @@ const CustomMenu = (props: ICustomMenuDropdownProps) => {
static
>
{
as="div"
ref={dropdownRef}
tabIndex={tabIndex}
- className={`relative w-min text-left ${className}`}
+ className={cn("relative w-min text-left", className)}
onKeyDown={handleKeyDown}
>
{({ open }) => (
diff --git a/packages/ui/src/dropdowns/custom-search-select.tsx b/packages/ui/src/dropdowns/custom-search-select.tsx
index f9af00c93..9695eb931 100644
--- a/packages/ui/src/dropdowns/custom-search-select.tsx
+++ b/packages/ui/src/dropdowns/custom-search-select.tsx
@@ -1,14 +1,12 @@
import React, { useRef, useState } from "react";
-
-// react-popper
import { usePopper } from "react-popper";
+import { Combobox } from "@headlessui/react";
+import { Check, ChevronDown, Search } from "lucide-react";
// hooks
import { useDropdownKeyDown } from "../hooks/use-dropdown-key-down";
import useOutsideClickDetector from "../hooks/use-outside-click-detector";
-// headless ui
-import { Combobox } from "@headlessui/react";
-// icons
-import { Check, ChevronDown, Search } from "lucide-react";
+// helpers
+import { cn } from "../../helpers";
// types
import { ICustomSearchSelectProps } from "./helper";
@@ -31,7 +29,6 @@ export const CustomSearchSelect = (props: ICustomSearchSelectProps) => {
onOpen,
optionsClassName = "",
value,
- width = "auto",
tabIndex,
} = props;
const [query, setQuery] = useState("");
@@ -70,7 +67,7 @@ export const CustomSearchSelect = (props: ICustomSearchSelectProps) => {
as="div"
ref={dropdownRef}
tabIndex={tabIndex}
- className={`relative flex-shrink-0 text-left ${className}`}
+ className={cn("relative flex-shrink-0 text-left", className)}
onKeyDown={handleKeyDown}
{...comboboxProps}
>
@@ -114,37 +111,33 @@ export const CustomSearchSelect = (props: ICustomSearchSelectProps) => {
)}
{isOpen && (
-
+
-
-
+
+
setQuery(e.target.value)}
- placeholder="Type to search..."
+ placeholder="Search"
displayValue={(assigned: any) => assigned?.name}
/>
{filteredOptions ? (
filteredOptions.length > 0 ? (
@@ -152,37 +145,31 @@ export const CustomSearchSelect = (props: ICustomSearchSelectProps) => {
- `flex cursor-pointer select-none items-center justify-between gap-2 truncate rounded px-1 py-1.5 ${
- active || selected ? "bg-custom-background-80" : ""
- } ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
+ className={({ active }) =>
+ cn(
+ "w-full truncate flex items-center justify-between gap-2 rounded px-1 py-1.5 cursor-pointer select-none",
+ {
+ "bg-custom-background-80": active,
+ }
+ )
}
+ onClick={() => {
+ if (!multiple) closeDropdown();
+ }}
>
- {({ active, selected }) => (
+ {({ selected }) => (
<>
- {option.content}
- {multiple ? (
-
-
-
- ) : (
-
- )}
+ {option.content}
+ {selected && }
>
)}
))
) : (
-
- No matching results
-
+
No matches found
)
) : (
-
Loading...
+
Loading...
)}
{footerOption}
diff --git a/packages/ui/src/dropdowns/custom-select.tsx b/packages/ui/src/dropdowns/custom-select.tsx
index 805368b4b..0fa183cb2 100644
--- a/packages/ui/src/dropdowns/custom-select.tsx
+++ b/packages/ui/src/dropdowns/custom-select.tsx
@@ -1,14 +1,12 @@
import React, { useRef, useState } from "react";
-
-// react-popper
import { usePopper } from "react-popper";
+import { Listbox } from "@headlessui/react";
+import { Check, ChevronDown } from "lucide-react";
// hooks
import { useDropdownKeyDown } from "../hooks/use-dropdown-key-down";
import useOutsideClickDetector from "../hooks/use-outside-click-detector";
-// headless ui
-import { Listbox } from "@headlessui/react";
-// icons
-import { Check, ChevronDown } from "lucide-react";
+// helpers
+import { cn } from "../../helpers";
// types
import { ICustomSelectItemProps, ICustomSelectProps } from "./helper";
@@ -28,7 +26,6 @@ const CustomSelect = (props: ICustomSelectProps) => {
onChange,
optionsClassName = "",
value,
- width = "auto",
tabIndex,
} = props;
// states
@@ -57,7 +54,7 @@ const CustomSelect = (props: ICustomSelectProps) => {
tabIndex={tabIndex}
value={value}
onChange={onChange}
- className={`relative flex-shrink-0 text-left ${className}`}
+ className={cn("relative flex-shrink-0 text-left", className)}
onKeyDown={handleKeyDown}
disabled={disabled}
>
@@ -94,24 +91,23 @@ const CustomSelect = (props: ICustomSelectProps) => {
)}
>
{isOpen && (
-
+ closeDropdown()} static>
-
{children}
+ {children}
)}
@@ -124,16 +120,20 @@ const Option = (props: ICustomSelectItemProps) => {
return (
- `cursor-pointer select-none truncate rounded px-1 py-1.5 ${
- active || selected ? "bg-custom-background-80" : ""
- } ${selected ? "text-custom-text-100" : "text-custom-text-200"} ${className}`
+ className={({ active }) =>
+ cn(
+ "cursor-pointer select-none truncate rounded px-1 py-1.5 text-custom-text-200",
+ {
+ "bg-custom-background-80": active,
+ },
+ className
+ )
}
>
{({ selected }) => (
{children}
- {selected &&
}
+ {selected &&
}
)}
diff --git a/packages/ui/src/dropdowns/helper.tsx b/packages/ui/src/dropdowns/helper.tsx
index 9c0ae0566..453a33b63 100644
--- a/packages/ui/src/dropdowns/helper.tsx
+++ b/packages/ui/src/dropdowns/helper.tsx
@@ -13,7 +13,6 @@ export interface IDropdownProps {
noChevron?: boolean;
onOpen?: () => void;
optionsClassName?: string;
- width?: "auto" | string;
placement?: Placement;
tabIndex?: number;
}
diff --git a/web/components/analytics/custom-analytics/select/project.tsx b/web/components/analytics/custom-analytics/select/project.tsx
index ee3dce6d6..3c08e1574 100644
--- a/web/components/analytics/custom-analytics/select/project.tsx
+++ b/web/components/analytics/custom-analytics/select/project.tsx
@@ -21,9 +21,9 @@ export const SelectProject: React.FC = observer((props) => {
value: projectDetails?.id,
query: `${projectDetails?.name} ${projectDetails?.identifier}`,
content: (
-
-
{projectDetails?.identifier}
- {projectDetails?.name}
+
+ {projectDetails?.identifier}
+ {projectDetails?.name}
),
};
@@ -42,7 +42,6 @@ export const SelectProject: React.FC
= observer((props) => {
.join(", ")
: "All projects"
}
- optionsClassName="min-w-full max-w-[20rem]"
multiple
/>
);
diff --git a/web/components/analytics/custom-analytics/select/segment.tsx b/web/components/analytics/custom-analytics/select/segment.tsx
index b45c1fa55..055665d9e 100644
--- a/web/components/analytics/custom-analytics/select/segment.tsx
+++ b/web/components/analytics/custom-analytics/select/segment.tsx
@@ -28,7 +28,6 @@ export const SelectSegment: React.FC = ({ value, onChange, params }) => {
}
onChange={onChange}
- width="w-full"
maxHeight="lg"
>
No value
diff --git a/web/components/analytics/custom-analytics/select/x-axis.tsx b/web/components/analytics/custom-analytics/select/x-axis.tsx
index 237582ba0..74ee99a77 100644
--- a/web/components/analytics/custom-analytics/select/x-axis.tsx
+++ b/web/components/analytics/custom-analytics/select/x-axis.tsx
@@ -24,7 +24,6 @@ export const SelectXAxis: React.FC = (props) => {
value={value}
label={{ANALYTICS_X_AXIS_VALUES.find((v) => v.value === value)?.label}}
onChange={onChange}
- width="w-full"
maxHeight="lg"
>
{ANALYTICS_X_AXIS_VALUES.map((item) => {
diff --git a/web/components/analytics/custom-analytics/select/y-axis.tsx b/web/components/analytics/custom-analytics/select/y-axis.tsx
index 604457945..9f66c6b54 100644
--- a/web/components/analytics/custom-analytics/select/y-axis.tsx
+++ b/web/components/analytics/custom-analytics/select/y-axis.tsx
@@ -15,7 +15,7 @@ export const SelectYAxis: React.FC = ({ value, onChange }) => (
value={value}
label={{ANALYTICS_Y_AXIS_VALUES.find((v) => v.value === value)?.label ?? "None"}}
onChange={onChange}
- width="w-full"
+ maxHeight="lg"
>
{ANALYTICS_Y_AXIS_VALUES.map((item) => (
diff --git a/web/components/automation/auto-archive-automation.tsx b/web/components/automation/auto-archive-automation.tsx
index 3d5f6352e..974efff3a 100644
--- a/web/components/automation/auto-archive-automation.tsx
+++ b/web/components/automation/auto-archive-automation.tsx
@@ -79,7 +79,6 @@ export const AutoArchiveAutomation: React.FC = observer((props) => {
handleChange({ archive_in: val });
}}
input
- width="w-full"
disabled={!isAdmin}
>
<>
diff --git a/web/components/automation/auto-close-automation.tsx b/web/components/automation/auto-close-automation.tsx
index 49dd77e10..8d6662c11 100644
--- a/web/components/automation/auto-close-automation.tsx
+++ b/web/components/automation/auto-close-automation.tsx
@@ -106,7 +106,6 @@ export const AutoCloseAutomation: React.FC = observer((props) => {
handleChange({ close_in: val });
}}
input
- width="w-full"
disabled={!isAdmin}
>
<>
@@ -161,7 +160,6 @@ export const AutoCloseAutomation: React.FC = observer((props) => {
}}
options={options}
disabled={!multipleOptions}
- width="w-full"
input
/>
diff --git a/web/components/core/activity.tsx b/web/components/core/activity.tsx
index 792102be0..b281b8c36 100644
--- a/web/components/core/activity.tsx
+++ b/web/components/core/activity.tsx
@@ -43,7 +43,7 @@ const IssueLink = ({ activity }: { activity: IIssueActivity }) => {
}`}
target={activity.issue === null ? "_self" : "_blank"}
rel={activity.issue === null ? "" : "noopener noreferrer"}
- className="inline-flex items-center gap-1 font-medium text-custom-text-100 hover:underline"
+ className="inline-flex items-center gap-1 font-medium text-custom-text-100 hover:underline whitespace-nowrap"
>
{activity.issue_detail ? `${activity.project_detail.identifier}-${activity.issue_detail.sequence_id}` : "Issue"}{" "}
{activity.issue_detail?.name}
@@ -123,7 +123,6 @@ const activityDetails: {
to
>
)}
- .
>
);
else
@@ -136,7 +135,6 @@ const activityDetails: {
from
>
)}
- .
>
);
},
@@ -181,7 +179,6 @@ const activityDetails: {
from
>
)}
- .
>
);
},
@@ -197,7 +194,6 @@ const activityDetails: {
of
>
)}
- .
>
),
icon: ,
@@ -214,7 +210,6 @@ const activityDetails: {
from
>
)}
- .
>
);
else
@@ -227,7 +222,6 @@ const activityDetails: {
for
>
)}
- .
>
);
},
@@ -297,7 +291,6 @@ const activityDetails: {
to
>
)}
- .
>
);
else if (activity.verb === "updated")
@@ -318,7 +311,6 @@ const activityDetails: {
from
>
)}
- .
>
);
else
@@ -339,7 +331,6 @@ const activityDetails: {
from
>
)}
- .
>
);
},
@@ -449,7 +440,6 @@ const activityDetails: {
of
>
)}
- .
>
),
icon: ,
@@ -466,7 +456,6 @@ const activityDetails: {
from
>
)}
- .
>
);
else
@@ -479,7 +468,6 @@ const activityDetails: {
for
>
)}
- .
>
);
},
@@ -498,7 +486,6 @@ const activityDetails: {
for
>
)}
- .
>
),
icon: ,
@@ -587,7 +574,6 @@ const activityDetails: {
for
>
)}
- .
>
),
icon: ,
@@ -604,7 +590,6 @@ const activityDetails: {
from
>
)}
- .
>
);
else
@@ -618,7 +603,6 @@ const activityDetails: {
for
>
)}
- .
>
);
},
@@ -636,7 +620,6 @@ const activityDetails: {
from
>
)}
- .
>
);
else
@@ -650,7 +633,6 @@ const activityDetails: {
for
>
)}
- .
>
);
},
diff --git a/web/components/core/theme/theme-switch.tsx b/web/components/core/theme/theme-switch.tsx
index 60ef272a2..bcd847a28 100644
--- a/web/components/core/theme/theme-switch.tsx
+++ b/web/components/core/theme/theme-switch.tsx
@@ -46,7 +46,6 @@ export const ThemeSwitch: FC = (props) => {
}
onChange={onChange}
input
- width="w-full z-20"
>
{THEME_OPTIONS.map((themeOption) => (
diff --git a/web/components/cycles/cycles-board-card.tsx b/web/components/cycles/cycles-board-card.tsx
index f6836269c..4dffd7b2f 100644
--- a/web/components/cycles/cycles-board-card.tsx
+++ b/web/components/cycles/cycles-board-card.tsx
@@ -246,7 +246,7 @@ export const CyclesBoardCard: FC = (props) => {
))}
-
+
{!isCompleted && isEditingAllowed && (
<>
diff --git a/web/components/cycles/cycles-list-item.tsx b/web/components/cycles/cycles-list-item.tsx
index d25364bcd..a4ce3941b 100644
--- a/web/components/cycles/cycles-list-item.tsx
+++ b/web/components/cycles/cycles-list-item.tsx
@@ -240,7 +240,7 @@ export const CyclesListItem: FC = (props) => {
))}
-
+
{!isCompleted && isEditingAllowed && (
<>
diff --git a/web/components/cycles/sidebar.tsx b/web/components/cycles/sidebar.tsx
index 81cefac50..33b404e9d 100644
--- a/web/components/cycles/sidebar.tsx
+++ b/web/components/cycles/sidebar.tsx
@@ -341,7 +341,7 @@ export const CycleDetailsSidebar: React.FC = observer((props) => {
{!isCompleted && isEditingAllowed && (
-
+
{
setTrackElement("CYCLE_PAGE_SIDEBAR");
diff --git a/web/components/dropdowns/cycle.tsx b/web/components/dropdowns/cycle.tsx
index 5a861a8f9..cf3bd1cfc 100644
--- a/web/components/dropdowns/cycle.tsx
+++ b/web/components/dropdowns/cycle.tsx
@@ -2,7 +2,6 @@ import { Fragment, ReactNode, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
-import { Placement } from "@popperjs/core";
import { Check, ChevronDown, Search } from "lucide-react";
// hooks
import { useApplication, useCycle } from "hooks/store";
@@ -14,21 +13,14 @@ import { ContrastIcon } from "@plane/ui";
import { cn } from "helpers/common.helper";
// types
import { ICycle } from "@plane/types";
-import { TButtonVariants } from "./types";
+import { TDropdownProps } from "./types";
-type Props = {
+type Props = TDropdownProps & {
button?: ReactNode;
- buttonClassName?: string;
- buttonContainerClassName?: string;
- buttonVariant: TButtonVariants;
- className?: string;
- disabled?: boolean;
dropdownArrow?: boolean;
onChange: (val: string | null) => void;
- placement?: Placement;
projectId: string;
value: string | null;
- tabIndex?: number;
};
type ButtonProps = {
@@ -291,6 +283,7 @@ export const CycleDropdown: React.FC = observer((props) => {
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
+ onClick={closeDropdown}
>
{({ selected }) => (
<>
diff --git a/web/components/dropdowns/date.tsx b/web/components/dropdowns/date.tsx
index 92f35b910..b346529dc 100644
--- a/web/components/dropdowns/date.tsx
+++ b/web/components/dropdowns/date.tsx
@@ -3,7 +3,6 @@ import { Popover } from "@headlessui/react";
import DatePicker from "react-datepicker";
import { usePopper } from "react-popper";
import { CalendarDays, X } from "lucide-react";
-// import "react-datepicker/dist/react-datepicker.css";
// hooks
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
import useOutsideClickDetector from "hooks/use-outside-click-detector";
@@ -11,24 +10,17 @@ import useOutsideClickDetector from "hooks/use-outside-click-detector";
import { renderFormattedDate } from "helpers/date-time.helper";
import { cn } from "helpers/common.helper";
// types
-import { TButtonVariants } from "./types";
-import { Placement } from "@popperjs/core";
+import { TDropdownProps } from "./types";
-type Props = {
- buttonClassName?: string;
- buttonContainerClassName?: string;
- buttonVariant: TButtonVariants;
- disabled?: boolean;
+type Props = TDropdownProps & {
icon?: React.ReactNode;
isClearable?: boolean;
minDate?: Date;
maxDate?: Date;
onChange: (val: Date | null) => void;
placeholder: string;
- placement?: Placement;
value: Date | string | null;
closeOnSelect?: boolean;
- tabIndex?: number;
};
type ButtonProps = {
@@ -118,6 +110,7 @@ export const DateDropdown: React.FC = (props) => {
buttonClassName = "",
buttonContainerClassName,
buttonVariant,
+ className = "",
disabled = false,
icon = ,
isClearable = true,
@@ -160,102 +153,103 @@ export const DateDropdown: React.FC = (props) => {
useOutsideClickDetector(dropdownRef, closeDropdown);
return (
-
- {({ close }) => (
- <>
-
-
-
- {isOpen && (
-
-
- {
- onChange(val);
- if (closeOnSelect) close();
- }}
- dateFormat="dd-MM-yyyy"
- minDate={minDate}
- maxDate={maxDate}
- calendarClassName="shadow-custom-shadow-rg rounded"
- inline
- />
-
-
+
+
+
+ onClick={openDropdown}
+ >
+ {buttonVariant === "border-with-text" ? (
+ onChange(null)}
+ />
+ ) : buttonVariant === "border-without-text" ? (
+ onChange(null)}
+ hideText
+ />
+ ) : buttonVariant === "background-with-text" ? (
+ onChange(null)}
+ />
+ ) : buttonVariant === "background-without-text" ? (
+ onChange(null)}
+ hideText
+ />
+ ) : buttonVariant === "transparent-with-text" ? (
+ onChange(null)}
+ />
+ ) : buttonVariant === "transparent-without-text" ? (
+ onChange(null)}
+ hideText
+ />
+ ) : null}
+
+
+ {isOpen && (
+
+
+ {
+ onChange(val);
+ if (closeOnSelect) closeDropdown();
+ }}
+ dateFormat="dd-MM-yyyy"
+ minDate={minDate}
+ maxDate={maxDate}
+ calendarClassName="shadow-custom-shadow-rg rounded"
+ inline
+ />
+
+
)}
);
diff --git a/web/components/dropdowns/estimate.tsx b/web/components/dropdowns/estimate.tsx
index 241a695fa..dbf766b9a 100644
--- a/web/components/dropdowns/estimate.tsx
+++ b/web/components/dropdowns/estimate.tsx
@@ -2,7 +2,6 @@ import { Fragment, ReactNode, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
-import { Placement } from "@popperjs/core";
import { Check, ChevronDown, Search, Triangle } from "lucide-react";
import sortBy from "lodash/sortBy";
// hooks
@@ -12,21 +11,14 @@ import useOutsideClickDetector from "hooks/use-outside-click-detector";
// helpers
import { cn } from "helpers/common.helper";
// types
-import { TButtonVariants } from "./types";
+import { TDropdownProps } from "./types";
-type Props = {
+type Props = TDropdownProps & {
button?: ReactNode;
- buttonClassName?: string;
- buttonContainerClassName?: string;
- buttonVariant: TButtonVariants;
- className?: string;
- disabled?: boolean;
dropdownArrow?: boolean;
onChange: (val: number | null) => void;
- placement?: Placement;
projectId: string;
value: number | null;
- tabIndex?: number;
};
type ButtonProps = {
@@ -280,6 +272,7 @@ export const EstimateDropdown: React.FC = observer((props) => {
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
+ onClick={closeDropdown}
>
{({ selected }) => (
<>
diff --git a/web/components/dropdowns/member/project-member.tsx b/web/components/dropdowns/member/project-member.tsx
index 581978d9d..0c733272d 100644
--- a/web/components/dropdowns/member/project-member.tsx
+++ b/web/components/dropdowns/member/project-member.tsx
@@ -217,6 +217,9 @@ export const ProjectMemberDropdown: React.FC = observer((props) => {
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
+ onClick={() => {
+ if (!multiple) closeDropdown();
+ }}
>
{({ selected }) => (
<>
diff --git a/web/components/dropdowns/member/types.d.ts b/web/components/dropdowns/member/types.d.ts
index f5f81a5c6..fbf52c969 100644
--- a/web/components/dropdowns/member/types.d.ts
+++ b/web/components/dropdowns/member/types.d.ts
@@ -1,26 +1,18 @@
-import { Placement } from "@popperjs/core";
-import { TButtonVariants } from "../types";
+import { TDropdownProps } from "../types";
-export type MemberDropdownProps = {
+export type MemberDropdownProps = TDropdownProps & {
button?: ReactNode;
- buttonClassName?: string;
- buttonContainerClassName?: string;
- buttonVariant: TButtonVariants;
- className?: string;
- disabled?: boolean;
dropdownArrow?: boolean;
placeholder?: string;
- placement?: Placement;
- tabIndex?: number;
} & (
- | {
- multiple: false;
- onChange: (val: string | null) => void;
- value: string | null;
- }
- | {
- multiple: true;
- onChange: (val: string[]) => void;
- value: string[];
- }
-);
+ | {
+ multiple: false;
+ onChange: (val: string | null) => void;
+ value: string | null;
+ }
+ | {
+ multiple: true;
+ onChange: (val: string[]) => void;
+ value: string[];
+ }
+ );
diff --git a/web/components/dropdowns/member/workspace-member.tsx b/web/components/dropdowns/member/workspace-member.tsx
index f50da72c8..4089e52b9 100644
--- a/web/components/dropdowns/member/workspace-member.tsx
+++ b/web/components/dropdowns/member/workspace-member.tsx
@@ -1,4 +1,4 @@
-import { Fragment, useState } from "react";
+import { Fragment, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
@@ -13,6 +13,8 @@ import { Avatar } from "@plane/ui";
import { cn } from "helpers/common.helper";
// types
import { MemberDropdownProps } from "./types";
+import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
+import useOutsideClickDetector from "hooks/use-outside-click-detector";
export const WorkspaceMemberDropdown: React.FC = observer((props) => {
const {
@@ -28,9 +30,13 @@ export const WorkspaceMemberDropdown: React.FC = observer((
placeholder = "Members",
placement,
value,
+ tabIndex,
} = props;
// states
const [query, setQuery] = useState("");
+ const [isOpen, setIsOpen] = useState(false);
+ // refs
+ const dropdownRef = useRef(null);
// popper-js refs
const [referenceElement, setReferenceElement] = useState(null);
const [popperElement, setPopperElement] = useState(null);
@@ -78,13 +84,24 @@ export const WorkspaceMemberDropdown: React.FC = observer((
};
if (multiple) comboboxProps.multiple = true;
+ const openDropdown = () => {
+ setIsOpen(true);
+ if (referenceElement) referenceElement.focus();
+ };
+ const closeDropdown = () => setIsOpen(false);
+ const handleKeyDown = useDropdownKeyDown(openDropdown, closeDropdown, isOpen);
+ useOutsideClickDetector(dropdownRef, closeDropdown);
+
return (
{button ? (
@@ -186,6 +203,9 @@ export const WorkspaceMemberDropdown: React.FC = observer((
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
+ onClick={() => {
+ if (!multiple) closeDropdown();
+ }}
>
{({ selected }) => (
<>
diff --git a/web/components/dropdowns/module.tsx b/web/components/dropdowns/module.tsx
index e0d6b52f7..9bce79460 100644
--- a/web/components/dropdowns/module.tsx
+++ b/web/components/dropdowns/module.tsx
@@ -2,7 +2,6 @@ import { Fragment, ReactNode, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
-import { Placement } from "@popperjs/core";
import { Check, ChevronDown, Search } from "lucide-react";
// hooks
import { useApplication, useModule } from "hooks/store";
@@ -14,21 +13,14 @@ import { DiceIcon } from "@plane/ui";
import { cn } from "helpers/common.helper";
// types
import { IModule } from "@plane/types";
-import { TButtonVariants } from "./types";
+import { TDropdownProps } from "./types";
-type Props = {
+type Props = TDropdownProps & {
button?: ReactNode;
- buttonClassName?: string;
- buttonContainerClassName?: string;
- buttonVariant: TButtonVariants;
- className?: string;
- disabled?: boolean;
dropdownArrow?: boolean;
onChange: (val: string | null) => void;
- placement?: Placement;
projectId: string;
value: string | null;
- tabIndex?: number;
};
type DropdownOptions =
@@ -186,9 +178,7 @@ export const ModuleDropdown: React.FC = observer((props) => {
as="div"
ref={dropdownRef}
tabIndex={tabIndex}
- className={cn("h-full flex-shrink-0", {
- className,
- })}
+ className={cn("h-full flex-shrink-0", className)}
value={value}
onChange={onChange}
disabled={disabled}
@@ -291,6 +281,7 @@ export const ModuleDropdown: React.FC = observer((props) => {
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
+ onClick={closeDropdown}
>
{({ selected }) => (
<>
diff --git a/web/components/dropdowns/priority.tsx b/web/components/dropdowns/priority.tsx
index bd20c7965..afcfaa8e4 100644
--- a/web/components/dropdowns/priority.tsx
+++ b/web/components/dropdowns/priority.tsx
@@ -1,7 +1,6 @@
import { Fragment, ReactNode, useRef, useState } from "react";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
-import { Placement } from "@popperjs/core";
import { Check, ChevronDown, Search } from "lucide-react";
// hooks
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
@@ -12,23 +11,17 @@ import { PriorityIcon } from "@plane/ui";
import { cn } from "helpers/common.helper";
// types
import { TIssuePriorities } from "@plane/types";
-import { TButtonVariants } from "./types";
+import { TDropdownProps } from "./types";
// constants
import { ISSUE_PRIORITIES } from "constants/issue";
+import { useTheme } from "next-themes";
-type Props = {
+type Props = TDropdownProps & {
button?: ReactNode;
- buttonClassName?: string;
- buttonContainerClassName?: string;
- buttonVariant: TButtonVariants;
- className?: string;
- disabled?: boolean;
dropdownArrow?: boolean;
highlightUrgent?: boolean;
onChange: (val: TIssuePriorities) => void;
- placement?: Placement;
value: TIssuePriorities;
- tabIndex?: number;
};
type ButtonProps = {
@@ -236,43 +229,20 @@ export const PriorityDropdown: React.FC = (props) => {
},
],
});
+ // next-themes
+ // TODO: remove this after new theming implementation
+ const { resolvedTheme } = useTheme();
- const options = ISSUE_PRIORITIES.map((priority) => {
- const priorityClasses = {
- urgent: "bg-red-500/20 text-red-950 border-red-500",
- high: "bg-orange-500/20 text-orange-950 border-orange-500",
- medium: "bg-yellow-500/20 text-yellow-950 border-yellow-500",
- low: "bg-custom-primary-100/20 text-custom-primary-950 border-custom-primary-100",
- none: "bg-custom-background-80 border-custom-border-300",
- };
-
- return {
- value: priority.key,
- query: priority.key,
- content: (
-
- ),
- };
- });
+ const options = ISSUE_PRIORITIES.map((priority) => ({
+ value: priority.key,
+ query: priority.key,
+ content: (
+
+ ),
+ }));
const filteredOptions =
query === "" ? options : options.filter((o) => o.query.toLowerCase().includes(query.toLowerCase()));
@@ -325,14 +295,18 @@ export const PriorityDropdown: React.FC = (props) => {
{buttonVariant === "border-with-text" ? (
) : buttonVariant === "border-without-text" ? (
= (props) => {
) : buttonVariant === "background-with-text" ? (
) : buttonVariant === "background-without-text" ? (
= (props) => {
) : buttonVariant === "transparent-with-text" ? (
) : buttonVariant === "transparent-without-text" ? (
= (props) => {
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
+ onClick={closeDropdown}
>
{({ selected }) => (
<>
diff --git a/web/components/dropdowns/project.tsx b/web/components/dropdowns/project.tsx
index 7649e1d75..512cba528 100644
--- a/web/components/dropdowns/project.tsx
+++ b/web/components/dropdowns/project.tsx
@@ -2,7 +2,6 @@ import { Fragment, ReactNode, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
-import { Placement } from "@popperjs/core";
import { Check, ChevronDown, Search } from "lucide-react";
// hooks
import { useProject } from "hooks/store";
@@ -13,20 +12,13 @@ import { cn } from "helpers/common.helper";
import { renderEmoji } from "helpers/emoji.helper";
// types
import { IProject } from "@plane/types";
-import { TButtonVariants } from "./types";
+import { TDropdownProps } from "./types";
-type Props = {
+type Props = TDropdownProps & {
button?: ReactNode;
- buttonClassName?: string;
- buttonContainerClassName?: string;
- buttonVariant: TButtonVariants;
- className?: string;
- disabled?: boolean;
dropdownArrow?: boolean;
onChange: (val: string) => void;
- placement?: Placement;
value: string | null;
- tabIndex?: number;
};
type ButtonProps = {
@@ -166,9 +158,7 @@ export const ProjectDropdown: React.FC = observer((props) => {
as="div"
ref={dropdownRef}
tabIndex={tabIndex}
- className={cn("h-full flex-shrink-0", {
- className,
- })}
+ className={cn("h-full flex-shrink-0", className)}
value={value}
onChange={onChange}
disabled={disabled}
@@ -271,6 +261,7 @@ export const ProjectDropdown: React.FC = observer((props) => {
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
+ onClick={closeDropdown}
>
{({ selected }) => (
<>
diff --git a/web/components/dropdowns/state.tsx b/web/components/dropdowns/state.tsx
index 25073901a..501dd609b 100644
--- a/web/components/dropdowns/state.tsx
+++ b/web/components/dropdowns/state.tsx
@@ -2,7 +2,6 @@ import { Fragment, ReactNode, useEffect, useRef, useState } from "react";
import { observer } from "mobx-react-lite";
import { Combobox } from "@headlessui/react";
import { usePopper } from "react-popper";
-import { Placement } from "@popperjs/core";
import { Check, ChevronDown, Search } from "lucide-react";
// hooks
import { useApplication, useProjectState } from "hooks/store";
@@ -14,21 +13,14 @@ import { StateGroupIcon } from "@plane/ui";
import { cn } from "helpers/common.helper";
// types
import { IState } from "@plane/types";
-import { TButtonVariants } from "./types";
+import { TDropdownProps } from "./types";
-type Props = {
+type Props = TDropdownProps & {
button?: ReactNode;
- buttonClassName?: string;
- buttonContainerClassName?: string;
- buttonVariant: TButtonVariants;
- className?: string;
- disabled?: boolean;
dropdownArrow?: boolean;
onChange: (val: string) => void;
- placement?: Placement;
projectId: string;
value: string;
- tabIndex?: number;
};
type ButtonProps = {
@@ -159,9 +151,7 @@ export const StateDropdown: React.FC = observer((props) => {
as="div"
ref={dropdownRef}
tabIndex={tabIndex}
- className={cn("h-full flex-shrink-0", {
- className,
- })}
+ className={cn("h-full flex-shrink-0", className)}
value={value}
onChange={onChange}
disabled={disabled}
@@ -264,6 +254,7 @@ export const StateDropdown: React.FC = observer((props) => {
active ? "bg-custom-background-80" : ""
} ${selected ? "text-custom-text-100" : "text-custom-text-200"}`
}
+ onClick={closeDropdown}
>
{({ selected }) => (
<>
diff --git a/web/components/dropdowns/types.d.ts b/web/components/dropdowns/types.d.ts
index f23914daa..0b8ef9907 100644
--- a/web/components/dropdowns/types.d.ts
+++ b/web/components/dropdowns/types.d.ts
@@ -1,3 +1,5 @@
+import { Placement } from "@popperjs/core";
+
export type TButtonVariants =
| "border-with-text"
| "border-without-text"
@@ -5,3 +7,13 @@ export type TButtonVariants =
| "background-without-text"
| "transparent-with-text"
| "transparent-without-text";
+
+export type TDropdownProps = {
+ buttonClassName?: string;
+ buttonContainerClassName?: string;
+ buttonVariant: TButtonVariants;
+ className?: string;
+ disabled?: boolean;
+ placement?: Placement;
+ tabIndex?: number;
+};
diff --git a/web/components/headers/cycle-issues.tsx b/web/components/headers/cycle-issues.tsx
index f97be5244..949c192fa 100644
--- a/web/components/headers/cycle-issues.tsx
+++ b/web/components/headers/cycle-issues.tsx
@@ -180,7 +180,6 @@ export const CycleIssuesHeader: React.FC = observer(() => {
>
}
className="ml-1.5 flex-shrink-0"
- width="auto"
placement="bottom-start"
>
{currentProjectCycleIds?.map((cycleId) => (
diff --git a/web/components/headers/module-issues.tsx b/web/components/headers/module-issues.tsx
index 3b60e69ab..52d7ef4f9 100644
--- a/web/components/headers/module-issues.tsx
+++ b/web/components/headers/module-issues.tsx
@@ -183,7 +183,6 @@ export const ModuleIssuesHeader: React.FC = observer(() => {
>
}
className="ml-1.5 flex-shrink-0"
- width="auto"
placement="bottom-start"
>
{projectModuleIds?.map((moduleId) => (
diff --git a/web/components/integration/jira/give-details.tsx b/web/components/integration/jira/give-details.tsx
index 90dfe404b..efeca487a 100644
--- a/web/components/integration/jira/give-details.tsx
+++ b/web/components/integration/jira/give-details.tsx
@@ -161,7 +161,6 @@ export const JiraGetImportDetail: React.FC = observer(() => {
@@ -172,6 +171,7 @@ export const JiraGetImportDetail: React.FC = observer(() => {
)}
}
+ optionsClassName="w-full"
>
{workspaceProjectIds && workspaceProjectIds.length > 0 ? (
workspaceProjectIds.map((projectId) => {
diff --git a/web/components/integration/jira/import-users.tsx b/web/components/integration/jira/import-users.tsx
index dc23d6a7b..63cf84b4f 100644
--- a/web/components/integration/jira/import-users.tsx
+++ b/web/components/integration/jira/import-users.tsx
@@ -82,7 +82,7 @@ export const JiraImportUsers: FC = () => {
input
value={value}
onChange={onChange}
- width="w-full"
+ optionsClassName="w-full"
label={{Boolean(value) ? value : ("Ignore" as any)}}
>
Invite by email
diff --git a/web/components/issues/issue-detail/cycle-select.tsx b/web/components/issues/issue-detail/cycle-select.tsx
index 5185ac790..88d0d4297 100644
--- a/web/components/issues/issue-detail/cycle-select.tsx
+++ b/web/components/issues/issue-detail/cycle-select.tsx
@@ -93,7 +93,6 @@ export const IssueCycleSelect: React.FC = observer((props) =>
}
- width="max-w-[10rem]"
noChevron
disabled={disableSelect}
/>
diff --git a/web/components/issues/issue-detail/module-select.tsx b/web/components/issues/issue-detail/module-select.tsx
index 4ac5f1fa5..05d7035b6 100644
--- a/web/components/issues/issue-detail/module-select.tsx
+++ b/web/components/issues/issue-detail/module-select.tsx
@@ -93,7 +93,6 @@ export const IssueModuleSelect: React.FC
= observer((props)
}
- width="max-w-[10rem]"
noChevron
disabled={disableSelect}
/>
diff --git a/web/components/issues/issue-layouts/kanban/headers/group-by-card.tsx b/web/components/issues/issue-layouts/kanban/headers/group-by-card.tsx
index 3bb49106b..512a071bc 100644
--- a/web/components/issues/issue-layouts/kanban/headers/group-by-card.tsx
+++ b/web/components/issues/issue-layouts/kanban/headers/group-by-card.tsx
@@ -135,7 +135,6 @@ export const HeaderGroupByCard: FC = observer((props) => {
{!disableIssueCreation &&
(renderExistingIssueModal ? (
diff --git a/web/components/issues/issue-layouts/list/block.tsx b/web/components/issues/issue-layouts/list/block.tsx
index 820f98fdd..da63a834e 100644
--- a/web/components/issues/issue-layouts/list/block.tsx
+++ b/web/components/issues/issue-layouts/list/block.tsx
@@ -73,7 +73,7 @@ export const IssueBlock: React.FC = observer((props: IssueBlock
{!issue?.tempId ? (
<>
diff --git a/web/components/issues/issue-layouts/spreadsheet/columns/header-column.tsx b/web/components/issues/issue-layouts/spreadsheet/columns/header-column.tsx
index 040000218..dc9f8c7c6 100644
--- a/web/components/issues/issue-layouts/spreadsheet/columns/header-column.tsx
+++ b/web/components/issues/issue-layouts/spreadsheet/columns/header-column.tsx
@@ -62,7 +62,6 @@ export const SpreadsheetHeaderColumn = (props: Props) => {
}
- width="xl"
placement="bottom-end"
>
handleOrderBy(propertyDetails.ascendingOrderKey, property)}>
diff --git a/web/components/issues/sub-issues/issue-list-item.tsx b/web/components/issues/sub-issues/issue-list-item.tsx
index 0e8fe76a2..033473470 100644
--- a/web/components/issues/sub-issues/issue-list-item.tsx
+++ b/web/components/issues/sub-issues/issue-list-item.tsx
@@ -134,7 +134,7 @@ export const IssueListItem: React.FC = observer((props) => {
-
+
{disabled && (
handleIssueCrudState("update", parentIssueId, issue)}>
diff --git a/web/components/issues/view-select/estimate.tsx b/web/components/issues/view-select/estimate.tsx
index bcad6a51c..c9b29af95 100644
--- a/web/components/issues/view-select/estimate.tsx
+++ b/web/components/issues/view-select/estimate.tsx
@@ -42,7 +42,7 @@ export const ViewEstimateSelect: React.FC
= observer((props) => {
maxHeight="md"
noChevron
disabled={disabled}
- width="w-full min-w-[8rem]"
+ optionsClassName="w-full"
>
<>
diff --git a/web/components/modules/module-card-item.tsx b/web/components/modules/module-card-item.tsx
index f69e6ba2e..f9236ef10 100644
--- a/web/components/modules/module-card-item.tsx
+++ b/web/components/modules/module-card-item.tsx
@@ -232,7 +232,7 @@ export const ModuleCardItem: React.FC = observer((props) => {
))}
-
+
{isEditingAllowed && (
<>
diff --git a/web/components/modules/module-list-item.tsx b/web/components/modules/module-list-item.tsx
index bb868d7e0..c24e75198 100644
--- a/web/components/modules/module-list-item.tsx
+++ b/web/components/modules/module-list-item.tsx
@@ -209,7 +209,7 @@ export const ModuleListItem: React.FC = observer((props) => {
))}
-
+
{isEditingAllowed && (
<>
diff --git a/web/components/modules/sidebar.tsx b/web/components/modules/sidebar.tsx
index 803e1879b..5b2c8f170 100644
--- a/web/components/modules/sidebar.tsx
+++ b/web/components/modules/sidebar.tsx
@@ -291,7 +291,7 @@ export const ModuleDetailsSidebar: React.FC = observer((props) => {
{isEditingAllowed && (
-
+
setModuleDeleteModal(true)}>
diff --git a/web/components/notifications/select-snooze-till-modal.tsx b/web/components/notifications/select-snooze-till-modal.tsx
index b8312d7d0..ab3497bb8 100644
--- a/web/components/notifications/select-snooze-till-modal.tsx
+++ b/web/components/notifications/select-snooze-till-modal.tsx
@@ -200,7 +200,7 @@ export const SnoozeNotificationModal: FC = (props) => {
)}
}
- width="w-full"
+ optionsClassName="w-full"
input
>
diff --git a/web/components/pages/pages-list/list-item.tsx b/web/components/pages/pages-list/list-item.tsx
index 99b50e3c0..960e222ce 100644
--- a/web/components/pages/pages-list/list-item.tsx
+++ b/web/components/pages/pages-list/list-item.tsx
@@ -235,7 +235,7 @@ export const PagesListItem: FC
= observer(({ pageId, projectId }
>
-
+
{archived_at ? (
<>
{userCanArchive && (
diff --git a/web/components/project/member-select.tsx b/web/components/project/member-select.tsx
index e525bd6f5..e019a29e7 100644
--- a/web/components/project/member-select.tsx
+++ b/web/components/project/member-select.tsx
@@ -69,7 +69,6 @@ export const MemberSelect: React.FC = observer((props) => {
]
}
maxHeight="md"
- width="w-full"
onChange={onChange}
disabled={isDisabled}
/>
diff --git a/web/components/project/send-project-invitation-modal.tsx b/web/components/project/send-project-invitation-modal.tsx
index db7572dd9..b165a40ae 100644
--- a/web/components/project/send-project-invitation-modal.tsx
+++ b/web/components/project/send-project-invitation-modal.tsx
@@ -236,7 +236,7 @@ export const SendProjectInvitationModal: React.FC = observer((props) => {
onChange(val);
}}
options={options}
- width="w-full min-w-[12rem]"
+ optionsClassName="w-full"
/>
);
}}
@@ -266,7 +266,7 @@ export const SendProjectInvitationModal: React.FC = observer((props) => {
}
input
- width="w-full"
+ optionsClassName="w-full"
>
{Object.entries(ROLE).map(([key, label]) => {
if (parseInt(key) > (currentProjectRole ?? EUserProjectRoles.GUEST)) return null;
diff --git a/web/components/states/create-state-modal.tsx b/web/components/states/create-state-modal.tsx
index 95ceb894f..db91bb6b0 100644
--- a/web/components/states/create-state-modal.tsx
+++ b/web/components/states/create-state-modal.tsx
@@ -160,7 +160,7 @@ export const CreateStateModal: React.FC = observer((props) => {
value={value}
label={GROUP_CHOICES[value as keyof typeof GROUP_CHOICES]}
onChange={onChange}
- width="w-full"
+ optionsClassName="w-full"
input
>
{Object.keys(GROUP_CHOICES).map((key) => (
diff --git a/web/components/views/view-list-item.tsx b/web/components/views/view-list-item.tsx
index 1b04dbff0..8da507539 100644
--- a/web/components/views/view-list-item.tsx
+++ b/web/components/views/view-list-item.tsx
@@ -123,7 +123,7 @@ export const ProjectViewListItem: React.FC = observer((props) => {
))}
-
+
{isEditingAllowed && (
<>
= observer((props) => {
}
buttonClassName="!border-[0.5px] !border-custom-border-200 !shadow-none"
input
- width="w-full"
+ optionsClassName="w-full"
>
{ORGANIZATION_SIZE.map((item) => (
diff --git a/web/components/workspace/send-workspace-invitation-modal.tsx b/web/components/workspace/send-workspace-invitation-modal.tsx
index 3fd818402..35b5963d0 100644
--- a/web/components/workspace/send-workspace-invitation-modal.tsx
+++ b/web/components/workspace/send-workspace-invitation-modal.tsx
@@ -165,7 +165,7 @@ export const SendWorkspaceInvitationModal: React.FC = observer((props) =>
value={value}
label={{ROLE[value]}}
onChange={onChange}
- width="w-full"
+ optionsClassName="w-full"
input
>
{Object.entries(ROLE).map(([key, value]) => {
diff --git a/web/components/workspace/settings/workspace-details.tsx b/web/components/workspace/settings/workspace-details.tsx
index a309012d1..3063855fd 100644
--- a/web/components/workspace/settings/workspace-details.tsx
+++ b/web/components/workspace/settings/workspace-details.tsx
@@ -247,7 +247,7 @@ export const WorkspaceDetails: FC = observer(() => {
value={value}
onChange={onChange}
label={ORGANIZATION_SIZE.find((c) => c === value) ?? "Select organization size"}
- width="w-full"
+ optionsClassName="w-full"
buttonClassName="!border-[0.5px] !border-custom-border-200 !shadow-none"
input
disabled={!isAdmin}
diff --git a/web/components/workspace/views/view-list-item.tsx b/web/components/workspace/views/view-list-item.tsx
index 25be61a59..1d9289037 100644
--- a/web/components/workspace/views/view-list-item.tsx
+++ b/web/components/workspace/views/view-list-item.tsx
@@ -54,7 +54,7 @@ export const GlobalViewListItem: React.FC = observer((props) => {
{totalFilters} {totalFilters === 1 ? "filter" : "filters"}
-
+
{
e.preventDefault();
diff --git a/web/pages/profile/index.tsx b/web/pages/profile/index.tsx
index 88333388a..3174c53f3 100644
--- a/web/pages/profile/index.tsx
+++ b/web/pages/profile/index.tsx
@@ -284,7 +284,9 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
ref={ref}
hasError={Boolean(errors.email)}
placeholder="Enter your email"
- className={`w-full rounded-md cursor-not-allowed !bg-custom-background-80 ${errors.email ? "border-red-500" : ""}`}
+ className={`w-full rounded-md cursor-not-allowed !bg-custom-background-80 ${
+ errors.email ? "border-red-500" : ""
+ }`}
disabled
/>
)}
@@ -306,7 +308,7 @@ const ProfileSettingsPage: NextPageWithLayout = observer(() => {
label={value ? value.toString() : "Select your role"}
buttonClassName={errors.role ? "border-red-500" : "border-none"}
className="rounded-md border-[0.5px] !border-custom-border-200"
- width="w-full"
+ optionsClassName="w-full"
input
>
{USER_ROLES.map((item) => (