UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: новый канон внешних контуров и стандартизация свойств

This commit is contained in:
DCCONSTRUCTIONS
2026-04-20 11:40:20 +03:00
parent 8fed697531
commit b1f980bc7f
14 changed files with 403 additions and 94 deletions
@@ -26,6 +26,7 @@ import { usePlatformOS } from "@/hooks/use-platform-os";
export type TWorkItemLabelSelectBaseProps = {
buttonClassName?: string;
buttonContainerClassName?: string;
rootClassName?: string;
createLabelEnabled?: boolean;
disabled?: boolean;
getLabelById: (labelId: string) => IIssueLabel | null;
@@ -43,6 +44,7 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
const {
buttonClassName,
buttonContainerClassName,
rootClassName,
createLabelEnabled = false,
disabled = false,
getLabelById,
@@ -157,7 +159,9 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
tabIndex={tabIndex}
value={value}
onChange={dropdownOnChange}
className="relative h-full flex-shrink-0"
className={cn("relative h-full flex-shrink-0", rootClassName, {
"w-full": rootClassName?.includes("w-full") || buttonContainerClassName?.includes("w-full"),
})}
multiple
disabled={disabled}
onKeyDown={handleKeyDown}
@@ -181,7 +185,7 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
) : (
<div
className={cn(
"flex h-full items-center justify-center gap-1 rounded-sm border-[0.5px] border-strong px-2 py-1 text-11 hover:bg-layer-1",
"nodedc-modal-field flex h-full items-center justify-center gap-1 px-3 py-1.5 text-11",
buttonClassName
)}
>
@@ -192,26 +196,26 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
</button>
{isDropdownOpen && (
<Combobox.Options className="fixed z-10" static>
<Combobox.Options className="fixed z-[120]" static>
<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-dropdown-surface my-1 w-64 min-w-[16rem]"
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<div className="flex items-center gap-1.5 rounded-sm border border-subtle bg-surface-2 px-2">
<div className="nodedc-dropdown-search">
<SearchIcon className="h-3.5 w-3.5 text-placeholder" strokeWidth={1.5} />
<Combobox.Input
as="input"
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"
onChange={(event) => setQuery(event.target.value)}
placeholder={t("search")}
displayValue={(assigned: any) => assigned?.name}
onKeyDown={searchInputKeyDown}
/>
</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">
{labelsList && filteredOptions ? (
filteredOptions.length > 0 ? (
filteredOptions.map((label) => {
@@ -223,14 +227,16 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
<Combobox.Option
key={label.id}
className={({ active }) =>
`${
active ? "bg-layer-1" : ""
} group flex w-full cursor-pointer items-center gap-2 truncate rounded-sm px-1 py-1.5 text-secondary select-none`
cn(
"nodedc-dropdown-option cursor-pointer",
active ? "bg-white/6" : "",
"text-secondary"
)
}
value={label.id}
>
{({ selected }) => (
<div className="flex w-full justify-between gap-2 rounded-sm">
<div className="flex w-full justify-between gap-2 rounded-[0.9rem]">
<div className="flex items-center justify-start gap-2 truncate">
<span
className="h-2.5 w-2.5 flex-shrink-0 rounded-full"
@@ -240,7 +246,7 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
/>
<span className="truncate">{label.name}</span>
</div>
<div className="flex shrink-0 items-center justify-center rounded-sm p-1">
<div className="flex shrink-0 items-center justify-center rounded-[0.9rem] p-1">
<CheckIcon className={`h-3 w-3 ${selected ? "opacity-100" : "opacity-0"}`} />
</div>
</div>
@@ -249,7 +255,7 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
);
} else
return (
<div key={label.id} className="border-y border-subtle">
<div key={label.id} className="overflow-hidden rounded-[1rem] bg-white/[0.02]">
<div className="flex items-center gap-2 truncate p-2 text-primary select-none">
<Component className="h-3 w-3" /> {label.name}
</div>
@@ -258,14 +264,16 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
<Combobox.Option
key={child.id}
className={({ active }) =>
`${
active ? "bg-layer-1" : ""
} group flex min-w-[14rem] cursor-pointer items-center gap-2 truncate rounded-sm px-1 py-1.5 text-secondary select-none`
cn(
"nodedc-dropdown-option min-w-[14rem] cursor-pointer",
active ? "bg-white/6" : "",
"text-secondary"
)
}
value={child.id}
>
{({ selected }) => (
<div className="flex w-full justify-between gap-2 rounded-sm">
<div className="flex w-full justify-between gap-2 rounded-[0.9rem]">
<div className="flex items-center justify-start gap-2">
<span
className="h-2.5 w-2.5 flex-shrink-0 rounded-full"
@@ -275,7 +283,7 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
/>
<span>{child.name}</span>
</div>
<div className="flex items-center justify-center rounded-sm p-1">
<div className="flex items-center justify-center rounded-[0.9rem] p-1">
<CheckIcon className={`h-3 w-3 ${selected ? "opacity-100" : "opacity-0"}`} />
</div>
</div>
@@ -294,12 +302,11 @@ export const WorkItemLabelSelectBase = observer(function WorkItemLabelSelectBase
if (!query.length) return;
handleAddLabel(query);
}}
className={`text-left text-secondary ${query.length ? "cursor-pointer" : "cursor-default"}`}
className={`rounded-[0.9rem] px-2 py-2 text-left text-secondary ${query.length ? "cursor-pointer hover:bg-white/6" : "cursor-default"}`}
>
{/* TODO: translate here */}
{query.length ? (
<>
+ Add <span className="text-primary">&quot;{query}&quot;</span> to labels
+ {t("label.create.type")} <span className="text-primary">&quot;{query}&quot;</span>
</>
) : (
t("label.create.type")
@@ -178,6 +178,10 @@ export class ProjectExternalContoursStore implements IProjectExternalContoursSto
};
handleCurrentTab = async (workspaceSlug: string, projectId: string, tab: TInboxIssueCurrentTab) => {
this.requestIds = [];
this.requests = {};
this.error = undefined;
this.loader = "init-loading";
this.currentTab = tab;
await this.fetchRequests(workspaceSlug, projectId, tab);
};