diff --git a/frontend/app/element/dropdown.stories.tsx b/frontend/app/element/dropdown.stories.tsx index 456685c0..77fa35f8 100644 --- a/frontend/app/element/dropdown.stories.tsx +++ b/frontend/app/element/dropdown.stories.tsx @@ -40,6 +40,28 @@ export const Test: Story = { setIsDropdownVisible((prev) => !prev); }; + const mapItemsWithClick = (items: any[]) => { + return items.map((item) => ({ + ...item, + onClick: () => { + // Call the original onClick if it exists + if (item.onClick) { + item.onClick(); + } + // Close the dropdown after an item is clicked + setIsDropdownVisible(false); + }, + // Recursively update subItems' onClick handlers + subItems: item.subItems ? mapItemsWithClick(item.subItems) : undefined, + })); + }; + + // Modify args to include updated items with the new onClick behavior + const modifiedArgs = { + ...args, + items: mapItemsWithClick(args.items), + }; + return (
- {isDropdownVisible && } + {isDropdownVisible && } ); }, args: { items: [ - { label: "Option 1", onClick: () => null }, + { label: "Option 1", onClick: (e) => console.log("Clicked Option 1") }, { label: "Option 2", - onClick: () => console.log("Clicked Option 2"), + onClick: (e) => console.log("Clicked Option 2"), subItems: [ - { label: "Option 2 -> 1", onClick: () => null }, - { label: "Option 2 -> 2", onClick: () => null }, + { label: "Option 2 -> 1", onClick: (e) => console.log("Clicked Option 2 -> 1") }, + { label: "Option 2 -> 2", onClick: (e) => console.log("Clicked Option 2 -> 2") }, ], }, { label: "Option 3", - onClick: () => console.log("Clicked Option 3"), + onClick: (e) => console.log("Clicked Option 3"), subItems: [ - { label: "Option 3 -> 1", onClick: () => null }, - { label: "Option 3 -> 2", onClick: () => null }, + { label: "Option 3 -> 1", onClick: (e) => console.log("Clicked Option 3 -> 1") }, + { label: "Option 3 -> 2", onClick: (e) => console.log("Clicked Option 3 -> 2") }, { label: "Option 3 -> 3", - onClick: () => console.log("Clicked Option 3"), + onClick: (e) => console.log("Clicked Option 3 -> 3"), subItems: [ - { label: "Option 3 -> 3 -> 1", onClick: () => null }, - { label: "Option 3 -> 3 -> 2", onClick: () => null }, + { label: "Option 3 -> 3 -> 1", onClick: (e) => console.log("Clicked Option 3 -> 3 -> 1") }, + { label: "Option 3 -> 3 -> 2", onClick: (e) => console.log("Clicked Option 3 -> 3 -> 2") }, + { label: "Option 3 -> 3 -> 3", onClick: (e) => console.log("Clicked Option 3 -> 3 -> 3") }, { - label: "Option 3 -> 3", - onClick: () => console.log("Clicked Option 3"), + label: "Option 3 -> 3 -> 4", + onClick: (e) => console.log("Clicked Option 3 -> 3 -> 4"), subItems: [ - { label: "Option 3 -> 3 -> 1", onClick: () => null }, - { label: "Option 3 -> 3 -> 2", onClick: () => null }, + { + label: "Option 3 -> 3 -> 4 -> 1", + onClick: (e) => console.log("Clicked Option 3 -> 3 -> 4 -> 1"), + }, + { + label: "Option 3 -> 3 -> 4 -> 2", + onClick: (e) => console.log("Clicked Option 3 -> 3 -> 4 -> 2"), + }, + { + label: "Option 3 -> 3 -> 4 -> 3", + onClick: (e) => console.log("Clicked Option 3 -> 3 -> 4 -> 3"), + }, ], }, ], @@ -101,19 +134,15 @@ export const Test: Story = { }, { label: "Option 4", - onClick: () => console.log("Clicked Option 3"), + onClick: (e) => console.log("Clicked Option 4"), subItems: [ - { label: "Option 4 -> 1", onClick: () => null }, - { label: "Option 4 -> 2", onClick: () => null }, - { label: "Option 4 -> 4", onClick: () => null }, - { label: "Option 4 -> 4", onClick: () => null }, - { label: "Option 4 -> 5", onClick: () => null }, - { label: "Option 4 -> 6", onClick: () => null }, - { label: "Option 4 -> 7", onClick: () => null }, - { label: "Option 4 -> 8", onClick: () => null }, - { label: "Option 4 -> 9", onClick: () => null }, - { label: "Option 4 -> 10", onClick: () => null }, - { label: "Option 4 -> 11", onClick: () => null }, + { label: "Option 4 -> 1", onClick: (e) => console.log("Clicked Option 4 -> 1") }, + { label: "Option 4 -> 2", onClick: (e) => console.log("Clicked Option 4 -> 2") }, + { label: "Option 4 -> 3", onClick: (e) => console.log("Clicked Option 4 -> 3") }, + { label: "Option 4 -> 4", onClick: (e) => console.log("Clicked Option 4 -> 4") }, + { label: "Option 4 -> 5", onClick: (e) => console.log("Clicked Option 4 -> 5") }, + { label: "Option 4 -> 6", onClick: (e) => console.log("Clicked Option 4 -> 6") }, + { label: "Option 4 -> 7", onClick: (e) => console.log("Clicked Option 4 -> 7") }, ], }, ], diff --git a/frontend/app/element/dropdown.tsx b/frontend/app/element/dropdown.tsx index 469b2d20..fd9ad2d7 100644 --- a/frontend/app/element/dropdown.tsx +++ b/frontend/app/element/dropdown.tsx @@ -12,16 +12,25 @@ const SubMenu = memo( subMenuPosition, visibleSubMenus, hoveredItems, - handleMouseEnterItem, subMenuRefs, + handleMouseEnterItem, + handleOnClick, }: { subItems: DropdownItem[]; parentKey: string; - subMenuPosition: any; - visibleSubMenus: any; + subMenuPosition: { + [key: string]: { top: number; left: number; label: string }; + }; + visibleSubMenus: { [key: string]: any }; hoveredItems: string[]; - handleMouseEnterItem: any; - subMenuRefs: any; + subMenuRefs: React.MutableRefObject<{ [key: string]: React.RefObject }>; + handleMouseEnterItem: ( + event: React.MouseEvent, + parentKey: string | null, + index: number, + item: DropdownItem + ) => void; + handleOnClick: (e: React.MouseEvent, item: DropdownItem) => void; }) => { // Ensure a ref exists for each submenu subItems.forEach((_, idx) => { @@ -54,8 +63,9 @@ const SubMenu = memo( return (
handleMouseEnterItem(event, parentKey, idx, item)} + onClick={(e) => handleOnClick(e, item)} > {item.label} {item.subItems && } @@ -65,8 +75,9 @@ const SubMenu = memo( parentKey={newKey} subMenuPosition={subMenuPosition} visibleSubMenus={visibleSubMenus} - hoveredItems={hoveredItems} // Pass hoveredItems to submenus + hoveredItems={hoveredItems} handleMouseEnterItem={handleMouseEnterItem} + handleOnClick={handleOnClick} subMenuRefs={subMenuRefs} /> )} @@ -81,7 +92,7 @@ const SubMenu = memo( type DropdownItem = { label: string; - onClick?: () => void; + onClick?: (e) => void; subItems?: DropdownItem[]; }; @@ -238,6 +249,11 @@ const Dropdown = memo( handleSubMenuPosition(key, itemRect, dropdownRef, item.label); }; + const handleOnClick = (e: React.MouseEvent, item: DropdownItem) => { + e.stopPropagation(); + item.onClick && item.onClick(e); + }; + return ReactDOM.createPortal(
handleMouseEnterItem(event, null, index, item)} + onClick={(e) => handleOnClick(e, item)} > {item.label} {item.subItems && } @@ -262,8 +279,9 @@ const Dropdown = memo( parentKey={key} subMenuPosition={subMenuPosition} visibleSubMenus={visibleSubMenus} - hoveredItems={hoveredItems} // Pass hoveredItems to submenus + hoveredItems={hoveredItems} handleMouseEnterItem={handleMouseEnterItem} + handleOnClick={handleOnClick} subMenuRefs={subMenuRefs} /> )}