Skip to content

Commit

Permalink
Change TabstripNext's overflow menu to use a Menu instead of a Dropdown
Browse files Browse the repository at this point in the history
  • Loading branch information
joshwooding committed May 21, 2024
1 parent 5b9f090 commit 4636290
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 37 deletions.
5 changes: 5 additions & 0 deletions .changeset/cool-fishes-appear.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@salt-ds/lab": patch
---

Changed TabstripNext's overflow menu to use a Menu instead of a Dropdown.
60 changes: 41 additions & 19 deletions packages/lab/src/tabs-next/OverflowMenu.tsx
Original file line number Diff line number Diff line change
@@ -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<TabValue> {
export interface OverflowMenuProps extends ButtonProps {
tabs: TabValue[];
onItemClick?: (event: SyntheticEvent, value: string) => void;
}

export const OverflowMenu = forwardRef<HTMLDivElement, OverflowMenuProps>(
export const OverflowMenu = forwardRef<HTMLButtonElement, OverflowMenuProps>(
function OverflowMenu(props, forwardedRef) {
const { tabs, ...rest } = props;
const { tabs, onItemClick, ...rest } = props;
const { ref, overflowCount, isOverflowing } =
useOverflowMenu<HTMLDivElement>();
useOverflowMenu<HTMLButtonElement>();
const handleRef = useForkRef(ref, forwardedRef);
const itemVisibility = useOverflowContext(
(context) => context.itemVisibility
Expand All @@ -28,20 +36,34 @@ export const OverflowMenu = forwardRef<HTMLDivElement, OverflowMenuProps>(

if (!isOverflowing) return null;

const handleItemClick = (event: MouseEvent<HTMLDivElement>) => {
const value = event.currentTarget.dataset.value;
if (value) {
onItemClick?.(event, value);
}
};

return (
<Dropdown<TabValue>
aria-label={`${overflowCount} more tabs`}
triggerComponent={
<Button aria-label="More tabs" variant="secondary" role="combobox">
<OverflowMenuIcon aria-hidden style={{ margin: 0 }} />
<Menu>
<MenuTrigger>
<Button
aria-label={`${overflowCount} more tabs`}
variant="secondary"
role="combobox"
ref={handleRef}
{...rest}
>
<OverflowMenuIcon aria-hidden />
</Button>
}
width="auto"
ref={handleRef}
source={tabList}
selected={null}
{...rest}
/>
</MenuTrigger>
<MenuPanel>
{tabList.map(({ value, label }) => (
<MenuItem key={value} onClick={handleItemClick} data-value={value}>
{label}
</MenuItem>
))}
</MenuPanel>
</Menu>
);
}
);
27 changes: 9 additions & 18 deletions packages/lab/src/tabs-next/TabstripNext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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");

Expand Down Expand Up @@ -74,7 +73,6 @@ export const TabstripNext = forwardRef<HTMLDivElement, TabstripNextProps>(
state: "selected",
});
const [focusable, setFocusableState] = useState<string | undefined>(value);
const [overflowOpen, setOverflowOpen] = useState(false);

const activate = useCallback(
(event: SyntheticEvent<HTMLButtonElement>) => {
Expand Down Expand Up @@ -115,8 +113,6 @@ export const TabstripNext = forwardRef<HTMLDivElement, TabstripNextProps>(
}, []);

const handleKeyDown = (event: KeyboardEvent<HTMLDivElement>) => {
if (overflowOpen) return;

const elements: HTMLElement[] = Array.from(
tabstripRef.current?.querySelectorAll(
`div:not([data-overflowing]) > [role="tab"]:not([disabled])`
Expand Down Expand Up @@ -148,30 +144,26 @@ export const TabstripNext = forwardRef<HTMLDivElement, TabstripNextProps>(
onKeyDown?.(event);
};

const handleOverflowItemClick: SelectionChangeHandler<TabValue> = (
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,
Expand Down Expand Up @@ -218,8 +210,7 @@ export const TabstripNext = forwardRef<HTMLDivElement, TabstripNextProps>(
{children}
<OverflowMenu
tabs={tabList}
onOpenChange={handleOverflowOpenChange}
onSelectionChange={handleOverflowItemClick}
onItemClick={handleOverflowItemClick}
/>
</div>
</Overflow>
Expand Down

0 comments on commit 4636290

Please sign in to comment.