UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: дизайн и русификация God Mode

This commit is contained in:
DCCONSTRUCTIONS
2026-04-29 00:38:04 +03:00
parent 5d336039ba
commit 7f47b85c36
57 changed files with 1104 additions and 588 deletions
@@ -4,11 +4,10 @@
* See the LICENSE file for details.
*/
import React, { Fragment, useState } from "react";
import React, { useCallback, useEffect, useState } from "react";
import { createPortal } from "react-dom";
import type { Placement } from "@popperjs/core";
import { usePopper } from "react-popper";
// headless ui
import { Popover, Portal, Transition } from "@headlessui/react";
// ui
import { Button } from "@plane/propel/button";
@@ -45,93 +44,132 @@ export function FiltersDropdown(props: Props) {
const [referenceElement, setReferenceElement] = useState<HTMLButtonElement | HTMLDivElement | null>(null);
const [popperElement, setPopperElement] = useState<HTMLDivElement | null>(null);
const [isOpen, setIsOpen] = useState(false);
const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: placement ?? "auto",
});
return (
<Popover as="div">
{({ open, close }) => (
<>
<Popover.Button as={React.Fragment}>
{menuButton ? (
<button
type="button"
ref={setReferenceElement}
className={menuButtonWrapperClassName}
disabled={disabled}
>
{typeof menuButton === "function" ? menuButton({ open }) : menuButton}
</button>
) : (
<div ref={setReferenceElement}>
<div className="hidden @4xl:flex">
<Button
disabled={disabled}
variant="secondary"
prependIcon={icon}
tabIndex={tabIndex}
className="nodedc-toolbar-pill nodedc-toolbar-pill-wide relative"
data-active={open}
size="lg"
>
<>
<div className={`${open ? "text-[rgb(var(--nodedc-accent-rgb))]" : "text-secondary"}`}>
<span>{title}</span>
</div>
{isFiltersApplied && (
<span className="absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-accent-primary" />
)}
</>
</Button>
</div>
<div className="flex @4xl:hidden">
<Button
disabled={disabled}
ref={setReferenceElement}
variant="secondary"
tabIndex={tabIndex}
className="nodedc-toolbar-pill nodedc-toolbar-pill-wide"
size="lg"
>
{miniIcon || title}
</Button>
</div>
</div>
)}
</Popover.Button>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
enterFrom="opacity-0 translate-y-1"
enterTo="opacity-100 translate-y-0"
leave="transition ease-in duration-150"
leaveFrom="opacity-100 translate-y-0"
leaveTo="opacity-0 translate-y-1"
const toggleDropdown = useCallback(() => {
if (!disabled) setIsOpen((current) => !current);
}, [disabled]);
const closeDropdown = useCallback(() => setIsOpen(false), []);
const handleTriggerKeyDown = useCallback(
(event: React.KeyboardEvent<HTMLDivElement>) => {
if (disabled) return;
if (event.key === "Enter" || event.key === " ") {
event.preventDefault();
toggleDropdown();
}
if (event.key === "Escape") closeDropdown();
},
[closeDropdown, disabled, toggleDropdown]
);
useEffect(() => {
if (!isOpen) return;
const handleDocumentMouseDown = (event: MouseEvent) => {
const target = event.target;
if (!(target instanceof Node)) return;
if (referenceElement?.contains(target) || popperElement?.contains(target)) return;
closeDropdown();
};
const handleDocumentKeyDown = (event: KeyboardEvent) => {
if (event.key === "Escape") closeDropdown();
};
document.addEventListener("mousedown", handleDocumentMouseDown);
document.addEventListener("keydown", handleDocumentKeyDown);
return () => {
document.removeEventListener("mousedown", handleDocumentMouseDown);
document.removeEventListener("keydown", handleDocumentKeyDown);
};
}, [closeDropdown, isOpen, popperElement, referenceElement]);
const dropdownPanel =
isOpen &&
createPortal(
<div className="fixed z-[760] translate-y-0">
<div
className={`nodedc-dropdown-surface my-1 overflow-hidden ${dropdownClassName ?? ""}`}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<div
className={`flex max-h-[30rem] w-[18.75rem] flex-col overflow-hidden lg:max-h-[37.5rem] ${
dropdownContentClassName ?? ""
}`}
>
<Portal>
{/** translate-y-0 is a hack to create new stacking context. Required for safari */}
<Popover.Panel className="fixed z-[760] translate-y-0">
<div
className={`nodedc-dropdown-surface my-1 overflow-hidden ${dropdownClassName ?? ""}`}
ref={setPopperElement}
style={styles.popper}
{...attributes.popper}
>
<div
className={`flex max-h-[30rem] w-[18.75rem] flex-col overflow-hidden lg:max-h-[37.5rem] ${
dropdownContentClassName ?? ""
}`}
>
{typeof children === "function" ? children({ closeDropdown: close }) : children}
</div>
{typeof children === "function" ? children({ closeDropdown }) : children}
</div>
</div>
</div>,
document.body
);
return (
<>
{menuButton ? (
<button
type="button"
ref={setReferenceElement}
className={menuButtonWrapperClassName}
disabled={disabled}
tabIndex={tabIndex}
onClick={toggleDropdown}
>
{typeof menuButton === "function" ? menuButton({ open: isOpen }) : menuButton}
</button>
) : (
<div
ref={setReferenceElement}
role="button"
tabIndex={disabled ? -1 : tabIndex}
aria-disabled={disabled}
onClick={toggleDropdown}
onKeyDown={handleTriggerKeyDown}
>
<div className="hidden @4xl:flex">
<Button
disabled={disabled}
variant="secondary"
prependIcon={icon}
tabIndex={-1}
className="nodedc-toolbar-pill nodedc-toolbar-pill-wide relative"
data-active={isOpen}
size="lg"
>
<>
<div className={`${isOpen ? "text-[rgb(var(--nodedc-accent-rgb))]" : "text-secondary"}`}>
<span>{title}</span>
</div>
</Popover.Panel>
</Portal>
</Transition>
</>
{isFiltersApplied && (
<span className="absolute -top-0.5 -right-0.5 h-2 w-2 rounded-full bg-accent-primary" />
)}
</>
</Button>
</div>
<div className="flex @4xl:hidden">
<Button
disabled={disabled}
variant="secondary"
tabIndex={-1}
className="nodedc-toolbar-pill nodedc-toolbar-pill-wide"
size="lg"
>
{miniIcon || title}
</Button>
</div>
</div>
)}
</Popover>
{dropdownPanel}
</>
);
}