UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: поиск из лупы, маршрутизация и статусные dropdown
This commit is contained in:
parent
21581373cd
commit
16f1552b22
|
|
@ -7,7 +7,6 @@
|
||||||
import type { ReactNode } from "react";
|
import type { ReactNode } from "react";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useTranslation } from "@plane/i18n";
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { Badge } from "@plane/propel/badge";
|
|
||||||
import type { TExternalContourRequest } from "@plane/types";
|
import type { TExternalContourRequest } from "@plane/types";
|
||||||
import { Avatar } from "@plane/ui";
|
import { Avatar } from "@plane/ui";
|
||||||
import { renderFormattedDate } from "@plane/utils";
|
import { renderFormattedDate } from "@plane/utils";
|
||||||
|
|
@ -54,7 +53,7 @@ export const ExternalContoursRequestTraceability = observer(function ExternalCon
|
||||||
</TraceabilityCell>
|
</TraceabilityCell>
|
||||||
|
|
||||||
<TraceabilityCell label={t("external_contours_page.traceability.target_contour")}>
|
<TraceabilityCell label={t("external_contours_page.traceability.target_contour")}>
|
||||||
<Badge variant="neutral">{targetProjectName}</Badge>
|
{targetProjectName}
|
||||||
</TraceabilityCell>
|
</TraceabilityCell>
|
||||||
|
|
||||||
<TraceabilityCell label={t("external_contours_page.traceability.status")}>
|
<TraceabilityCell label={t("external_contours_page.traceability.status")}>
|
||||||
|
|
@ -72,7 +71,7 @@ export const ExternalContoursRequestTraceability = observer(function ExternalCon
|
||||||
{assigneeDetails.length > 0 ? (
|
{assigneeDetails.length > 0 ? (
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
<div className="flex flex-wrap items-center gap-2">
|
||||||
{assigneeDetails.map((assignee) => (
|
{assigneeDetails.map((assignee) => (
|
||||||
<div key={assignee.id} className="flex items-center gap-2 rounded-sm border border-strong px-2 py-1">
|
<div key={assignee.id} className="flex items-center gap-2">
|
||||||
<Avatar src={assignee.avatar_url || ""} name={assignee.display_name || t("common.none")} size="sm" showTooltip />
|
<Avatar src={assignee.avatar_url || ""} name={assignee.display_name || t("common.none")} size="sm" showTooltip />
|
||||||
<span className="text-12 font-medium text-secondary">{assignee.display_name}</span>
|
<span className="text-12 font-medium text-secondary">{assignee.display_name}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -91,13 +90,13 @@ export const ExternalContoursRequestTraceability = observer(function ExternalCon
|
||||||
{requestedAt ? renderFormattedDate(requestedAt) : t("common.none")}
|
{requestedAt ? renderFormattedDate(requestedAt) : t("common.none")}
|
||||||
</TraceabilityCell>
|
</TraceabilityCell>
|
||||||
|
|
||||||
<TraceabilityCell label={t("external_contours_page.traceability.due_date")}>
|
|
||||||
{dueDate}
|
|
||||||
</TraceabilityCell>
|
|
||||||
|
|
||||||
<TraceabilityCell label={t("external_contours_page.traceability.last_updated")}>
|
<TraceabilityCell label={t("external_contours_page.traceability.last_updated")}>
|
||||||
{lastUpdatedAt ? renderFormattedDate(lastUpdatedAt) : t("common.none")}
|
{lastUpdatedAt ? renderFormattedDate(lastUpdatedAt) : t("common.none")}
|
||||||
</TraceabilityCell>
|
</TraceabilityCell>
|
||||||
|
|
||||||
|
<TraceabilityCell label={t("external_contours_page.traceability.due_date")}>
|
||||||
|
{dueDate}
|
||||||
|
</TraceabilityCell>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ export function ExternalContourStatePill(props: Props) {
|
||||||
const state = request.issue.state_detail;
|
const state = request.issue.state_detail;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="inline-flex items-center gap-1 rounded-sm border border-subtle bg-layer-2 px-1.5 py-0.5 text-11 font-medium text-secondary">
|
<div className="inline-flex items-center gap-1.5 text-13 font-medium text-secondary">
|
||||||
<StateGroupIcon
|
<StateGroupIcon
|
||||||
stateGroup={state?.group ?? "backlog"}
|
stateGroup={state?.group ?? "backlog"}
|
||||||
color={state?.color}
|
color={state?.color}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { usePopper } from "react-popper";
|
||||||
import { Combobox } from "@headlessui/react";
|
import { Combobox } from "@headlessui/react";
|
||||||
// plane imports
|
// plane imports
|
||||||
import { useTranslation } from "@plane/i18n";
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { SearchIcon, IntakeStateGroupIcon, ChevronDownIcon } from "@plane/propel/icons";
|
import { SearchIcon, IntakeStateGroupIcon, ChevronDownIcon, CheckIcon } from "@plane/propel/icons";
|
||||||
import type { IIntakeState } from "@plane/types";
|
import type { IIntakeState } from "@plane/types";
|
||||||
import { ComboDropDown, Spinner } from "@plane/ui";
|
import { ComboDropDown, Spinner } from "@plane/ui";
|
||||||
import { cn } from "@plane/utils";
|
import { cn } from "@plane/utils";
|
||||||
|
|
@ -21,9 +21,6 @@ import { BUTTON_VARIANTS_WITH_TEXT } from "@/components/dropdowns/constants";
|
||||||
import type { TDropdownProps } from "@/components/dropdowns/types";
|
import type { TDropdownProps } from "@/components/dropdowns/types";
|
||||||
// hooks
|
// hooks
|
||||||
import { useDropdown } from "@/hooks/use-dropdown";
|
import { useDropdown } from "@/hooks/use-dropdown";
|
||||||
// plane web imports
|
|
||||||
import { StateOption } from "@/plane-web/components/workflow";
|
|
||||||
|
|
||||||
export type TWorkItemStateDropdownBaseProps = TDropdownProps & {
|
export type TWorkItemStateDropdownBaseProps = TDropdownProps & {
|
||||||
alwaysAllowStateChange?: boolean;
|
alwaysAllowStateChange?: boolean;
|
||||||
button?: ReactNode;
|
button?: ReactNode;
|
||||||
|
|
@ -135,70 +132,69 @@ export const WorkItemStateDropdownBase = observer(function WorkItemStateDropdown
|
||||||
handleClose();
|
handleClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
const comboButton = (
|
const comboButton = button ? (
|
||||||
<>
|
<button
|
||||||
{button ? (
|
ref={setReferenceElement}
|
||||||
<button
|
type="button"
|
||||||
ref={setReferenceElement}
|
className={cn(
|
||||||
type="button"
|
"clickable block h-full w-full rounded-full border-0 bg-transparent shadow-none outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0",
|
||||||
className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)}
|
buttonContainerClassName
|
||||||
onClick={handleOnClick}
|
|
||||||
disabled={disabled}
|
|
||||||
tabIndex={tabIndex}
|
|
||||||
>
|
|
||||||
{button}
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
tabIndex={tabIndex}
|
|
||||||
ref={setReferenceElement}
|
|
||||||
type="button"
|
|
||||||
className={cn(
|
|
||||||
"clickable block h-full max-w-full outline-none",
|
|
||||||
{
|
|
||||||
"cursor-not-allowed text-secondary": disabled,
|
|
||||||
"cursor-pointer": !disabled,
|
|
||||||
},
|
|
||||||
buttonContainerClassName
|
|
||||||
)}
|
|
||||||
onClick={handleOnClick}
|
|
||||||
disabled={disabled}
|
|
||||||
>
|
|
||||||
<DropdownButton
|
|
||||||
className={buttonClassName}
|
|
||||||
isActive={isOpen}
|
|
||||||
tooltipHeading={t("state")}
|
|
||||||
tooltipContent={selectedState?.name ?? t("state")}
|
|
||||||
showTooltip={showTooltip}
|
|
||||||
variant={buttonVariant}
|
|
||||||
renderToolTipByDefault={renderByDefault}
|
|
||||||
>
|
|
||||||
{isInitializing ? (
|
|
||||||
<Spinner className="h-3.5 w-3.5" />
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{!hideIcon && (
|
|
||||||
<IntakeStateGroupIcon
|
|
||||||
stateGroup={selectedState?.group ?? "triage"}
|
|
||||||
color={selectedState?.color ?? "var(--text-color-tertiary)"}
|
|
||||||
className={cn("flex-shrink-0", iconSize)}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{BUTTON_VARIANTS_WITH_TEXT.includes(buttonVariant) && (
|
|
||||||
<span className="flex-grow truncate text-left">{selectedState?.name ?? t("state")}</span>
|
|
||||||
)}
|
|
||||||
{dropdownArrow && (
|
|
||||||
<ChevronDownIcon
|
|
||||||
className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)}
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</DropdownButton>
|
|
||||||
</button>
|
|
||||||
)}
|
)}
|
||||||
</>
|
onClick={handleOnClick}
|
||||||
|
disabled={disabled}
|
||||||
|
tabIndex={tabIndex}
|
||||||
|
>
|
||||||
|
{button}
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
tabIndex={tabIndex}
|
||||||
|
ref={setReferenceElement}
|
||||||
|
type="button"
|
||||||
|
className={cn(
|
||||||
|
"clickable block h-full max-w-full rounded-full border-0 bg-transparent shadow-none outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0",
|
||||||
|
{
|
||||||
|
"cursor-not-allowed text-secondary": disabled,
|
||||||
|
"cursor-pointer": !disabled,
|
||||||
|
},
|
||||||
|
buttonContainerClassName
|
||||||
|
)}
|
||||||
|
onClick={handleOnClick}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
<DropdownButton
|
||||||
|
className={buttonClassName}
|
||||||
|
isActive={isOpen}
|
||||||
|
tooltipHeading={t("state")}
|
||||||
|
tooltipContent={selectedState?.name ?? t("state")}
|
||||||
|
showTooltip={showTooltip}
|
||||||
|
variant={buttonVariant}
|
||||||
|
renderToolTipByDefault={renderByDefault}
|
||||||
|
>
|
||||||
|
{isInitializing ? (
|
||||||
|
<Spinner className="h-3.5 w-3.5" />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{!hideIcon && (
|
||||||
|
<IntakeStateGroupIcon
|
||||||
|
stateGroup={selectedState?.group ?? "triage"}
|
||||||
|
color={selectedState?.color ?? "var(--text-color-tertiary)"}
|
||||||
|
className={cn("flex-shrink-0", iconSize)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{BUTTON_VARIANTS_WITH_TEXT.includes(buttonVariant) && (
|
||||||
|
<span className="flex-grow truncate text-left">{selectedState?.name ?? t("state")}</span>
|
||||||
|
)}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDownIcon
|
||||||
|
className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</DropdownButton>
|
||||||
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -216,17 +212,17 @@ export const WorkItemStateDropdownBase = observer(function WorkItemStateDropdown
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<Combobox.Options className="fixed z-10" static>
|
<Combobox.Options className="fixed z-10" static>
|
||||||
<div
|
<div
|
||||||
className="my-1 w-48 rounded-sm border-[0.5px] border-strong bg-surface-1 px-2 py-2.5 text-11 shadow-raised-200 focus:outline-none"
|
className="nodedc-glass-modal nodedc-glass-surface my-1 w-52 rounded-[1.25rem] border-0 px-3 py-3 text-12 shadow-none outline-none"
|
||||||
ref={setPopperElement}
|
ref={setPopperElement}
|
||||||
style={styles.popper}
|
style={styles.popper}
|
||||||
{...attributes.popper}
|
{...attributes.popper}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-1.5 rounded-sm border border-subtle bg-surface-2 px-2">
|
<div className="flex items-center gap-1.5 rounded-[0.95rem] border-0 bg-white/5 px-3 py-2 outline-none">
|
||||||
<SearchIcon className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
|
<SearchIcon className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
|
||||||
<Combobox.Input
|
<Combobox.Input
|
||||||
as="input"
|
as="input"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="w-full bg-transparent py-1 text-11 text-secondary placeholder:text-placeholder focus:outline-none"
|
className="w-full bg-transparent py-0 text-12 text-secondary placeholder:text-placeholder outline-none focus:outline-none"
|
||||||
value={query}
|
value={query}
|
||||||
onChange={(e) => setQuery(e.target.value)}
|
onChange={(e) => setQuery(e.target.value)}
|
||||||
placeholder={t("common.search.label")}
|
placeholder={t("common.search.label")}
|
||||||
|
|
@ -234,17 +230,28 @@ export const WorkItemStateDropdownBase = observer(function WorkItemStateDropdown
|
||||||
onKeyDown={searchInputKeyDown}
|
onKeyDown={searchInputKeyDown}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 max-h-48 space-y-1 overflow-y-scroll">
|
<div className="mt-2 max-h-56 space-y-1 overflow-y-auto">
|
||||||
{filteredOptions ? (
|
{filteredOptions ? (
|
||||||
filteredOptions.length > 0 ? (
|
filteredOptions.length > 0 ? (
|
||||||
filteredOptions.map((option) => (
|
filteredOptions.map((option) => (
|
||||||
<StateOption
|
<Combobox.Option
|
||||||
{...props}
|
|
||||||
key={option.value}
|
key={option.value}
|
||||||
option={option}
|
value={option.value}
|
||||||
selectedValue={value}
|
className={({ active, selected }) =>
|
||||||
className="flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-sm px-1 py-1.5 select-none"
|
cn(
|
||||||
/>
|
`flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-[0.9rem] px-2 py-2 select-none outline-none ${
|
||||||
|
active ? "bg-white/6" : ""
|
||||||
|
} ${selected ? "text-primary" : "text-secondary"}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{({ selected }) => (
|
||||||
|
<>
|
||||||
|
<span className="flex-grow truncate">{option.content}</span>
|
||||||
|
{selected && <CheckIcon className="h-3.5 w-3.5 flex-shrink-0" />}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Combobox.Option>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<p className="px-1.5 py-1 text-placeholder italic">{t("no_matching_results")}</p>
|
<p className="px-1.5 py-1 text-placeholder italic">{t("no_matching_results")}</p>
|
||||||
|
|
|
||||||
|
|
@ -102,26 +102,18 @@ function BorderButton(props: ButtonProps) {
|
||||||
>
|
>
|
||||||
{!hideIcon &&
|
{!hideIcon &&
|
||||||
(priority ? (
|
(priority ? (
|
||||||
<div
|
<PriorityIcon
|
||||||
className={cn({
|
priority={priority}
|
||||||
// highlight just the icon if text is visible and priority is urgent
|
size={12}
|
||||||
"rounded-sm border border-priority-urgent p-0.5": priority === "urgent" && !hideText && highlightUrgent,
|
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",
|
||||||
})}
|
})}
|
||||||
>
|
/>
|
||||||
<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
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<SignalHigh className="size-3" />
|
<SignalHigh className="size-3" />
|
||||||
))}
|
))}
|
||||||
|
|
@ -132,7 +124,7 @@ function BorderButton(props: ButtonProps) {
|
||||||
"text-placeholder": !priority || priority === "none",
|
"text-placeholder": !priority || priority === "none",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{priorityDetails?.title ?? placeholder}
|
{priority ? t(priority) : placeholder}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{dropdownArrow && (
|
{dropdownArrow && (
|
||||||
|
|
@ -193,26 +185,18 @@ function BackgroundButton(props: ButtonProps) {
|
||||||
>
|
>
|
||||||
{!hideIcon &&
|
{!hideIcon &&
|
||||||
(priority ? (
|
(priority ? (
|
||||||
<div
|
<PriorityIcon
|
||||||
className={cn({
|
priority={priority}
|
||||||
// highlight just the icon if text is visible and priority is urgent
|
size={12}
|
||||||
"rounded-sm border border-priority-urgent p-0.5": priority === "urgent" && !hideText && highlightUrgent,
|
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",
|
||||||
})}
|
})}
|
||||||
>
|
/>
|
||||||
<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
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<SignalHigh className="size-3" />
|
<SignalHigh className="size-3" />
|
||||||
))}
|
))}
|
||||||
|
|
@ -223,7 +207,7 @@ function BackgroundButton(props: ButtonProps) {
|
||||||
"text-placeholder": !priority || priority === "none",
|
"text-placeholder": !priority || priority === "none",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{priorityDetails?.title ?? t("common.priority") ?? placeholder}
|
{priority ? t(priority) : t("common.priority") ?? placeholder}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{dropdownArrow && (
|
{dropdownArrow && (
|
||||||
|
|
@ -277,26 +261,18 @@ function TransparentButton(props: ButtonProps) {
|
||||||
>
|
>
|
||||||
{!hideIcon &&
|
{!hideIcon &&
|
||||||
(priority ? (
|
(priority ? (
|
||||||
<div
|
<PriorityIcon
|
||||||
className={cn({
|
priority={priority}
|
||||||
// highlight just the icon if text is visible and priority is urgent
|
size={12}
|
||||||
"rounded-sm border border-priority-urgent p-0.5": priority === "urgent" && !hideText && highlightUrgent,
|
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",
|
||||||
})}
|
})}
|
||||||
>
|
/>
|
||||||
<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
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
) : (
|
) : (
|
||||||
<SignalHigh className="size-3" />
|
<SignalHigh className="size-3" />
|
||||||
))}
|
))}
|
||||||
|
|
@ -307,7 +283,7 @@ function TransparentButton(props: ButtonProps) {
|
||||||
"text-placeholder": !priority || priority === "none",
|
"text-placeholder": !priority || priority === "none",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{priorityDetails?.title ?? t("common.priority") ?? placeholder}
|
{priority ? t(priority) : t("common.priority") ?? placeholder}
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
{dropdownArrow && (
|
{dropdownArrow && (
|
||||||
|
|
@ -368,8 +344,8 @@ export function PriorityDropdown(props: Props) {
|
||||||
query: priority.key,
|
query: priority.key,
|
||||||
content: (
|
content: (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<PriorityIcon priority={priority.key} size={14} withContainer />
|
<PriorityIcon priority={priority.key} size={14} />
|
||||||
<span className="flex-grow truncate">{priority.title}</span>
|
<span className="flex-grow truncate">{t(priority.key)}</span>
|
||||||
</div>
|
</div>
|
||||||
),
|
),
|
||||||
}));
|
}));
|
||||||
|
|
@ -398,63 +374,53 @@ export function PriorityDropdown(props: Props) {
|
||||||
? BackgroundButton
|
? BackgroundButton
|
||||||
: TransparentButton;
|
: TransparentButton;
|
||||||
|
|
||||||
const comboButton = (
|
const comboButton = button ? (
|
||||||
<>
|
<button
|
||||||
{button ? (
|
ref={setReferenceElement}
|
||||||
<button
|
type="button"
|
||||||
ref={setReferenceElement}
|
className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)}
|
||||||
type="button"
|
onClick={handleOnClick}
|
||||||
className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)}
|
disabled={disabled}
|
||||||
onClick={handleOnClick}
|
tabIndex={tabIndex}
|
||||||
disabled={disabled}
|
>
|
||||||
tabIndex={tabIndex}
|
{button}
|
||||||
>
|
</button>
|
||||||
{button}
|
) : (
|
||||||
</button>
|
<button
|
||||||
) : (
|
ref={setReferenceElement}
|
||||||
<button
|
type="button"
|
||||||
ref={setReferenceElement}
|
className={cn(
|
||||||
type="button"
|
"clickable block h-full max-w-full outline-none",
|
||||||
className={cn(
|
{
|
||||||
"clickable block h-full max-w-full outline-none",
|
"cursor-not-allowed text-secondary": disabled,
|
||||||
{
|
"cursor-pointer": !disabled,
|
||||||
"cursor-not-allowed text-secondary": disabled,
|
},
|
||||||
"cursor-pointer": !disabled,
|
buttonContainerClassName
|
||||||
},
|
|
||||||
buttonContainerClassName
|
|
||||||
)}
|
|
||||||
onClick={handleOnClick}
|
|
||||||
disabled={disabled}
|
|
||||||
tabIndex={tabIndex}
|
|
||||||
>
|
|
||||||
<ButtonToRender
|
|
||||||
priority={value ?? undefined}
|
|
||||||
className={buttonClassName}
|
|
||||||
highlightUrgent={highlightUrgent}
|
|
||||||
dropdownArrow={dropdownArrow && !disabled}
|
|
||||||
dropdownArrowClassName={dropdownArrowClassName}
|
|
||||||
hideIcon={hideIcon}
|
|
||||||
placeholder={placeholder}
|
|
||||||
showTooltip={showTooltip}
|
|
||||||
hideText={BUTTON_VARIANTS_WITHOUT_TEXT.includes(buttonVariant)}
|
|
||||||
renderToolTipByDefault={renderByDefault}
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
)}
|
)}
|
||||||
</>
|
onClick={handleOnClick}
|
||||||
|
disabled={disabled}
|
||||||
|
tabIndex={tabIndex}
|
||||||
|
>
|
||||||
|
<ButtonToRender
|
||||||
|
priority={value ?? undefined}
|
||||||
|
className={buttonClassName}
|
||||||
|
highlightUrgent={highlightUrgent}
|
||||||
|
dropdownArrow={dropdownArrow && !disabled}
|
||||||
|
dropdownArrowClassName={dropdownArrowClassName}
|
||||||
|
hideIcon={hideIcon}
|
||||||
|
placeholder={placeholder}
|
||||||
|
showTooltip={showTooltip}
|
||||||
|
hideText={BUTTON_VARIANTS_WITHOUT_TEXT.includes(buttonVariant)}
|
||||||
|
renderToolTipByDefault={renderByDefault}
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ComboDropDown
|
<ComboDropDown
|
||||||
as="div"
|
as="div"
|
||||||
ref={dropdownRef}
|
ref={dropdownRef}
|
||||||
className={cn(
|
className={cn("h-full", className)}
|
||||||
"h-full",
|
|
||||||
{
|
|
||||||
"bg-layer-1": isOpen,
|
|
||||||
},
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
value={value}
|
value={value}
|
||||||
onChange={dropdownOnChange}
|
onChange={dropdownOnChange}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
|
|
@ -465,17 +431,17 @@ export function PriorityDropdown(props: Props) {
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<Combobox.Options className="fixed z-10" static>
|
<Combobox.Options className="fixed z-10" static>
|
||||||
<div
|
<div
|
||||||
className="my-1 w-48 rounded-sm border-[0.5px] border-strong bg-surface-1 px-2 py-2.5 text-11 shadow-raised-200 focus:outline-none"
|
className="nodedc-glass-modal nodedc-glass-surface my-1 w-52 rounded-[1.25rem] border-0 px-3 py-3 text-12 shadow-none outline-none"
|
||||||
ref={setPopperElement}
|
ref={setPopperElement}
|
||||||
style={styles.popper}
|
style={styles.popper}
|
||||||
{...attributes.popper}
|
{...attributes.popper}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-1.5 rounded-sm border border-subtle bg-surface-2 px-2">
|
<div className="flex items-center gap-1.5 rounded-[0.95rem] border-0 bg-white/5 px-3 py-2 outline-none">
|
||||||
<SearchIcon className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
|
<SearchIcon className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
|
||||||
<Combobox.Input
|
<Combobox.Input
|
||||||
as="input"
|
as="input"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="w-full bg-transparent py-1 text-11 text-secondary placeholder:text-placeholder focus:outline-none"
|
className="w-full bg-transparent py-0 text-12 text-secondary placeholder:text-placeholder outline-none focus:outline-none"
|
||||||
value={query}
|
value={query}
|
||||||
onChange={(e) => setQuery(e.target.value)}
|
onChange={(e) => setQuery(e.target.value)}
|
||||||
placeholder={t("search")}
|
placeholder={t("search")}
|
||||||
|
|
@ -483,7 +449,7 @@ export function PriorityDropdown(props: Props) {
|
||||||
onKeyDown={searchInputKeyDown}
|
onKeyDown={searchInputKeyDown}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 max-h-48 space-y-1 overflow-y-scroll">
|
<div className="mt-2 max-h-56 space-y-1 overflow-y-auto">
|
||||||
{filteredOptions.length > 0 ? (
|
{filteredOptions.length > 0 ? (
|
||||||
filteredOptions.map((option) => (
|
filteredOptions.map((option) => (
|
||||||
<Combobox.Option
|
<Combobox.Option
|
||||||
|
|
@ -491,8 +457,8 @@ export function PriorityDropdown(props: Props) {
|
||||||
value={option.value}
|
value={option.value}
|
||||||
className={({ active, selected }) =>
|
className={({ active, selected }) =>
|
||||||
cn(
|
cn(
|
||||||
`flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-sm px-1 py-1.5 select-none ${
|
`flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-[0.9rem] px-2 py-2 select-none outline-none ${
|
||||||
active ? "bg-layer-transparent-hover" : ""
|
active ? "bg-white/6" : ""
|
||||||
} ${selected ? "text-primary" : "text-secondary"}`
|
} ${selected ? "text-primary" : "text-secondary"}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ import { usePopper } from "react-popper";
|
||||||
import { Combobox } from "@headlessui/react";
|
import { Combobox } from "@headlessui/react";
|
||||||
// plane imports
|
// plane imports
|
||||||
import { useTranslation } from "@plane/i18n";
|
import { useTranslation } from "@plane/i18n";
|
||||||
import { SearchIcon, StateGroupIcon, ChevronDownIcon } from "@plane/propel/icons";
|
import { SearchIcon, StateGroupIcon, ChevronDownIcon, CheckIcon } from "@plane/propel/icons";
|
||||||
import type { IState } from "@plane/types";
|
import type { IState } from "@plane/types";
|
||||||
import { ComboDropDown, Spinner } from "@plane/ui";
|
import { ComboDropDown, Spinner } from "@plane/ui";
|
||||||
import { cn } from "@plane/utils";
|
import { cn } from "@plane/utils";
|
||||||
|
|
@ -21,9 +21,6 @@ import { BUTTON_VARIANTS_WITH_TEXT } from "@/components/dropdowns/constants";
|
||||||
import type { TDropdownProps } from "@/components/dropdowns/types";
|
import type { TDropdownProps } from "@/components/dropdowns/types";
|
||||||
// hooks
|
// hooks
|
||||||
import { useDropdown } from "@/hooks/use-dropdown";
|
import { useDropdown } from "@/hooks/use-dropdown";
|
||||||
// plane web imports
|
|
||||||
import { StateOption } from "@/plane-web/components/workflow";
|
|
||||||
|
|
||||||
export type TWorkItemStateDropdownBaseProps = TDropdownProps & {
|
export type TWorkItemStateDropdownBaseProps = TDropdownProps & {
|
||||||
alwaysAllowStateChange?: boolean;
|
alwaysAllowStateChange?: boolean;
|
||||||
button?: ReactNode;
|
button?: ReactNode;
|
||||||
|
|
@ -136,71 +133,70 @@ export const WorkItemStateDropdownBase = observer(function WorkItemStateDropdown
|
||||||
handleClose();
|
handleClose();
|
||||||
};
|
};
|
||||||
|
|
||||||
const comboButton = (
|
const comboButton = button ? (
|
||||||
<>
|
<button
|
||||||
{button ? (
|
ref={setReferenceElement}
|
||||||
<button
|
type="button"
|
||||||
ref={setReferenceElement}
|
className={cn(
|
||||||
type="button"
|
"clickable block h-full w-full rounded-full border-0 bg-transparent shadow-none outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0",
|
||||||
className={cn("clickable block h-full w-full outline-none", buttonContainerClassName)}
|
buttonContainerClassName
|
||||||
onClick={handleOnClick}
|
|
||||||
disabled={disabled}
|
|
||||||
tabIndex={tabIndex}
|
|
||||||
>
|
|
||||||
{button}
|
|
||||||
</button>
|
|
||||||
) : (
|
|
||||||
<button
|
|
||||||
tabIndex={tabIndex}
|
|
||||||
ref={setReferenceElement}
|
|
||||||
type="button"
|
|
||||||
className={cn(
|
|
||||||
"clickable block h-full max-w-full outline-none",
|
|
||||||
{
|
|
||||||
"cursor-not-allowed text-secondary": disabled,
|
|
||||||
"cursor-pointer": !disabled,
|
|
||||||
},
|
|
||||||
buttonContainerClassName
|
|
||||||
)}
|
|
||||||
onClick={handleOnClick}
|
|
||||||
disabled={disabled}
|
|
||||||
>
|
|
||||||
<DropdownButton
|
|
||||||
className={buttonClassName}
|
|
||||||
isActive={isOpen}
|
|
||||||
tooltipHeading={t("state")}
|
|
||||||
tooltipContent={selectedState?.name ?? t("state")}
|
|
||||||
showTooltip={showTooltip}
|
|
||||||
variant={buttonVariant}
|
|
||||||
renderToolTipByDefault={renderByDefault}
|
|
||||||
>
|
|
||||||
{isInitializing ? (
|
|
||||||
<Spinner className="h-3.5 w-3.5" />
|
|
||||||
) : (
|
|
||||||
<>
|
|
||||||
{!hideIcon && (
|
|
||||||
<StateGroupIcon
|
|
||||||
stateGroup={selectedState?.group ?? "backlog"}
|
|
||||||
color={selectedState?.color ?? "var(--text-color-tertiary)"}
|
|
||||||
className={cn("flex-shrink-0", iconSize)}
|
|
||||||
percentage={selectedState?.order}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{BUTTON_VARIANTS_WITH_TEXT.includes(buttonVariant) && (
|
|
||||||
<span className="flex-grow truncate text-left">{selectedState?.name ?? t("state")}</span>
|
|
||||||
)}
|
|
||||||
{dropdownArrow && (
|
|
||||||
<ChevronDownIcon
|
|
||||||
className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)}
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</DropdownButton>
|
|
||||||
</button>
|
|
||||||
)}
|
)}
|
||||||
</>
|
onClick={handleOnClick}
|
||||||
|
disabled={disabled}
|
||||||
|
tabIndex={tabIndex}
|
||||||
|
>
|
||||||
|
{button}
|
||||||
|
</button>
|
||||||
|
) : (
|
||||||
|
<button
|
||||||
|
tabIndex={tabIndex}
|
||||||
|
ref={setReferenceElement}
|
||||||
|
type="button"
|
||||||
|
className={cn(
|
||||||
|
"clickable block h-full max-w-full rounded-full border-0 bg-transparent shadow-none outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0",
|
||||||
|
{
|
||||||
|
"cursor-not-allowed text-secondary": disabled,
|
||||||
|
"cursor-pointer": !disabled,
|
||||||
|
},
|
||||||
|
buttonContainerClassName
|
||||||
|
)}
|
||||||
|
onClick={handleOnClick}
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
<DropdownButton
|
||||||
|
className={buttonClassName}
|
||||||
|
isActive={isOpen}
|
||||||
|
tooltipHeading={t("state")}
|
||||||
|
tooltipContent={selectedState?.name ?? t("state")}
|
||||||
|
showTooltip={showTooltip}
|
||||||
|
variant={buttonVariant}
|
||||||
|
renderToolTipByDefault={renderByDefault}
|
||||||
|
>
|
||||||
|
{isInitializing ? (
|
||||||
|
<Spinner className="h-3.5 w-3.5" />
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
{!hideIcon && (
|
||||||
|
<StateGroupIcon
|
||||||
|
stateGroup={selectedState?.group ?? "backlog"}
|
||||||
|
color={selectedState?.color ?? "var(--text-color-tertiary)"}
|
||||||
|
className={cn("flex-shrink-0", iconSize)}
|
||||||
|
percentage={selectedState?.order}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{BUTTON_VARIANTS_WITH_TEXT.includes(buttonVariant) && (
|
||||||
|
<span className="flex-grow truncate text-left">{selectedState?.name ?? t("state")}</span>
|
||||||
|
)}
|
||||||
|
{dropdownArrow && (
|
||||||
|
<ChevronDownIcon
|
||||||
|
className={cn("h-2.5 w-2.5 flex-shrink-0", dropdownArrowClassName)}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</DropdownButton>
|
||||||
|
</button>
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
@ -218,17 +214,17 @@ export const WorkItemStateDropdownBase = observer(function WorkItemStateDropdown
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<Combobox.Options className="fixed z-10" static>
|
<Combobox.Options className="fixed z-10" static>
|
||||||
<div
|
<div
|
||||||
className="my-1 w-48 rounded-sm border-[0.5px] border-strong bg-surface-1 px-2 py-2.5 text-11 shadow-raised-200 focus:outline-none"
|
className="nodedc-glass-modal nodedc-glass-surface my-1 w-52 rounded-[1.25rem] border-0 px-3 py-3 text-12 shadow-none outline-none"
|
||||||
ref={setPopperElement}
|
ref={setPopperElement}
|
||||||
style={styles.popper}
|
style={styles.popper}
|
||||||
{...attributes.popper}
|
{...attributes.popper}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-1.5 rounded-sm border border-subtle bg-surface-2 px-2">
|
<div className="flex items-center gap-1.5 rounded-[0.95rem] border-0 bg-white/5 px-3 py-2 outline-none">
|
||||||
<SearchIcon className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
|
<SearchIcon className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
|
||||||
<Combobox.Input
|
<Combobox.Input
|
||||||
as="input"
|
as="input"
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
className="w-full bg-transparent py-1 text-11 text-secondary placeholder:text-placeholder focus:outline-none"
|
className="w-full bg-transparent py-0 text-12 text-secondary placeholder:text-placeholder outline-none focus:outline-none"
|
||||||
value={query}
|
value={query}
|
||||||
onChange={(e) => setQuery(e.target.value)}
|
onChange={(e) => setQuery(e.target.value)}
|
||||||
placeholder={t("common.search.label")}
|
placeholder={t("common.search.label")}
|
||||||
|
|
@ -236,17 +232,28 @@ export const WorkItemStateDropdownBase = observer(function WorkItemStateDropdown
|
||||||
onKeyDown={searchInputKeyDown}
|
onKeyDown={searchInputKeyDown}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-2 max-h-48 space-y-1 overflow-y-scroll">
|
<div className="mt-2 max-h-56 space-y-1 overflow-y-auto">
|
||||||
{filteredOptions ? (
|
{filteredOptions ? (
|
||||||
filteredOptions.length > 0 ? (
|
filteredOptions.length > 0 ? (
|
||||||
filteredOptions.map((option) => (
|
filteredOptions.map((option) => (
|
||||||
<StateOption
|
<Combobox.Option
|
||||||
{...props}
|
|
||||||
key={option.value}
|
key={option.value}
|
||||||
option={option}
|
value={option.value}
|
||||||
selectedValue={value}
|
className={({ active, selected }) =>
|
||||||
className="flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-sm px-1 py-1.5 select-none"
|
cn(
|
||||||
/>
|
`flex w-full cursor-pointer items-center justify-between gap-2 truncate rounded-[0.9rem] px-2 py-2 select-none outline-none ${
|
||||||
|
active ? "bg-white/6" : ""
|
||||||
|
} ${selected ? "text-primary" : "text-secondary"}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{({ selected }) => (
|
||||||
|
<>
|
||||||
|
<span className="flex-grow truncate">{option.content}</span>
|
||||||
|
{selected && <CheckIcon className="h-3.5 w-3.5 flex-shrink-0" />}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Combobox.Option>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<p className="px-1.5 py-1 text-placeholder italic">{t("no_matching_results")}</p>
|
<p className="px-1.5 py-1 text-placeholder italic">{t("no_matching_results")}</p>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import { Command } from "cmdk";
|
||||||
import { observer } from "mobx-react";
|
import { observer } from "mobx-react";
|
||||||
import { useParams } from "next/navigation";
|
import { useParams } from "next/navigation";
|
||||||
import { createPortal } from "react-dom";
|
import { createPortal } from "react-dom";
|
||||||
|
import { useTranslation } from "@plane/i18n";
|
||||||
// hooks
|
// hooks
|
||||||
import { CloseIcon, SearchIcon } from "@plane/propel/icons";
|
import { CloseIcon, SearchIcon } from "@plane/propel/icons";
|
||||||
import { cn } from "@plane/utils";
|
import { cn } from "@plane/utils";
|
||||||
|
|
@ -28,6 +29,7 @@ type TTopNavPowerKProps = {
|
||||||
|
|
||||||
export const TopNavPowerK = observer((props: TTopNavPowerKProps) => {
|
export const TopNavPowerK = observer((props: TTopNavPowerKProps) => {
|
||||||
const { variant = "top-navigation" } = props;
|
const { variant = "top-navigation" } = props;
|
||||||
|
const { t } = useTranslation();
|
||||||
// router
|
// router
|
||||||
const router = useAppRouter();
|
const router = useAppRouter();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
|
@ -313,7 +315,7 @@ export const TopNavPowerK = observer((props: TTopNavPowerKProps) => {
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
onFocus={handleFocus}
|
onFocus={handleFocus}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder="Search commands..."
|
placeholder={t("power_k.search_menu.quick_command_placeholder")}
|
||||||
className="placeholder-text-placeholder min-w-0 flex-1 bg-transparent text-13 text-primary outline-none"
|
className="placeholder-text-placeholder min-w-0 flex-1 bg-transparent text-13 text-primary outline-none"
|
||||||
/>
|
/>
|
||||||
{searchTerm && (
|
{searchTerm && (
|
||||||
|
|
@ -386,19 +388,24 @@ export const TopNavPowerK = observer((props: TTopNavPowerKProps) => {
|
||||||
if (!isOpen) openPanel();
|
if (!isOpen) openPanel();
|
||||||
}}
|
}}
|
||||||
onMouseDown={handleMouseDown}
|
onMouseDown={handleMouseDown}
|
||||||
onFocus={handleFocus}
|
onFocus={handleFocus}
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder="Search commands..."
|
placeholder={t("power_k.search_menu.quick_command_placeholder")}
|
||||||
className="placeholder-text-placeholder min-w-0 flex-1 bg-transparent text-13 text-primary outline-none"
|
className="placeholder-text-placeholder min-w-0 flex-1 bg-transparent text-13 text-primary outline-none"
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
{searchTerm && (
|
{searchTerm && (
|
||||||
<button type="button" onClick={handleClear} className="ml-2 shrink-0">
|
<button type="button" onClick={handleClear} className="ml-2 shrink-0">
|
||||||
<CloseIcon className="size-3.5 text-placeholder hover:text-primary" />
|
<CloseIcon className="size-3.5 text-placeholder hover:text-primary" />
|
||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<div className="nodedc-glass-modal nodedc-glass-surface mt-3 flex max-h-[70vh] w-full flex-col overflow-hidden rounded-[1.5rem] pt-3">
|
<div className="nodedc-glass-modal nodedc-glass-surface absolute bottom-full left-0 mb-3 flex max-h-[70vh] w-full flex-col overflow-hidden rounded-[1.5rem] pt-3">
|
||||||
|
<div className="px-4 pb-2">
|
||||||
|
<div className="text-[13px] font-medium text-secondary">
|
||||||
|
{t("power_k.search_menu.quick_access_title")}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{searchCommandContent}
|
{searchCommandContent}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -2891,6 +2891,8 @@ export default {
|
||||||
search_menu: {
|
search_menu: {
|
||||||
no_results: "No results found",
|
no_results: "No results found",
|
||||||
clear_search: "Clear search",
|
clear_search: "Clear search",
|
||||||
|
quick_access_title: "Quick access",
|
||||||
|
quick_command_placeholder: "Find a quick command",
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
workspace_level: "Workspace level",
|
workspace_level: "Workspace level",
|
||||||
|
|
|
||||||
|
|
@ -3044,6 +3044,8 @@ export default {
|
||||||
search_menu: {
|
search_menu: {
|
||||||
no_results: "Ничего не найдено",
|
no_results: "Ничего не найдено",
|
||||||
clear_search: "Очистить поиск",
|
clear_search: "Очистить поиск",
|
||||||
|
quick_access_title: "Быстрый доступ",
|
||||||
|
quick_command_placeholder: "Найти быструю команду",
|
||||||
},
|
},
|
||||||
footer: {
|
footer: {
|
||||||
workspace_level: "Уровень рабочего пространства",
|
workspace_level: "Уровень рабочего пространства",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue