UNPKG

@react-md/menu

Version:

Create menus that auto-position themselves within the viewport and adhere to the accessibility guidelines

136 lines (135 loc) 5.25 kB
import type { KeyboardEventHandler, MouseEventHandler, MutableRefObject } from "react"; import type { FABPosition } from "@react-md/button"; import type { BaseMenuHookOptions, BaseMenuHookReturnValue, ProvidedMenuToggleProps } from "./types"; /** @remarks \@since 5.0.0 */ export interface MenuHookOptions<ToggleEl extends HTMLElement> extends BaseMenuHookOptions { /** * Boolean if the toggle component is currently disabled which will prevent * the arrow keys from opening a menuitem's menu. * * @defaultValue `false` */ disabled?: boolean; /** * This is just used to update the default anchor behavior. * * @see {@link FABPosition} * @defaultValue `null` */ floating?: FABPosition; /** * An optional click handler to merge with the * {@link MenuHookReturnValue.onClick} behavior. */ onMenuClick?: MouseEventHandler<HTMLDivElement>; /** * An optional keydown handler to merge with the * {@link MenuHookReturnValue.menuProps} behavior. Calling * `event.stopPropagation()` will prevent the default behavior of closing the * menu when the `"Escape"` key is pressed. */ onMenuKeyDown?: KeyboardEventHandler<HTMLDivElement>; /** * An optional click handler to merge with the toggle visibility behavior. * Calling `event.stopPropagation()` will prevent the default behavior from * occurring. */ onToggleClick?: MouseEventHandler<ToggleEl>; /** * An optional keydown handler to merge with the * {@link ProvidedMenuToggleProps.onKeyDown} behavior. */ onToggleKeyDown?: KeyboardEventHandler<ToggleEl>; /** * An optional keydown handler to merge with the * {@link ProvidedMenuToggleProps.onMouseEnter} behavior. */ onToggleMouseEnter?: MouseEventHandler<ToggleEl>; /** * An optional keydown handler to merge with the * {@link ProvidedMenuToggleProps.onMouseLeave} behavior. */ onToggleMouseLeave?: MouseEventHandler<ToggleEl>; } /** * @remarks \@since 5.0.0 */ export interface MenuHookReturnValue<ToggleEl extends HTMLElement> extends BaseMenuHookReturnValue { /** * A ref that **must** be passed to the toggle element if the toggle should be * refocused when the menu is closed via a keyboard press. This can also be * used if you need access to the toggle element's DOM node for some reason. */ toggleRef: MutableRefObject<ToggleEl | null>; /** * An object of props that must be provided to the toggle element for the * visibility functionality of menus to work. * * @see {@link ProvidedMenuToggleProps} */ toggleProps: ProvidedMenuToggleProps<ToggleEl>; } /** * This hook provides all the functionality for a menu to: * - toggle the `Menu`'s visibility when the `MenuButton` or `MenuItemButton` * has been clicked * - hide the `Menu` when an element outside of the `Menu` has been clicked * - hide the `Menu` when the `Escape` or `Tab` key has been pressed * - focus the `Menu` element when it gains visibility * - refocus the `MenuButton` or `MenuItemButton` when the menu loses visibility * - position the menu within the viewport with {@link useFixedPositioning} * - show the `Menu` when the `ArrowRight` key is pressed for a vertical * `MenuItemButton` * - show the `Menu` when the `ArrowDown` key is pressed for a horizontal * `MenuItemButton` * - hide the `Menu` when the `ArrowRight` key is pressed in a vertical submenu * - hide the `Menu` when the `ArrowDown` key is pressed in a horizontal * submenu * - conditionally hide the `Menu` if the page is scrolled while the `Menu` is * visible * - conditionally hide the `Menu` if the page is resized while the `Menu` is * visible * - conditionally move focus to the next `DropdownMenu` with keyboard movement * when inside of a `MenuBar` * - conditionally enable the visibility for a `DropdownMenu` when the mouse * hovers over a `MenuItemButton` with a parent `MenuBar` that has been * activated * - conditionally show/hide the `Menu` based on a parent `MenuBar`'s `activeId` * * This hook will probably never need to be used externally since it has been * integrated into the `DropdownMenu` component and `useContextMenu` hook. * * @example * Simple Example * ```tsx * import { ReactElement, useState } from "react"; * import { useMenu, Menu, MenuButton, MenuItem } from "@react-md/menu"; * * function Example(): ReactElement { * const [visible, setVisible] = useState(false); * const { menuRef, menuProps, toggleRef, toggleProps } = useMenu< * HTMLButtonElement * >({ * baseId: "custom-menu-button", * visible, * setVisible, * }); * * return ( * <> * <MenuButton ref={toggleRef} {...toggleProps}> * Button * </MenuButton> * <Menu ref={menuRef} {...menuProps}> * <MenuItem>Item 1</MenuItem> * <MenuItem>Item 2</MenuItem> * <MenuItem>Item 3</MenuItem> * </Menu> * </> * ); * } * ``` * * @remarks \@since 5.0.0 */ export declare function useMenu<ToggleEl extends HTMLElement>(options: MenuHookOptions<ToggleEl>): MenuHookReturnValue<ToggleEl>;