UI - МЕЖПРОЕКТНАЯ КОММУНИКАЦИЯ: миграция secondary detail action-menu на ActionDropdown

This commit is contained in:
DCCONSTRUCTIONS
2026-04-22 12:31:17 +03:00
parent b0173c82e6
commit c86fc16cdf
6 changed files with 176 additions and 215 deletions
@@ -21,6 +21,7 @@ export interface IActionDropdownProps {
button?: TActionDropdownTrigger;
buttonClassName?: string;
className?: string;
disabled?: boolean;
items: TContextMenuItem[];
menuClassName?: string;
onOpenChange?: (isOpen: boolean) => void;
@@ -107,13 +108,14 @@ function ActionDropdownItem(props: TActionDropdownItemProps) {
}
export function ActionDropdown(props: IActionDropdownProps) {
const { button, buttonClassName, className, items, menuClassName, onOpenChange, placement, portalElement } = props;
const { button, buttonClassName, className, disabled = false, items, menuClassName, onOpenChange, placement, portalElement } = props;
const dropdownRef = React.useRef<HTMLDivElement | null>(null);
const [referenceElement, setReferenceElement] = React.useState<HTMLElement | null>(null);
const [popperElement, setPopperElement] = React.useState<HTMLDivElement | null>(null);
const [isOpen, setIsOpen] = React.useState(false);
const renderedItems = items.filter((item) => item.shouldRender !== false);
const isDropdownDisabled = disabled || renderedItems.length === 0;
const { styles, attributes } = usePopper(referenceElement, popperElement, {
placement: placement ?? "bottom-end",
@@ -141,10 +143,10 @@ export function ActionDropdown(props: IActionDropdownProps) {
});
const openDropdown = React.useCallback(() => {
if (renderedItems.length === 0) return;
if (isDropdownDisabled) return;
setIsOpen(true);
onOpenChange?.(true);
}, [onOpenChange, renderedItems.length]);
}, [isDropdownDisabled, onOpenChange]);
const closeDropdown = React.useCallback(() => {
if (!isOpen) return;
@@ -156,7 +158,7 @@ export function ActionDropdown(props: IActionDropdownProps) {
event.preventDefault();
event.stopPropagation();
if (renderedItems.length === 0) return;
if (isDropdownDisabled) return;
if (isOpen) {
closeDropdown();
@@ -177,14 +179,14 @@ export function ActionDropdown(props: IActionDropdownProps) {
className={cn(
"clickable relative grid place-items-center rounded-sm border-0 bg-transparent p-1 text-secondary shadow-none outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0 hover:text-primary",
{
"cursor-not-allowed": renderedItems.length === 0,
"cursor-pointer": renderedItems.length > 0,
"cursor-not-allowed": isDropdownDisabled,
"cursor-pointer": !isDropdownDisabled,
},
buttonClassName
)}
onClick={handleTriggerClick}
onKeyDown={handleKeyDown}
disabled={renderedItems.length === 0}
disabled={isDropdownDisabled}
aria-haspopup="menu"
aria-expanded={isOpen}
aria-label="Work item actions"
@@ -201,14 +203,14 @@ export function ActionDropdown(props: IActionDropdownProps) {
className={cn(
"clickable block h-full rounded-full border-0 bg-transparent p-0 shadow-none outline-none focus:outline-none focus-visible:outline-none focus-visible:ring-0",
{
"cursor-not-allowed": renderedItems.length === 0,
"cursor-pointer": renderedItems.length > 0,
"cursor-not-allowed": isDropdownDisabled,
"cursor-pointer": !isDropdownDisabled,
},
buttonClassName
)}
onClick={handleTriggerClick}
onKeyDown={handleKeyDown}
disabled={renderedItems.length === 0}
disabled={isDropdownDisabled}
aria-haspopup="menu"
aria-expanded={isOpen}
aria-label="Work item actions"