forked from github/plane
chore: added optional tooltip to dropdowns (#3462)
This commit is contained in:
parent
7fd625e0e3
commit
eae32593cb
@ -128,7 +128,7 @@ export const IssuesByPriorityWidget: React.FC<WidgetProps> = observer((props) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full py-6 hover:shadow-custom-shadow-4xl duration-300 overflow-hidden min-h-96">
|
<div className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full py-6 hover:shadow-custom-shadow-4xl duration-300 overflow-hidden min-h-96 flex flex-col">
|
||||||
<div className="flex items-start justify-between gap-2 pl-7 pr-6">
|
<div className="flex items-start justify-between gap-2 pl-7 pr-6">
|
||||||
<div>
|
<div>
|
||||||
<Link
|
<Link
|
||||||
|
@ -127,7 +127,7 @@ export const IssuesByStateGroupWidget: React.FC<WidgetProps> = observer((props)
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full py-6 hover:shadow-custom-shadow-4xl duration-300 overflow-hidden min-h-96">
|
<div className="bg-custom-background-100 rounded-xl border-[0.5px] border-custom-border-200 w-full py-6 hover:shadow-custom-shadow-4xl duration-300 overflow-hidden min-h-96 flex flex-col">
|
||||||
<div className="flex items-start justify-between gap-2 pl-7 pr-6">
|
<div className="flex items-start justify-between gap-2 pl-7 pr-6">
|
||||||
<div>
|
<div>
|
||||||
<Link
|
<Link
|
||||||
|
@ -8,7 +8,7 @@ import { useApplication, useCycle } from "hooks/store";
|
|||||||
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
||||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||||
// icons
|
// icons
|
||||||
import { ContrastIcon } from "@plane/ui";
|
import { ContrastIcon, Tooltip } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "helpers/common.helper";
|
import { cn } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
@ -32,6 +32,7 @@ type ButtonProps = {
|
|||||||
dropdownArrow: boolean;
|
dropdownArrow: boolean;
|
||||||
dropdownArrowClassName: string;
|
dropdownArrowClassName: string;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
|
tooltip: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type DropdownOptions =
|
type DropdownOptions =
|
||||||
@ -51,21 +52,24 @@ const BorderButton = (props: ButtonProps) => {
|
|||||||
hideIcon = false,
|
hideIcon = false,
|
||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Cycle" tooltipContent={cycle?.name ?? placeholder} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
className={cn(
|
||||||
className
|
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && <ContrastIcon className="h-3 w-3 flex-shrink-0" />}{" "}
|
>
|
||||||
{!hideText && <span className="flex-grow truncate">{cycle?.name ?? placeholder}</span>}
|
{!hideIcon && <ContrastIcon className="h-3 w-3 flex-shrink-0" />}{" "}
|
||||||
{dropdownArrow && (
|
{!hideText && <span className="flex-grow truncate">{cycle?.name ?? placeholder}</span>}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
{dropdownArrow && (
|
||||||
)}
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,18 +82,24 @@ const BackgroundButton = (props: ButtonProps) => {
|
|||||||
hideIcon = false,
|
hideIcon = false,
|
||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Cycle" tooltipContent={cycle?.name ?? placeholder} disabled={!tooltip}>
|
||||||
className={cn("h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80", className)}
|
<div
|
||||||
>
|
className={cn(
|
||||||
{!hideIcon && <ContrastIcon className="h-3 w-3 flex-shrink-0" />}
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80",
|
||||||
{!hideText && <span className="flex-grow truncate">{cycle?.name ?? placeholder}</span>}
|
className
|
||||||
{dropdownArrow && (
|
)}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
>
|
||||||
)}
|
{!hideIcon && <ContrastIcon className="h-3 w-3 flex-shrink-0" />}
|
||||||
</div>
|
{!hideText && <span className="flex-grow truncate">{cycle?.name ?? placeholder}</span>}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -102,21 +112,24 @@ const TransparentButton = (props: ButtonProps) => {
|
|||||||
hideIcon = false,
|
hideIcon = false,
|
||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Cycle" tooltipContent={cycle?.name ?? placeholder} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
className={cn(
|
||||||
className
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && <ContrastIcon className="h-3 w-3 flex-shrink-0" />}
|
>
|
||||||
{!hideText && <span className="flex-grow truncate">{cycle?.name ?? placeholder}</span>}
|
{!hideIcon && <ContrastIcon className="h-3 w-3 flex-shrink-0" />}
|
||||||
{dropdownArrow && (
|
{!hideText && <span className="flex-grow truncate">{cycle?.name ?? placeholder}</span>}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
{dropdownArrow && (
|
||||||
)}
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -135,8 +148,9 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
placeholder = "Cycle",
|
placeholder = "Cycle",
|
||||||
placement,
|
placement,
|
||||||
projectId,
|
projectId,
|
||||||
value,
|
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
tooltip = false,
|
||||||
|
value,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@ -254,6 +268,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "border-without-text" ? (
|
) : buttonVariant === "border-without-text" ? (
|
||||||
<BorderButton
|
<BorderButton
|
||||||
@ -264,6 +279,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-with-text" ? (
|
) : buttonVariant === "background-with-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -273,6 +289,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-without-text" ? (
|
) : buttonVariant === "background-without-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -283,6 +300,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-with-text" ? (
|
) : buttonVariant === "transparent-with-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -292,6 +310,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-without-text" ? (
|
) : buttonVariant === "transparent-without-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -302,6 +321,7 @@ export const CycleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</button>
|
</button>
|
||||||
|
@ -6,6 +6,8 @@ import { CalendarDays, X } from "lucide-react";
|
|||||||
// hooks
|
// hooks
|
||||||
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
||||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||||
|
// ui
|
||||||
|
import { Tooltip } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { renderFormattedDate } from "helpers/date-time.helper";
|
import { renderFormattedDate } from "helpers/date-time.helper";
|
||||||
import { cn } from "helpers/common.helper";
|
import { cn } from "helpers/common.helper";
|
||||||
@ -33,6 +35,7 @@ type ButtonProps = {
|
|||||||
hideText?: boolean;
|
hideText?: boolean;
|
||||||
onClear: () => void;
|
onClear: () => void;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
|
tooltip: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BorderButton = (props: ButtonProps) => {
|
const BorderButton = (props: ButtonProps) => {
|
||||||
@ -46,27 +49,34 @@ const BorderButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
onClear,
|
onClear,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
className={cn(
|
tooltipHeading={placeholder}
|
||||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
tooltipContent={date ? renderFormattedDate(date) : "None"}
|
||||||
className
|
disabled={!tooltip}
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{!hideIcon && icon}
|
<div
|
||||||
{!hideText && <span className="flex-grow truncate">{date ? renderFormattedDate(date) : placeholder}</span>}
|
className={cn(
|
||||||
{isClearable && (
|
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||||
<X
|
className
|
||||||
className={cn("h-2 w-2 flex-shrink-0", clearIconClassName)}
|
)}
|
||||||
onClick={(e) => {
|
>
|
||||||
e.stopPropagation();
|
{!hideIcon && icon}
|
||||||
onClear();
|
{!hideText && <span className="flex-grow truncate">{date ? renderFormattedDate(date) : placeholder}</span>}
|
||||||
}}
|
{isClearable && (
|
||||||
/>
|
<X
|
||||||
)}
|
className={cn("h-2 w-2 flex-shrink-0", clearIconClassName)}
|
||||||
</div>
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onClear();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -81,24 +91,34 @@ const BackgroundButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
onClear,
|
onClear,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
className={cn("h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80", className)}
|
tooltipHeading={placeholder}
|
||||||
|
tooltipContent={date ? renderFormattedDate(date) : "None"}
|
||||||
|
disabled={!tooltip}
|
||||||
>
|
>
|
||||||
{!hideIcon && icon}
|
<div
|
||||||
{!hideText && <span className="flex-grow truncate">{date ? renderFormattedDate(date) : placeholder}</span>}
|
className={cn(
|
||||||
{isClearable && (
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80",
|
||||||
<X
|
className
|
||||||
className={cn("h-2 w-2 flex-shrink-0", clearIconClassName)}
|
)}
|
||||||
onClick={(e) => {
|
>
|
||||||
e.stopPropagation();
|
{!hideIcon && icon}
|
||||||
onClear();
|
{!hideText && <span className="flex-grow truncate">{date ? renderFormattedDate(date) : placeholder}</span>}
|
||||||
}}
|
{isClearable && (
|
||||||
/>
|
<X
|
||||||
)}
|
className={cn("h-2 w-2 flex-shrink-0", clearIconClassName)}
|
||||||
</div>
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onClear();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -113,27 +133,34 @@ const TransparentButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
onClear,
|
onClear,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
className={cn(
|
tooltipHeading={placeholder}
|
||||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
tooltipContent={date ? renderFormattedDate(date) : "None"}
|
||||||
className
|
disabled={!tooltip}
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{!hideIcon && icon}
|
<div
|
||||||
{!hideText && <span className="flex-grow truncate">{date ? renderFormattedDate(date) : placeholder}</span>}
|
className={cn(
|
||||||
{isClearable && (
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||||
<X
|
className
|
||||||
className={cn("h-2 w-2 flex-shrink-0", clearIconClassName)}
|
)}
|
||||||
onClick={(e) => {
|
>
|
||||||
e.stopPropagation();
|
{!hideIcon && icon}
|
||||||
onClear();
|
{!hideText && <span className="flex-grow truncate">{date ? renderFormattedDate(date) : placeholder}</span>}
|
||||||
}}
|
{isClearable && (
|
||||||
/>
|
<X
|
||||||
)}
|
className={cn("h-2 w-2 flex-shrink-0", clearIconClassName)}
|
||||||
</div>
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
onClear();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -144,6 +171,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
|||||||
buttonVariant,
|
buttonVariant,
|
||||||
className = "",
|
className = "",
|
||||||
clearIconClassName = "",
|
clearIconClassName = "",
|
||||||
|
closeOnSelect = true,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
hideIcon = false,
|
hideIcon = false,
|
||||||
icon = <CalendarDays className="h-3 w-3 flex-shrink-0" />,
|
icon = <CalendarDays className="h-3 w-3 flex-shrink-0" />,
|
||||||
@ -153,9 +181,9 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
|||||||
onChange,
|
onChange,
|
||||||
placeholder = "Date",
|
placeholder = "Date",
|
||||||
placement,
|
placement,
|
||||||
value,
|
|
||||||
closeOnSelect = true,
|
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
tooltip = false,
|
||||||
|
value,
|
||||||
} = props;
|
} = props;
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
// refs
|
// refs
|
||||||
@ -218,6 +246,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
isClearable={isClearable && isDateSelected}
|
isClearable={isClearable && isDateSelected}
|
||||||
onClear={() => onChange(null)}
|
onClear={() => onChange(null)}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "border-without-text" ? (
|
) : buttonVariant === "border-without-text" ? (
|
||||||
<BorderButton
|
<BorderButton
|
||||||
@ -229,6 +258,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
isClearable={isClearable && isDateSelected}
|
isClearable={isClearable && isDateSelected}
|
||||||
onClear={() => onChange(null)}
|
onClear={() => onChange(null)}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-with-text" ? (
|
) : buttonVariant === "background-with-text" ? (
|
||||||
@ -241,6 +271,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
isClearable={isClearable && isDateSelected}
|
isClearable={isClearable && isDateSelected}
|
||||||
onClear={() => onChange(null)}
|
onClear={() => onChange(null)}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-without-text" ? (
|
) : buttonVariant === "background-without-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -252,6 +283,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
isClearable={isClearable && isDateSelected}
|
isClearable={isClearable && isDateSelected}
|
||||||
onClear={() => onChange(null)}
|
onClear={() => onChange(null)}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-with-text" ? (
|
) : buttonVariant === "transparent-with-text" ? (
|
||||||
@ -264,6 +296,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
isClearable={isClearable && isDateSelected}
|
isClearable={isClearable && isDateSelected}
|
||||||
onClear={() => onChange(null)}
|
onClear={() => onChange(null)}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-without-text" ? (
|
) : buttonVariant === "transparent-without-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -275,6 +308,7 @@ export const DateDropdown: React.FC<Props> = (props) => {
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
isClearable={isClearable && isDateSelected}
|
isClearable={isClearable && isDateSelected}
|
||||||
onClear={() => onChange(null)}
|
onClear={() => onChange(null)}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -8,6 +8,8 @@ import sortBy from "lodash/sortBy";
|
|||||||
import { useApplication, useEstimate } from "hooks/store";
|
import { useApplication, useEstimate } from "hooks/store";
|
||||||
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
||||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||||
|
// ui
|
||||||
|
import { Tooltip } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "helpers/common.helper";
|
import { cn } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
@ -30,6 +32,7 @@ type ButtonProps = {
|
|||||||
hideIcon?: boolean;
|
hideIcon?: boolean;
|
||||||
hideText?: boolean;
|
hideText?: boolean;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
|
tooltip: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type DropdownOptions =
|
type DropdownOptions =
|
||||||
@ -49,21 +52,30 @@ const BorderButton = (props: ButtonProps) => {
|
|||||||
hideIcon = false,
|
hideIcon = false,
|
||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
className={cn(
|
tooltipHeading="Estimate"
|
||||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
tooltipContent={estimatePoint !== null ? estimatePoint : placeholder}
|
||||||
className
|
disabled={!tooltip}
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{!hideIcon && <Triangle className="h-3 w-3 flex-shrink-0" />}
|
<div
|
||||||
{!hideText && <span className="flex-grow truncate">{estimatePoint !== null ? estimatePoint : placeholder}</span>}
|
className={cn(
|
||||||
{dropdownArrow && (
|
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
className
|
||||||
)}
|
)}
|
||||||
</div>
|
>
|
||||||
|
{!hideIcon && <Triangle className="h-3 w-3 flex-shrink-0" />}
|
||||||
|
{!hideText && (
|
||||||
|
<span className="flex-grow truncate">{estimatePoint !== null ? estimatePoint : placeholder}</span>
|
||||||
|
)}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -76,18 +88,30 @@ const BackgroundButton = (props: ButtonProps) => {
|
|||||||
hideIcon = false,
|
hideIcon = false,
|
||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
className={cn("h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80", className)}
|
tooltipHeading="Estimate"
|
||||||
|
tooltipContent={estimatePoint !== null ? estimatePoint : placeholder}
|
||||||
|
disabled={!tooltip}
|
||||||
>
|
>
|
||||||
{!hideIcon && <Triangle className="h-3 w-3 flex-shrink-0" />}
|
<div
|
||||||
{!hideText && <span className="flex-grow truncate">{estimatePoint !== null ? estimatePoint : placeholder}</span>}
|
className={cn(
|
||||||
{dropdownArrow && (
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80",
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
className
|
||||||
)}
|
)}
|
||||||
</div>
|
>
|
||||||
|
{!hideIcon && <Triangle className="h-3 w-3 flex-shrink-0" />}
|
||||||
|
{!hideText && (
|
||||||
|
<span className="flex-grow truncate">{estimatePoint !== null ? estimatePoint : placeholder}</span>
|
||||||
|
)}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,21 +124,30 @@ const TransparentButton = (props: ButtonProps) => {
|
|||||||
hideIcon = false,
|
hideIcon = false,
|
||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
className={cn(
|
tooltipHeading="Estimate"
|
||||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
tooltipContent={estimatePoint !== null ? estimatePoint : placeholder}
|
||||||
className
|
disabled={!tooltip}
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{!hideIcon && <Triangle className="h-3 w-3 flex-shrink-0" />}
|
<div
|
||||||
{!hideText && <span className="flex-grow truncate">{estimatePoint !== null ? estimatePoint : placeholder}</span>}
|
className={cn(
|
||||||
{dropdownArrow && (
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
className
|
||||||
)}
|
)}
|
||||||
</div>
|
>
|
||||||
|
{!hideIcon && <Triangle className="h-3 w-3 flex-shrink-0" />}
|
||||||
|
{!hideText && (
|
||||||
|
<span className="flex-grow truncate">{estimatePoint !== null ? estimatePoint : placeholder}</span>
|
||||||
|
)}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -133,8 +166,9 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
placeholder = "Estimate",
|
placeholder = "Estimate",
|
||||||
placement,
|
placement,
|
||||||
projectId,
|
projectId,
|
||||||
value,
|
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
tooltip = false,
|
||||||
|
value,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@ -242,6 +276,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "border-without-text" ? (
|
) : buttonVariant === "border-without-text" ? (
|
||||||
<BorderButton
|
<BorderButton
|
||||||
@ -252,6 +287,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-with-text" ? (
|
) : buttonVariant === "background-with-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -261,6 +297,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-without-text" ? (
|
) : buttonVariant === "background-without-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -271,6 +308,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-with-text" ? (
|
) : buttonVariant === "transparent-with-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -280,6 +318,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-without-text" ? (
|
) : buttonVariant === "transparent-without-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -290,6 +329,7 @@ export const EstimateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</button>
|
</button>
|
||||||
|
@ -3,7 +3,7 @@ import { ChevronDown } from "lucide-react";
|
|||||||
// hooks
|
// hooks
|
||||||
import { useMember } from "hooks/store";
|
import { useMember } from "hooks/store";
|
||||||
// ui
|
// ui
|
||||||
import { Avatar, AvatarGroup, UserGroupIcon } from "@plane/ui";
|
import { Avatar, AvatarGroup, Tooltip, UserGroupIcon } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "helpers/common.helper";
|
import { cn } from "helpers/common.helper";
|
||||||
|
|
||||||
@ -14,16 +14,17 @@ type ButtonProps = {
|
|||||||
placeholder: string;
|
placeholder: string;
|
||||||
hideIcon?: boolean;
|
hideIcon?: boolean;
|
||||||
hideText?: boolean;
|
hideText?: boolean;
|
||||||
|
tooltip: boolean;
|
||||||
userIds: string | string[] | null;
|
userIds: string | string[] | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ButtonAvatars = observer(({ userIds }: { userIds: string | string[] | null }) => {
|
const ButtonAvatars = observer(({ tooltip, userIds }: { tooltip: boolean; userIds: string | string[] | null }) => {
|
||||||
const { getUserDetails } = useMember();
|
const { getUserDetails } = useMember();
|
||||||
|
|
||||||
if (Array.isArray(userIds)) {
|
if (Array.isArray(userIds)) {
|
||||||
if (userIds.length > 0)
|
if (userIds.length > 0)
|
||||||
return (
|
return (
|
||||||
<AvatarGroup size="md">
|
<AvatarGroup size="md" showTooltip={!tooltip}>
|
||||||
{userIds.map((userId) => {
|
{userIds.map((userId) => {
|
||||||
const userDetails = getUserDetails(userId);
|
const userDetails = getUserDetails(userId);
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ const ButtonAvatars = observer(({ userIds }: { userIds: string | string[] | null
|
|||||||
} else {
|
} else {
|
||||||
if (userIds) {
|
if (userIds) {
|
||||||
const userDetails = getUserDetails(userIds);
|
const userDetails = getUserDetails(userIds);
|
||||||
return <Avatar src={userDetails?.avatar} name={userDetails?.display_name} size="md" />;
|
return <Avatar src={userDetails?.avatar} name={userDetails?.display_name} size="md" showTooltip={!tooltip} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,6 +52,7 @@ export const BorderButton = observer((props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
userIds,
|
userIds,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { getUserDetails } = useMember();
|
const { getUserDetails } = useMember();
|
||||||
@ -58,22 +60,28 @@ export const BorderButton = observer((props: ButtonProps) => {
|
|||||||
const isMultiple = Array.isArray(userIds);
|
const isMultiple = Array.isArray(userIds);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
className={cn(
|
tooltipHeading={placeholder}
|
||||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
tooltipContent={`${userIds?.length ?? 0} assignee${userIds?.length !== 1 ? "s" : ""}`}
|
||||||
className
|
disabled={!tooltip}
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{!hideIcon && <ButtonAvatars userIds={userIds} />}
|
<div
|
||||||
{!hideText && (
|
className={cn(
|
||||||
<span className="flex-grow truncate">
|
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||||
{userIds ? (isMultiple ? placeholder : getUserDetails(userIds)?.display_name) : placeholder}
|
className
|
||||||
</span>
|
)}
|
||||||
)}
|
>
|
||||||
{dropdownArrow && (
|
{!hideIcon && <ButtonAvatars tooltip={tooltip} userIds={userIds} />}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
{!hideText && (
|
||||||
)}
|
<span className="flex-grow truncate">
|
||||||
</div>
|
{userIds ? (isMultiple ? placeholder : getUserDetails(userIds)?.display_name) : placeholder}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -86,6 +94,7 @@ export const BackgroundButton = observer((props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
userIds,
|
userIds,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { getUserDetails } = useMember();
|
const { getUserDetails } = useMember();
|
||||||
@ -93,19 +102,28 @@ export const BackgroundButton = observer((props: ButtonProps) => {
|
|||||||
const isMultiple = Array.isArray(userIds);
|
const isMultiple = Array.isArray(userIds);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
className={cn("h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80", className)}
|
tooltipHeading={placeholder}
|
||||||
|
tooltipContent={`${userIds?.length ?? 0} assignee${userIds?.length !== 1 ? "s" : ""}`}
|
||||||
|
disabled={!tooltip}
|
||||||
>
|
>
|
||||||
{!hideIcon && <ButtonAvatars userIds={userIds} />}
|
<div
|
||||||
{!hideText && (
|
className={cn(
|
||||||
<span className="flex-grow truncate">
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80",
|
||||||
{userIds ? (isMultiple ? placeholder : getUserDetails(userIds)?.display_name) : placeholder}
|
className
|
||||||
</span>
|
)}
|
||||||
)}
|
>
|
||||||
{dropdownArrow && (
|
{!hideIcon && <ButtonAvatars tooltip={tooltip} userIds={userIds} />}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
{!hideText && (
|
||||||
)}
|
<span className="flex-grow truncate">
|
||||||
</div>
|
{userIds ? (isMultiple ? placeholder : getUserDetails(userIds)?.display_name) : placeholder}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -118,6 +136,7 @@ export const TransparentButton = observer((props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
userIds,
|
userIds,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
// store hooks
|
// store hooks
|
||||||
const { getUserDetails } = useMember();
|
const { getUserDetails } = useMember();
|
||||||
@ -125,21 +144,27 @@ export const TransparentButton = observer((props: ButtonProps) => {
|
|||||||
const isMultiple = Array.isArray(userIds);
|
const isMultiple = Array.isArray(userIds);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip
|
||||||
className={cn(
|
tooltipHeading={placeholder}
|
||||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
tooltipContent={`${userIds?.length ?? 0} assignee${userIds?.length !== 1 ? "s" : ""}`}
|
||||||
className
|
disabled={!tooltip}
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
{!hideIcon && <ButtonAvatars userIds={userIds} />}
|
<div
|
||||||
{!hideText && (
|
className={cn(
|
||||||
<span className="flex-grow truncate">
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||||
{userIds ? (isMultiple ? placeholder : getUserDetails(userIds)?.display_name) : placeholder}
|
className
|
||||||
</span>
|
)}
|
||||||
)}
|
>
|
||||||
{dropdownArrow && (
|
{!hideIcon && <ButtonAvatars tooltip={tooltip} userIds={userIds} />}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
{!hideText && (
|
||||||
)}
|
<span className="flex-grow truncate">
|
||||||
</div>
|
{userIds ? (isMultiple ? placeholder : getUserDetails(userIds)?.display_name) : placeholder}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -36,8 +36,9 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
|||||||
placeholder = "Members",
|
placeholder = "Members",
|
||||||
placement,
|
placement,
|
||||||
projectId,
|
projectId,
|
||||||
value,
|
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
tooltip = false,
|
||||||
|
value,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@ -146,6 +147,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "border-without-text" ? (
|
) : buttonVariant === "border-without-text" ? (
|
||||||
<BorderButton
|
<BorderButton
|
||||||
@ -155,6 +157,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-with-text" ? (
|
) : buttonVariant === "background-with-text" ? (
|
||||||
@ -165,6 +168,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-without-text" ? (
|
) : buttonVariant === "background-without-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -174,6 +178,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-with-text" ? (
|
) : buttonVariant === "transparent-with-text" ? (
|
||||||
@ -184,6 +189,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-without-text" ? (
|
) : buttonVariant === "transparent-without-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -193,6 +199,7 @@ export const ProjectMemberDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -31,8 +31,9 @@ export const WorkspaceMemberDropdown: React.FC<MemberDropdownProps> = observer((
|
|||||||
onChange,
|
onChange,
|
||||||
placeholder = "Members",
|
placeholder = "Members",
|
||||||
placement,
|
placement,
|
||||||
value,
|
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
tooltip = false,
|
||||||
|
value,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@ -133,6 +134,7 @@ export const WorkspaceMemberDropdown: React.FC<MemberDropdownProps> = observer((
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "border-without-text" ? (
|
) : buttonVariant === "border-without-text" ? (
|
||||||
<BorderButton
|
<BorderButton
|
||||||
@ -142,6 +144,7 @@ export const WorkspaceMemberDropdown: React.FC<MemberDropdownProps> = observer((
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-with-text" ? (
|
) : buttonVariant === "background-with-text" ? (
|
||||||
@ -152,6 +155,7 @@ export const WorkspaceMemberDropdown: React.FC<MemberDropdownProps> = observer((
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-without-text" ? (
|
) : buttonVariant === "background-without-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -161,6 +165,7 @@ export const WorkspaceMemberDropdown: React.FC<MemberDropdownProps> = observer((
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-with-text" ? (
|
) : buttonVariant === "transparent-with-text" ? (
|
||||||
@ -171,6 +176,7 @@ export const WorkspaceMemberDropdown: React.FC<MemberDropdownProps> = observer((
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-without-text" ? (
|
) : buttonVariant === "transparent-without-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -180,6 +186,7 @@ export const WorkspaceMemberDropdown: React.FC<MemberDropdownProps> = observer((
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -8,7 +8,7 @@ import { useApplication, useModule } from "hooks/store";
|
|||||||
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
||||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||||
// icons
|
// icons
|
||||||
import { DiceIcon } from "@plane/ui";
|
import { DiceIcon, Tooltip } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "helpers/common.helper";
|
import { cn } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
@ -40,6 +40,7 @@ type ButtonProps = {
|
|||||||
hideText?: boolean;
|
hideText?: boolean;
|
||||||
module: IModule | null;
|
module: IModule | null;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
|
tooltip: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BorderButton = (props: ButtonProps) => {
|
const BorderButton = (props: ButtonProps) => {
|
||||||
@ -51,21 +52,24 @@ const BorderButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
module,
|
module,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Module" tooltipContent={module?.name ?? placeholder} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
className={cn(
|
||||||
className
|
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && <DiceIcon className="h-3 w-3 flex-shrink-0" />}
|
>
|
||||||
{!hideText && <span className="flex-grow truncate">{module?.name ?? placeholder}</span>}
|
{!hideIcon && <DiceIcon className="h-3 w-3 flex-shrink-0" />}
|
||||||
{dropdownArrow && (
|
{!hideText && <span className="flex-grow truncate">{module?.name ?? placeholder}</span>}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
{dropdownArrow && (
|
||||||
)}
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -78,18 +82,24 @@ const BackgroundButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
module,
|
module,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Module" tooltipContent={module?.name ?? placeholder} disabled={!tooltip}>
|
||||||
className={cn("h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80", className)}
|
<div
|
||||||
>
|
className={cn(
|
||||||
{!hideIcon && <DiceIcon className="h-3 w-3 flex-shrink-0" />}
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80",
|
||||||
{!hideText && <span className="flex-grow truncate">{module?.name ?? placeholder}</span>}
|
className
|
||||||
{dropdownArrow && (
|
)}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
>
|
||||||
)}
|
{!hideIcon && <DiceIcon className="h-3 w-3 flex-shrink-0" />}
|
||||||
</div>
|
{!hideText && <span className="flex-grow truncate">{module?.name ?? placeholder}</span>}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -102,21 +112,24 @@ const TransparentButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
module,
|
module,
|
||||||
placeholder,
|
placeholder,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Module" tooltipContent={module?.name ?? placeholder} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
className={cn(
|
||||||
className
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && <DiceIcon className="h-3 w-3 flex-shrink-0" />}
|
>
|
||||||
{!hideText && <span className="flex-grow truncate">{module?.name ?? placeholder}</span>}
|
{!hideIcon && <DiceIcon className="h-3 w-3 flex-shrink-0" />}
|
||||||
{dropdownArrow && (
|
{!hideText && <span className="flex-grow truncate">{module?.name ?? placeholder}</span>}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
{dropdownArrow && (
|
||||||
)}
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -135,8 +148,9 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
placeholder = "Module",
|
placeholder = "Module",
|
||||||
placement,
|
placement,
|
||||||
projectId,
|
projectId,
|
||||||
value,
|
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
tooltip = false,
|
||||||
|
value,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@ -253,6 +267,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "border-without-text" ? (
|
) : buttonVariant === "border-without-text" ? (
|
||||||
<BorderButton
|
<BorderButton
|
||||||
@ -263,6 +278,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-with-text" ? (
|
) : buttonVariant === "background-with-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -272,6 +288,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-without-text" ? (
|
) : buttonVariant === "background-without-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -282,6 +299,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-with-text" ? (
|
) : buttonVariant === "transparent-with-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -291,6 +309,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-without-text" ? (
|
) : buttonVariant === "transparent-without-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -301,6 +320,7 @@ export const ModuleDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</button>
|
</button>
|
||||||
|
@ -2,11 +2,12 @@ import { Fragment, ReactNode, useRef, useState } from "react";
|
|||||||
import { Combobox } from "@headlessui/react";
|
import { Combobox } from "@headlessui/react";
|
||||||
import { usePopper } from "react-popper";
|
import { usePopper } from "react-popper";
|
||||||
import { Check, ChevronDown, Search } from "lucide-react";
|
import { Check, ChevronDown, Search } from "lucide-react";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
// hooks
|
// hooks
|
||||||
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
||||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||||
// icons
|
// icons
|
||||||
import { PriorityIcon } from "@plane/ui";
|
import { PriorityIcon, Tooltip } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "helpers/common.helper";
|
import { cn } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
@ -14,7 +15,6 @@ import { TIssuePriorities } from "@plane/types";
|
|||||||
import { TDropdownProps } from "./types";
|
import { TDropdownProps } from "./types";
|
||||||
// constants
|
// constants
|
||||||
import { ISSUE_PRIORITIES } from "constants/issue";
|
import { ISSUE_PRIORITIES } from "constants/issue";
|
||||||
import { useTheme } from "next-themes";
|
|
||||||
|
|
||||||
type Props = TDropdownProps & {
|
type Props = TDropdownProps & {
|
||||||
button?: ReactNode;
|
button?: ReactNode;
|
||||||
@ -33,6 +33,7 @@ type ButtonProps = {
|
|||||||
hideText?: boolean;
|
hideText?: boolean;
|
||||||
highlightUrgent: boolean;
|
highlightUrgent: boolean;
|
||||||
priority: TIssuePriorities;
|
priority: TIssuePriorities;
|
||||||
|
tooltip: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BorderButton = (props: ButtonProps) => {
|
const BorderButton = (props: ButtonProps) => {
|
||||||
@ -44,6 +45,7 @@ const BorderButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
highlightUrgent,
|
highlightUrgent,
|
||||||
priority,
|
priority,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const priorityDetails = ISSUE_PRIORITIES.find((p) => p.key === priority);
|
const priorityDetails = ISSUE_PRIORITIES.find((p) => p.key === priority);
|
||||||
@ -57,47 +59,49 @@ const BorderButton = (props: ButtonProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Priority" tooltipContent={priorityDetails?.title ?? "None"} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 border-[0.5px] rounded text-xs px-2 py-0.5",
|
className={cn(
|
||||||
priorityClasses[priority],
|
"h-full flex items-center gap-1.5 border-[0.5px] rounded text-xs px-2 py-0.5",
|
||||||
{
|
priorityClasses[priority],
|
||||||
// compact the icons if text is hidden
|
{
|
||||||
"px-0.5": hideText,
|
// compact the icons if text is hidden
|
||||||
// highlight the whole button if text is hidden and priority is urgent
|
"px-0.5": hideText,
|
||||||
"bg-red-500 border-red-500": priority === "urgent" && hideText && highlightUrgent,
|
// highlight the whole button if text is hidden and priority is urgent
|
||||||
},
|
"bg-red-500 border-red-500": priority === "urgent" && hideText && highlightUrgent,
|
||||||
className
|
},
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && (
|
>
|
||||||
<div
|
{!hideIcon && (
|
||||||
className={cn({
|
<div
|
||||||
// highlight just the icon if text is visible and priority is urgent
|
className={cn({
|
||||||
"bg-red-500 p-1 rounded": priority === "urgent" && !hideText && highlightUrgent,
|
// highlight just the icon if text is visible and priority is urgent
|
||||||
})}
|
"bg-red-500 p-1 rounded": priority === "urgent" && !hideText && highlightUrgent,
|
||||||
>
|
|
||||||
<PriorityIcon
|
|
||||||
priority={priority}
|
|
||||||
size={12}
|
|
||||||
className={cn("flex-shrink-0", {
|
|
||||||
// increase the icon size if text is hidden
|
|
||||||
"h-3.5 w-3.5": hideText,
|
|
||||||
// centre align the icons if text is hidden
|
|
||||||
"translate-x-[0.0625rem]": hideText && priority === "high",
|
|
||||||
"translate-x-0.5": hideText && priority === "medium",
|
|
||||||
"translate-x-1": hideText && priority === "low",
|
|
||||||
// highlight the icon if priority is urgent
|
|
||||||
"text-white": priority === "urgent" && highlightUrgent,
|
|
||||||
})}
|
})}
|
||||||
/>
|
>
|
||||||
</div>
|
<PriorityIcon
|
||||||
)}
|
priority={priority}
|
||||||
{!hideText && <span className="flex-grow truncate">{priorityDetails?.title}</span>}
|
size={12}
|
||||||
{dropdownArrow && (
|
className={cn("flex-shrink-0", {
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
// increase the icon size if text is hidden
|
||||||
)}
|
"h-3.5 w-3.5": hideText,
|
||||||
</div>
|
// centre align the icons if text is hidden
|
||||||
|
"translate-x-[0.0625rem]": hideText && priority === "high",
|
||||||
|
"translate-x-0.5": hideText && priority === "medium",
|
||||||
|
"translate-x-1": hideText && priority === "low",
|
||||||
|
// highlight the icon if priority is urgent
|
||||||
|
"text-white": priority === "urgent" && highlightUrgent,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!hideText && <span className="flex-grow truncate">{priorityDetails?.title}</span>}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -110,6 +114,7 @@ const BackgroundButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
highlightUrgent,
|
highlightUrgent,
|
||||||
priority,
|
priority,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const priorityDetails = ISSUE_PRIORITIES.find((p) => p.key === priority);
|
const priorityDetails = ISSUE_PRIORITIES.find((p) => p.key === priority);
|
||||||
@ -123,47 +128,49 @@ const BackgroundButton = (props: ButtonProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Priority" tooltipContent={priorityDetails?.title ?? "None"} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5",
|
className={cn(
|
||||||
priorityClasses[priority],
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5",
|
||||||
{
|
priorityClasses[priority],
|
||||||
// compact the icons if text is hidden
|
{
|
||||||
"px-0.5": hideText,
|
// compact the icons if text is hidden
|
||||||
// highlight the whole button if text is hidden and priority is urgent
|
"px-0.5": hideText,
|
||||||
"bg-red-500 border-red-500": priority === "urgent" && hideText && highlightUrgent,
|
// highlight the whole button if text is hidden and priority is urgent
|
||||||
},
|
"bg-red-500 border-red-500": priority === "urgent" && hideText && highlightUrgent,
|
||||||
className
|
},
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && (
|
>
|
||||||
<div
|
{!hideIcon && (
|
||||||
className={cn({
|
<div
|
||||||
// highlight just the icon if text is visible and priority is urgent
|
className={cn({
|
||||||
"bg-red-500 p-1 rounded": priority === "urgent" && !hideText && highlightUrgent,
|
// highlight just the icon if text is visible and priority is urgent
|
||||||
})}
|
"bg-red-500 p-1 rounded": priority === "urgent" && !hideText && highlightUrgent,
|
||||||
>
|
|
||||||
<PriorityIcon
|
|
||||||
priority={priority}
|
|
||||||
size={12}
|
|
||||||
className={cn("flex-shrink-0", {
|
|
||||||
// increase the icon size if text is hidden
|
|
||||||
"h-3.5 w-3.5": hideText,
|
|
||||||
// centre align the icons if text is hidden
|
|
||||||
"translate-x-[0.0625rem]": hideText && priority === "high",
|
|
||||||
"translate-x-0.5": hideText && priority === "medium",
|
|
||||||
"translate-x-1": hideText && priority === "low",
|
|
||||||
// highlight the icon if priority is urgent
|
|
||||||
"text-white": priority === "urgent" && highlightUrgent,
|
|
||||||
})}
|
})}
|
||||||
/>
|
>
|
||||||
</div>
|
<PriorityIcon
|
||||||
)}
|
priority={priority}
|
||||||
{!hideText && <span className="flex-grow truncate">{priorityDetails?.title}</span>}
|
size={12}
|
||||||
{dropdownArrow && (
|
className={cn("flex-shrink-0", {
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
// increase the icon size if text is hidden
|
||||||
)}
|
"h-3.5 w-3.5": hideText,
|
||||||
</div>
|
// centre align the icons if text is hidden
|
||||||
|
"translate-x-[0.0625rem]": hideText && priority === "high",
|
||||||
|
"translate-x-0.5": hideText && priority === "medium",
|
||||||
|
"translate-x-1": hideText && priority === "low",
|
||||||
|
// highlight the icon if priority is urgent
|
||||||
|
"text-white": priority === "urgent" && highlightUrgent,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!hideText && <span className="flex-grow truncate">{priorityDetails?.title}</span>}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -176,6 +183,7 @@ const TransparentButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
highlightUrgent,
|
highlightUrgent,
|
||||||
priority,
|
priority,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const priorityDetails = ISSUE_PRIORITIES.find((p) => p.key === priority);
|
const priorityDetails = ISSUE_PRIORITIES.find((p) => p.key === priority);
|
||||||
@ -189,47 +197,49 @@ const TransparentButton = (props: ButtonProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Priority" tooltipContent={priorityDetails?.title ?? "None"} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
className={cn(
|
||||||
priorityClasses[priority],
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||||
{
|
priorityClasses[priority],
|
||||||
// compact the icons if text is hidden
|
{
|
||||||
"px-0.5": hideText,
|
// compact the icons if text is hidden
|
||||||
// highlight the whole button if text is hidden and priority is urgent
|
"px-0.5": hideText,
|
||||||
"bg-red-500 border-red-500": priority === "urgent" && hideText && highlightUrgent,
|
// highlight the whole button if text is hidden and priority is urgent
|
||||||
},
|
"bg-red-500 border-red-500": priority === "urgent" && hideText && highlightUrgent,
|
||||||
className
|
},
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && (
|
>
|
||||||
<div
|
{!hideIcon && (
|
||||||
className={cn({
|
<div
|
||||||
// highlight just the icon if text is visible and priority is urgent
|
className={cn({
|
||||||
"bg-red-500 p-1 rounded": priority === "urgent" && !hideText && highlightUrgent,
|
// highlight just the icon if text is visible and priority is urgent
|
||||||
})}
|
"bg-red-500 p-1 rounded": priority === "urgent" && !hideText && highlightUrgent,
|
||||||
>
|
|
||||||
<PriorityIcon
|
|
||||||
priority={priority}
|
|
||||||
size={12}
|
|
||||||
className={cn("flex-shrink-0", {
|
|
||||||
// increase the icon size if text is hidden
|
|
||||||
"h-3.5 w-3.5": hideText,
|
|
||||||
// centre align the icons if text is hidden
|
|
||||||
"translate-x-[0.0625rem]": hideText && priority === "high",
|
|
||||||
"translate-x-0.5": hideText && priority === "medium",
|
|
||||||
"translate-x-1": hideText && priority === "low",
|
|
||||||
// highlight the icon if priority is urgent
|
|
||||||
"text-white": priority === "urgent" && highlightUrgent,
|
|
||||||
})}
|
})}
|
||||||
/>
|
>
|
||||||
</div>
|
<PriorityIcon
|
||||||
)}
|
priority={priority}
|
||||||
{!hideText && <span className="flex-grow truncate">{priorityDetails?.title}</span>}
|
size={12}
|
||||||
{dropdownArrow && (
|
className={cn("flex-shrink-0", {
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
// increase the icon size if text is hidden
|
||||||
)}
|
"h-3.5 w-3.5": hideText,
|
||||||
</div>
|
// centre align the icons if text is hidden
|
||||||
|
"translate-x-[0.0625rem]": hideText && priority === "high",
|
||||||
|
"translate-x-0.5": hideText && priority === "medium",
|
||||||
|
"translate-x-1": hideText && priority === "low",
|
||||||
|
// highlight the icon if priority is urgent
|
||||||
|
"text-white": priority === "urgent" && highlightUrgent,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!hideText && <span className="flex-grow truncate">{priorityDetails?.title}</span>}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -247,8 +257,9 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
|||||||
highlightUrgent = true,
|
highlightUrgent = true,
|
||||||
onChange,
|
onChange,
|
||||||
placement,
|
placement,
|
||||||
value,
|
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
tooltip = false,
|
||||||
|
value,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@ -341,6 +352,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "border-without-text" ? (
|
) : buttonVariant === "border-without-text" ? (
|
||||||
<BorderButton
|
<BorderButton
|
||||||
@ -352,6 +364,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-with-text" ? (
|
) : buttonVariant === "background-with-text" ? (
|
||||||
@ -364,6 +377,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-without-text" ? (
|
) : buttonVariant === "background-without-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -375,6 +389,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-with-text" ? (
|
) : buttonVariant === "transparent-with-text" ? (
|
||||||
@ -387,6 +402,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-without-text" ? (
|
) : buttonVariant === "transparent-without-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -398,6 +414,7 @@ export const PriorityDropdown: React.FC<Props> = (props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
@ -7,6 +7,8 @@ import { Check, ChevronDown, Search } from "lucide-react";
|
|||||||
import { useProject } from "hooks/store";
|
import { useProject } from "hooks/store";
|
||||||
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
||||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||||
|
// ui
|
||||||
|
import { Tooltip } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "helpers/common.helper";
|
import { cn } from "helpers/common.helper";
|
||||||
import { renderEmoji } from "helpers/emoji.helper";
|
import { renderEmoji } from "helpers/emoji.helper";
|
||||||
@ -30,6 +32,7 @@ type ButtonProps = {
|
|||||||
hideText?: boolean;
|
hideText?: boolean;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
project: IProject | null;
|
project: IProject | null;
|
||||||
|
tooltip: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BorderButton = (props: ButtonProps) => {
|
const BorderButton = (props: ButtonProps) => {
|
||||||
@ -41,25 +44,28 @@ const BorderButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
project,
|
project,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Project" tooltipContent={project?.name ?? placeholder} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
className={cn(
|
||||||
className
|
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && (
|
>
|
||||||
<span className="grid place-items-center flex-shrink-0">
|
{!hideIcon && (
|
||||||
{project?.emoji ? renderEmoji(project?.emoji) : project?.icon_prop ? renderEmoji(project?.icon_prop) : null}
|
<span className="grid place-items-center flex-shrink-0">
|
||||||
</span>
|
{project?.emoji ? renderEmoji(project?.emoji) : project?.icon_prop ? renderEmoji(project?.icon_prop) : null}
|
||||||
)}
|
</span>
|
||||||
{!hideText && <span className="flex-grow truncate">{project?.name ?? placeholder}</span>}
|
)}
|
||||||
{dropdownArrow && (
|
{!hideText && <span className="flex-grow truncate">{project?.name ?? placeholder}</span>}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
{dropdownArrow && (
|
||||||
)}
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -72,22 +78,28 @@ const BackgroundButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
project,
|
project,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Project" tooltipContent={project?.name ?? placeholder} disabled={!tooltip}>
|
||||||
className={cn("h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80", className)}
|
<div
|
||||||
>
|
className={cn(
|
||||||
{!hideIcon && (
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80",
|
||||||
<span className="grid place-items-center flex-shrink-0">
|
className
|
||||||
{project?.emoji ? renderEmoji(project?.emoji) : project?.icon_prop ? renderEmoji(project?.icon_prop) : null}
|
)}
|
||||||
</span>
|
>
|
||||||
)}
|
{!hideIcon && (
|
||||||
{!hideText && <span className="flex-grow truncate">{project?.name ?? placeholder}</span>}
|
<span className="grid place-items-center flex-shrink-0">
|
||||||
{dropdownArrow && (
|
{project?.emoji ? renderEmoji(project?.emoji) : project?.icon_prop ? renderEmoji(project?.icon_prop) : null}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
{!hideText && <span className="flex-grow truncate">{project?.name ?? placeholder}</span>}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,25 +112,28 @@ const TransparentButton = (props: ButtonProps) => {
|
|||||||
hideText = false,
|
hideText = false,
|
||||||
placeholder,
|
placeholder,
|
||||||
project,
|
project,
|
||||||
|
tooltip,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="Project" tooltipContent={project?.name ?? placeholder} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
className={cn(
|
||||||
className
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && (
|
>
|
||||||
<span className="grid place-items-center flex-shrink-0">
|
{!hideIcon && (
|
||||||
{project?.emoji ? renderEmoji(project?.emoji) : project?.icon_prop ? renderEmoji(project?.icon_prop) : null}
|
<span className="grid place-items-center flex-shrink-0">
|
||||||
</span>
|
{project?.emoji ? renderEmoji(project?.emoji) : project?.icon_prop ? renderEmoji(project?.icon_prop) : null}
|
||||||
)}
|
</span>
|
||||||
{!hideText && <span className="flex-grow truncate">{project?.name ?? placeholder}</span>}
|
)}
|
||||||
{dropdownArrow && (
|
{!hideText && <span className="flex-grow truncate">{project?.name ?? placeholder}</span>}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
{dropdownArrow && (
|
||||||
)}
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
</div>
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -136,8 +151,9 @@ export const ProjectDropdown: React.FC<Props> = observer((props) => {
|
|||||||
onChange,
|
onChange,
|
||||||
placeholder = "Project",
|
placeholder = "Project",
|
||||||
placement,
|
placement,
|
||||||
value,
|
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
tooltip = false,
|
||||||
|
value,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@ -239,6 +255,7 @@ export const ProjectDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "border-without-text" ? (
|
) : buttonVariant === "border-without-text" ? (
|
||||||
<BorderButton
|
<BorderButton
|
||||||
@ -249,6 +266,7 @@ export const ProjectDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-with-text" ? (
|
) : buttonVariant === "background-with-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -258,6 +276,7 @@ export const ProjectDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-without-text" ? (
|
) : buttonVariant === "background-without-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -268,6 +287,7 @@ export const ProjectDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-with-text" ? (
|
) : buttonVariant === "transparent-with-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -277,6 +297,7 @@ export const ProjectDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-without-text" ? (
|
) : buttonVariant === "transparent-without-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -287,6 +308,7 @@ export const ProjectDropdown: React.FC<Props> = observer((props) => {
|
|||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
hideText
|
hideText
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
</button>
|
</button>
|
||||||
|
@ -8,7 +8,7 @@ import { useApplication, useProjectState } from "hooks/store";
|
|||||||
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
import { useDropdownKeyDown } from "hooks/use-dropdown-key-down";
|
||||||
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
import useOutsideClickDetector from "hooks/use-outside-click-detector";
|
||||||
// icons
|
// icons
|
||||||
import { StateGroupIcon } from "@plane/ui";
|
import { StateGroupIcon, Tooltip } from "@plane/ui";
|
||||||
// helpers
|
// helpers
|
||||||
import { cn } from "helpers/common.helper";
|
import { cn } from "helpers/common.helper";
|
||||||
// types
|
// types
|
||||||
@ -31,65 +31,111 @@ type ButtonProps = {
|
|||||||
hideIcon?: boolean;
|
hideIcon?: boolean;
|
||||||
hideText?: boolean;
|
hideText?: boolean;
|
||||||
state: IState | undefined;
|
state: IState | undefined;
|
||||||
|
tooltip: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const BorderButton = (props: ButtonProps) => {
|
const BorderButton = (props: ButtonProps) => {
|
||||||
const { className, dropdownArrow, dropdownArrowClassName, hideIcon = false, hideText = false, state } = props;
|
const {
|
||||||
|
className,
|
||||||
|
dropdownArrow,
|
||||||
|
dropdownArrowClassName,
|
||||||
|
hideIcon = false,
|
||||||
|
hideText = false,
|
||||||
|
state,
|
||||||
|
tooltip,
|
||||||
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="State" tooltipContent={state?.name ?? "State"} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
className={cn(
|
||||||
className
|
"h-full flex items-center gap-1.5 border-[0.5px] border-custom-border-300 hover:bg-custom-background-80 rounded text-xs px-2 py-0.5",
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && (
|
>
|
||||||
<StateGroupIcon stateGroup={state?.group ?? "backlog"} color={state?.color} className="h-3 w-3 flex-shrink-0" />
|
{!hideIcon && (
|
||||||
)}
|
<StateGroupIcon
|
||||||
{!hideText && <span className="flex-grow truncate">{state?.name ?? "State"}</span>}
|
stateGroup={state?.group ?? "backlog"}
|
||||||
{dropdownArrow && (
|
color={state?.color}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
className="h-3 w-3 flex-shrink-0"
|
||||||
)}
|
/>
|
||||||
</div>
|
)}
|
||||||
|
{!hideText && <span className="flex-grow truncate">{state?.name ?? "State"}</span>}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const BackgroundButton = (props: ButtonProps) => {
|
const BackgroundButton = (props: ButtonProps) => {
|
||||||
const { className, dropdownArrow, dropdownArrowClassName, hideIcon = false, hideText = false, state } = props;
|
const {
|
||||||
|
className,
|
||||||
|
dropdownArrow,
|
||||||
|
dropdownArrowClassName,
|
||||||
|
hideIcon = false,
|
||||||
|
hideText = false,
|
||||||
|
state,
|
||||||
|
tooltip,
|
||||||
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="State" tooltipContent={state?.name ?? "State"} disabled={!tooltip}>
|
||||||
className={cn("h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80", className)}
|
<div
|
||||||
>
|
className={cn(
|
||||||
{!hideIcon && (
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 bg-custom-background-80",
|
||||||
<StateGroupIcon stateGroup={state?.group ?? "backlog"} color={state?.color} className="h-3 w-3 flex-shrink-0" />
|
className
|
||||||
)}
|
)}
|
||||||
{!hideText && <span className="flex-grow truncate">{state?.name ?? "State"}</span>}
|
>
|
||||||
{dropdownArrow && (
|
{!hideIcon && (
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
<StateGroupIcon
|
||||||
)}
|
stateGroup={state?.group ?? "backlog"}
|
||||||
</div>
|
color={state?.color}
|
||||||
|
className="h-3 w-3 flex-shrink-0"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{!hideText && <span className="flex-grow truncate">{state?.name ?? "State"}</span>}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const TransparentButton = (props: ButtonProps) => {
|
const TransparentButton = (props: ButtonProps) => {
|
||||||
const { className, dropdownArrow, dropdownArrowClassName, hideIcon = false, hideText = false, state } = props;
|
const {
|
||||||
|
className,
|
||||||
|
dropdownArrow,
|
||||||
|
dropdownArrowClassName,
|
||||||
|
hideIcon = false,
|
||||||
|
hideText = false,
|
||||||
|
state,
|
||||||
|
tooltip,
|
||||||
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Tooltip tooltipHeading="State" tooltipContent={state?.name ?? "State"} disabled={!tooltip}>
|
||||||
className={cn(
|
<div
|
||||||
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
className={cn(
|
||||||
className
|
"h-full flex items-center gap-1.5 rounded text-xs px-2 py-0.5 hover:bg-custom-background-80",
|
||||||
)}
|
className
|
||||||
>
|
)}
|
||||||
{!hideIcon && (
|
>
|
||||||
<StateGroupIcon stateGroup={state?.group ?? "backlog"} color={state?.color} className="h-3 w-3 flex-shrink-0" />
|
{!hideIcon && (
|
||||||
)}
|
<StateGroupIcon
|
||||||
{!hideText && <span className="flex-grow truncate">{state?.name ?? "State"}</span>}
|
stateGroup={state?.group ?? "backlog"}
|
||||||
{dropdownArrow && (
|
color={state?.color}
|
||||||
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
className="h-3 w-3 flex-shrink-0"
|
||||||
)}
|
/>
|
||||||
</div>
|
)}
|
||||||
|
{!hideText && <span className="flex-grow truncate">{state?.name ?? "State"}</span>}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDown className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -107,8 +153,9 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
onChange,
|
onChange,
|
||||||
placement,
|
placement,
|
||||||
projectId,
|
projectId,
|
||||||
value,
|
|
||||||
tabIndex,
|
tabIndex,
|
||||||
|
tooltip = false,
|
||||||
|
value,
|
||||||
} = props;
|
} = props;
|
||||||
// states
|
// states
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
@ -204,6 +251,7 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "border-without-text" ? (
|
) : buttonVariant === "border-without-text" ? (
|
||||||
<BorderButton
|
<BorderButton
|
||||||
@ -212,6 +260,7 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-with-text" ? (
|
) : buttonVariant === "background-with-text" ? (
|
||||||
@ -221,6 +270,7 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "background-without-text" ? (
|
) : buttonVariant === "background-without-text" ? (
|
||||||
<BackgroundButton
|
<BackgroundButton
|
||||||
@ -229,6 +279,7 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-with-text" ? (
|
) : buttonVariant === "transparent-with-text" ? (
|
||||||
@ -238,6 +289,7 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
hideIcon={hideIcon}
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
/>
|
/>
|
||||||
) : buttonVariant === "transparent-without-text" ? (
|
) : buttonVariant === "transparent-without-text" ? (
|
||||||
<TransparentButton
|
<TransparentButton
|
||||||
@ -245,6 +297,8 @@ export const StateDropdown: React.FC<Props> = observer((props) => {
|
|||||||
className={buttonClassName}
|
className={buttonClassName}
|
||||||
dropdownArrow={dropdownArrow && !disabled}
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
|
hideIcon={hideIcon}
|
||||||
|
tooltip={tooltip}
|
||||||
hideText
|
hideText
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
|
1
web/components/dropdowns/types.d.ts
vendored
1
web/components/dropdowns/types.d.ts
vendored
@ -18,4 +18,5 @@ export type TDropdownProps = {
|
|||||||
placeholder?: string;
|
placeholder?: string;
|
||||||
placement?: Placement;
|
placement?: Placement;
|
||||||
tabIndex?: number;
|
tabIndex?: number;
|
||||||
|
tooltip?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -81,6 +81,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
|||||||
projectId={issue.project_id}
|
projectId={issue.project_id}
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
|
tooltip
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</WithDisplayPropertiesHOC>
|
</WithDisplayPropertiesHOC>
|
||||||
@ -94,6 +95,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
|||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
buttonVariant="border-without-text"
|
buttonVariant="border-without-text"
|
||||||
buttonClassName="border"
|
buttonClassName="border"
|
||||||
|
tooltip
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</WithDisplayPropertiesHOC>
|
</WithDisplayPropertiesHOC>
|
||||||
@ -121,6 +123,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
|||||||
placeholder="Start date"
|
placeholder="Start date"
|
||||||
buttonVariant={issue.start_date ? "border-with-text" : "border-without-text"}
|
buttonVariant={issue.start_date ? "border-with-text" : "border-without-text"}
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
|
tooltip
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</WithDisplayPropertiesHOC>
|
</WithDisplayPropertiesHOC>
|
||||||
@ -136,6 +139,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
|||||||
placeholder="Due date"
|
placeholder="Due date"
|
||||||
buttonVariant={issue.target_date ? "border-with-text" : "border-without-text"}
|
buttonVariant={issue.target_date ? "border-with-text" : "border-without-text"}
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
|
tooltip
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</WithDisplayPropertiesHOC>
|
</WithDisplayPropertiesHOC>
|
||||||
@ -151,6 +155,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
|||||||
multiple
|
multiple
|
||||||
buttonVariant={issue.assignee_ids?.length > 0 ? "transparent-without-text" : "border-without-text"}
|
buttonVariant={issue.assignee_ids?.length > 0 ? "transparent-without-text" : "border-without-text"}
|
||||||
buttonClassName={issue.assignee_ids?.length > 0 ? "hover:bg-transparent px-0" : ""}
|
buttonClassName={issue.assignee_ids?.length > 0 ? "hover:bg-transparent px-0" : ""}
|
||||||
|
tooltip
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</WithDisplayPropertiesHOC>
|
</WithDisplayPropertiesHOC>
|
||||||
@ -165,6 +170,7 @@ export const IssueProperties: React.FC<IIssueProperties> = observer((props) => {
|
|||||||
projectId={issue.project_id}
|
projectId={issue.project_id}
|
||||||
disabled={isReadOnly}
|
disabled={isReadOnly}
|
||||||
buttonVariant="border-with-text"
|
buttonVariant="border-with-text"
|
||||||
|
tooltip
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</WithDisplayPropertiesHOC>
|
</WithDisplayPropertiesHOC>
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
<svg width="94" height="94" viewBox="0 0 94 94" fill="none" xmlns="http://www.w3.org/2000/svg">
|
<svg width="94" height="94" viewBox="0 0 94 94" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
<circle cx="46.7188" cy="46.7188" r="46.7188" fill="#F9F9FB"/>
|
<circle cx="46.7188" cy="46.7188" r="46.7188" fill="#F9F9FB"/>
|
||||||
<path d="M74.5 34.2487V29.9987C74.5 28.4958 73.903 27.0545 72.8403 25.9918C71.7776 24.9291 70.3362 24.332 68.8333 24.332H29.1667C27.6638 24.332 26.2224 24.9291 25.1597 25.9918C24.097 27.0545 23.5 28.4958 23.5 29.9987V69.6654C23.5 71.1683 24.097 72.6096 25.1597 73.6723C26.2224 74.735 27.6638 75.332 29.1667 75.332H39.0833" stroke="#D9D9E0" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M69.625 35.4362V31.7487C69.625 30.4447 69.107 29.1941 68.1849 28.2721C67.2629 27.35 66.0123 26.832 64.7083 26.832H30.2917C28.9877 26.832 27.7371 27.35 26.8151 28.2721C25.893 29.1941 25.375 30.4447 25.375 31.7487V66.1654C25.375 67.4693 25.893 68.7199 26.8151 69.642C27.7371 70.564 28.9877 71.082 30.2917 71.082H38.8958" stroke="#D9D9E0" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M60.332 18.668V30.0013" stroke="#CDCED6" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M57.332 21.918V31.7513" stroke="#CDCED6" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M37.668 18.668V30.0013" stroke="#CDCED6" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M37.668 21.918V31.7513" stroke="#CDCED6" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M23.5 41.332H37.6667" stroke="#D9D9E0" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M25.375 41.582H37.6667" stroke="#D9D9E0" stroke-width="5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M64.582 62.5846L60.332 59.1846V52.668" stroke="#B9BBC6" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M61.0195 60.0221L57.332 57.0721V51.418" stroke="#B9BBC6" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<path d="M60.332 75.332C69.7209 75.332 77.332 67.7209 77.332 58.332C77.332 48.9432 69.7209 41.332 60.332 41.332C50.9432 41.332 43.332 48.9432 43.332 58.332C43.332 67.7209 50.9432 75.332 60.332 75.332Z" stroke="#B9BBC6" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M57.332 71.082C65.4782 71.082 72.082 64.4782 72.082 56.332C72.082 48.1858 65.4782 41.582 57.332 41.582C49.1858 41.582 42.582 48.1858 42.582 56.332C42.582 64.4782 49.1858 71.082 57.332 71.082Z" stroke="#B9BBC6" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Loading…
Reference in New Issue
Block a user