From 46362908f52135645ee9fa7ea7600fc679dd764e Mon Sep 17 00:00:00 2001 From: Josh Wooding <12938082+joshwooding@users.noreply.github.com> Date: Tue, 21 May 2024 16:05:03 +0100 Subject: [PATCH] Change TabstripNext's overflow menu to use a Menu instead of a Dropdown --- .changeset/cool-fishes-appear.md | 5 ++ packages/lab/src/tabs-next/OverflowMenu.tsx | 60 ++++++++++++++------- packages/lab/src/tabs-next/TabstripNext.tsx | 27 ++++------ 3 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 .changeset/cool-fishes-appear.md diff --git a/.changeset/cool-fishes-appear.md b/.changeset/cool-fishes-appear.md new file mode 100644 index 0000000000..4faa1e189a --- /dev/null +++ b/.changeset/cool-fishes-appear.md @@ -0,0 +1,5 @@ +--- +"@salt-ds/lab": patch +--- + +Changed TabstripNext's overflow menu to use a Menu instead of a Dropdown. diff --git a/packages/lab/src/tabs-next/OverflowMenu.tsx b/packages/lab/src/tabs-next/OverflowMenu.tsx index 778ee0753c..d2d76cc8a5 100644 --- a/packages/lab/src/tabs-next/OverflowMenu.tsx +++ b/packages/lab/src/tabs-next/OverflowMenu.tsx @@ -1,24 +1,32 @@ -import { forwardRef, ReactNode } from "react"; -import { Button, useForkRef } from "@salt-ds/core"; +import { forwardRef, ReactNode, MouseEvent, SyntheticEvent } from "react"; +import { + Button, + useForkRef, + Menu, + MenuTrigger, + MenuPanel, + MenuItem, + ButtonProps, +} from "@salt-ds/core"; import { OverflowMenuIcon } from "@salt-ds/icons"; import { useOverflowContext, useOverflowMenu } from "@fluentui/react-overflow"; -import { Dropdown, DropdownProps } from "../dropdown"; type TabValue = { value: string; label: ReactNode; }; -export interface OverflowMenuProps extends DropdownProps { +export interface OverflowMenuProps extends ButtonProps { tabs: TabValue[]; + onItemClick?: (event: SyntheticEvent, value: string) => void; } -export const OverflowMenu = forwardRef( +export const OverflowMenu = forwardRef( function OverflowMenu(props, forwardedRef) { - const { tabs, ...rest } = props; + const { tabs, onItemClick, ...rest } = props; const { ref, overflowCount, isOverflowing } = - useOverflowMenu(); + useOverflowMenu(); const handleRef = useForkRef(ref, forwardedRef); const itemVisibility = useOverflowContext( (context) => context.itemVisibility @@ -28,20 +36,34 @@ export const OverflowMenu = forwardRef( if (!isOverflowing) return null; + const handleItemClick = (event: MouseEvent) => { + const value = event.currentTarget.dataset.value; + if (value) { + onItemClick?.(event, value); + } + }; + return ( - - aria-label={`${overflowCount} more tabs`} - triggerComponent={ - - } - width="auto" - ref={handleRef} - source={tabList} - selected={null} - {...rest} - /> + + + {tabList.map(({ value, label }) => ( + + {label} + + ))} + + ); } ); diff --git a/packages/lab/src/tabs-next/TabstripNext.tsx b/packages/lab/src/tabs-next/TabstripNext.tsx index 66050f8521..4e62193359 100644 --- a/packages/lab/src/tabs-next/TabstripNext.tsx +++ b/packages/lab/src/tabs-next/TabstripNext.tsx @@ -17,7 +17,6 @@ import { Overflow } from "@fluentui/react-overflow"; import { OverflowMenu } from "./OverflowMenu"; import tabstripCss from "./TabstripNext.css"; import { TabsContext } from "./TabNextContext"; -import { SelectionChangeHandler } from "../common-hooks"; const withBaseName = makePrefixer("saltTabstripNext"); @@ -74,7 +73,6 @@ export const TabstripNext = forwardRef( state: "selected", }); const [focusable, setFocusableState] = useState(value); - const [overflowOpen, setOverflowOpen] = useState(false); const activate = useCallback( (event: SyntheticEvent) => { @@ -115,8 +113,6 @@ export const TabstripNext = forwardRef( }, []); const handleKeyDown = (event: KeyboardEvent) => { - if (overflowOpen) return; - const elements: HTMLElement[] = Array.from( tabstripRef.current?.querySelectorAll( `div:not([data-overflowing]) > [role="tab"]:not([disabled])` @@ -148,30 +144,26 @@ export const TabstripNext = forwardRef( onKeyDown?.(event); }; - const handleOverflowItemClick: SelectionChangeHandler = ( - event, - item + const handleOverflowItemClick = ( + event: SyntheticEvent, + itemValue: string ) => { - if (item) { - setValue(item.value); + if (itemValue) { + setValue(itemValue); requestAnimationFrame(() => { const element = tabstripRef.current?.querySelector( - `[value="${item.value}"]` + `[value="${itemValue}"]` ); if (element instanceof HTMLElement) { element?.focus(); } }); - if (value !== item.value) { - onChange?.(event, { value: item.value }); + if (value !== itemValue) { + onChange?.(event, { value: itemValue }); } } }; - const handleOverflowOpenChange = (isOpen: boolean) => { - setOverflowOpen(isOpen); - }; - const contextValue = useMemo( () => ({ activate, @@ -218,8 +210,7 @@ export const TabstripNext = forwardRef( {children}