office-ui-fabric-react
Version:
Reusable React components for building experiences for Microsoft 365.
559 lines (558 loc) • 20.2 kB
TypeScript
import * as React from 'react';
import { DirectionalHint } from '../../common/DirectionalHint';
import { IFocusZoneProps } from '../../FocusZone';
import { IIconProps } from '../Icon/Icon.types';
import { ICalloutProps, ICalloutContentStyleProps } from '../../Callout';
import { ITheme, IStyle } from '../../Styling';
import { IButtonStyles } from '../../Button';
import { IRefObject, IBaseProps, IRectangle, IRenderFunction, IStyleFunctionOrObject } from '../../Utilities';
import { IWithResponsiveModeState } from '../../utilities/decorators/withResponsiveMode';
import { IContextualMenuClassNames, IMenuItemClassNames } from './ContextualMenu.classNames';
export { DirectionalHint } from '../../common/DirectionalHint';
import { IVerticalDividerClassNames } from '../Divider/VerticalDivider.types';
import { IContextualMenuItemProps, IContextualMenuRenderItem, IContextualMenuItemStyleProps, IContextualMenuItemRenderFunctions } from './ContextualMenuItem.types';
import { IKeytipProps } from '../../Keytip';
import { Target } from '@uifabric/react-hooks';
/**
* {@docCategory ContextualMenu}
*/
export declare enum ContextualMenuItemType {
Normal = 0,
Divider = 1,
Header = 2,
Section = 3
}
/**
* {@docCategory ContextualMenu}
*/
export interface IContextualMenu {
}
/**
* {@docCategory ContextualMenu}
*/
export interface IContextualMenuProps extends IBaseProps<IContextualMenu>, IWithResponsiveModeState {
/**
* Optional callback to access the IContextualMenu interface. Use this instead of ref for accessing
* the public methods and properties of the component.
*/
componentRef?: IRefObject<IContextualMenu>;
/**
* Call to provide customized styling that will layer on top of the variant rules.
*/
styles?: IStyleFunctionOrObject<IContextualMenuStyleProps, IContextualMenuStyles>;
/**
* Theme provided by higher-order component.
*/
theme?: ITheme;
/**
* Additional CSS class to apply to the ContextualMenu.
*/
className?: string;
/**
* The target that the ContextualMenu should try to position itself based on.
* It can be either an element, a query selector string resolving to a valid element,
* or a MouseEvent. If a MouseEvent is given, the origin point of the event will be used.
*/
target?: Target;
/**
* How the menu should be positioned
* @defaultvalue DirectionalHint.bottomAutoEdge
*/
directionalHint?: DirectionalHint;
/**
* How the menu should be positioned in RTL layouts.
* If not specified, a mirror of `directionalHint` will be used.
*/
directionalHintForRTL?: DirectionalHint;
/**
* The gap between the ContextualMenu and the target
* @defaultvalue 0
*/
gapSpace?: number;
/**
* The width of the beak.
* @defaultvalue 16
*/
beakWidth?: number;
/**
* If true the context menu will render as the same width as the target element
* @defaultvalue false
*/
useTargetWidth?: boolean;
/**
* If true the context menu will have a minimum width equal to the width of the target element
* @defaultvalue false
*/
useTargetAsMinWidth?: boolean;
/**
* The bounding rectangle (or callback that returns a rectangle) which the contextual menu can appear in.
*/
bounds?: IRectangle | ((target?: Target, targetWindow?: Window) => IRectangle | undefined);
/**
* If true then the beak is visible. If false it will not be shown.
*/
isBeakVisible?: boolean;
/**
* If true, the menu will be positioned to cover the target.
* If false, it will be positioned next to the target.
* @defaultvalue false
*/
coverTarget?: boolean;
/**
* If true the positioning logic will prefer to flip edges rather than to nudge the rectangle to fit within bounds,
* thus making sure the element aligns perfectly with target's alignment edge
*/
alignTargetEdge?: boolean;
/**
* Menu items to display.
*/
items: IContextualMenuItem[];
/**
* Used as `aria-labelledby` for the menu element inside the callout.
*/
labelElementId?: string;
/**
* Whether to focus on the menu when mounted.
* @defaultvalue true
*/
shouldFocusOnMount?: boolean;
/**
* Whether to focus on the contextual menu container (as opposed to the first menu item).
*/
shouldFocusOnContainer?: boolean;
/**
* Callback when the ContextualMenu tries to close. If `dismissAll` is true then all
* submenus will be dismissed.
*/
onDismiss?: (ev?: React.MouseEvent | React.KeyboardEvent, dismissAll?: boolean) => void;
/**
* Click handler which is invoked if `onClick` is not passed for individual contextual
* menu item.
* Returning true will dismiss the menu even if `ev.preventDefault()` was called.
*/
onItemClick?: (ev?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>, item?: IContextualMenuItem) => boolean | void;
/**
* Whether this menu is a submenu of another menu.
*/
isSubMenu?: boolean;
/**
* ID for the ContextualMenu's root element (inside the callout).
* Should be used for `aria-owns` and other such uses, rather than direct reference for programmatic purposes.
*/
id?: string;
/**
* Accessible label for the ContextualMenu's root element (inside the callout).
*/
ariaLabel?: string;
/**
* If true do not render on a new layer. If false render on a new layer.
* @defaultvalue false
*/
doNotLayer?: boolean;
/**
* If true the position will not change sides in an attempt to fit the ContextualMenu within bounds.
* It will still attempt to align it to whatever bounds are given.
* @defaultvalue false
*/
directionalHintFixed?: boolean;
/**
* Callback for when the menu has been opened.
*/
onMenuOpened?: (contextualMenu?: IContextualMenuProps) => void;
/**
* Callback for when the menu is being closed (removing from the DOM).
*/
onMenuDismissed?: (contextualMenu?: IContextualMenuProps) => void;
/**
* Additional custom props for the Callout.
*/
calloutProps?: ICalloutProps;
/**
* Title to be displayed at the top of the menu, above the items.
*/
title?: string;
/**
* Method to provide the classnames to style the contextual menu.
* @deprecated Use `styles` instead to leverage mergeStyles API.
*/
getMenuClassNames?: (theme: ITheme, className?: string) => IContextualMenuClassNames;
/** Custom render function for a submenu. */
onRenderSubMenu?: IRenderFunction<IContextualMenuProps>;
/**
* Method to override the render of the list of menu items.
*/
onRenderMenuList?: IRenderFunction<IContextualMenuListProps>;
/**
* Delay (in milliseconds) to wait before expanding / dismissing a submenu on mouseEnter or mouseLeave
*/
subMenuHoverDelay?: number;
/**
* Custom component to use for rendering individual menu items.
* @defaultvalue ContextualMenuItem
*/
contextualMenuItemAs?: React.ComponentClass<IContextualMenuItemProps> | React.FunctionComponent<IContextualMenuItemProps>;
/**
* Props to pass down to the FocusZone.
* NOTE: the default FocusZoneDirection will be used unless a direction
* is specified in the focusZoneProps (even if other focusZoneProps are defined)
* @defaultvalue \{ direction: FocusZoneDirection.vertical \}
*/
focusZoneProps?: IFocusZoneProps;
/**
* If true, renders the ContextualMenu in a hidden state.
* Use this flag, rather than rendering a ContextualMenu conditionally based on visibility,
* to improve rendering performance when it becomes visible.
* Note: When ContextualMenu is hidden its content will not be rendered. It will only render
* once the ContextualMenu is visible.
*/
hidden?: boolean;
/**
* If true, the menu will be updated even when `hidden=true`. Note that this will consume
* resources to update even when nothing is being shown to the user. This might be helpful if
* your updates are small and you want the menu to display quickly when `hidden` is set to false.
*/
shouldUpdateWhenHidden?: boolean;
/**
* If true, the contextual menu will not be updated until focus enters the menu via other means.
* This will only result in different behavior when `shouldFocusOnMount = false`.
*/
delayUpdateFocusOnHover?: boolean;
/**
* Called when the component is unmounting, and focus needs to be restored.
* Argument passed down contains two variables, the element that the underlying
* popup believes focus should go to and whether or not the popup currently
* contains focus. If this prop is provided, focus will not be restored automatically,
* you'll need to call originalElement.focus()
*/
onRestoreFocus?: (options: {
originalElement?: HTMLElement | Window;
containsFocus: boolean;
documentContainsFocus: boolean;
}) => void;
}
/**
* {@docCategory ContextualMenu}
*/
export interface IContextualMenuItemRenderProps extends IContextualMenuItem {
index: number;
focusableElementIndex: number;
totalItemCount: number;
hasCheckmarks: boolean;
hasIcons: boolean;
}
/**
* {@docCategory ContextualMenu}
*/
export interface IContextualMenuListProps {
items: IContextualMenuItem[];
totalItemCount: number;
hasCheckmarks: boolean;
hasIcons: boolean;
defaultMenuItemRenderer: (item: IContextualMenuItemRenderProps) => React.ReactNode;
ariaLabel?: string;
labelElementId?: string;
role?: string;
}
/**
* {@docCategory ContextualMenu}
*/
export interface IContextualMenuItem {
/**
* Optional callback to access the IContextualMenuRenderItem interface.
* This will get passed down to ContextualMenuItem.
*/
componentRef?: IRefObject<IContextualMenuRenderItem>;
/**
* Unique id to identify the item
*/
key: string;
/**
* Text of the menu item.
* If a standard hyphen (-) is passed in, then the item will be rendered as a divider.
* If a dash must appear as text, use an emdash (—), figuredash (‒), or minus symbol (−) instead.
*/
text?: string;
/**
* Seconday description for the menu item to display
*/
secondaryText?: string;
itemType?: ContextualMenuItemType;
/**
* Props for an icon to display next to the item.
*/
iconProps?: IIconProps;
/**
* Custom render function for the menu item icon
*/
onRenderIcon?: IRenderFunction<IContextualMenuItemProps>;
/**
* Props for the Icon used for the chevron.
*/
submenuIconProps?: IIconProps;
/**
* Whether the menu item is disabled
* @defaultvalue false
*/
disabled?: boolean;
/**
* If the menu item is a split button, this prop disables purely the primary action of the button.
* @defaultvalue false
*/
primaryDisabled?: boolean;
/**
* @deprecated Not used
*/
shortCut?: string;
/**
* Whether or not this menu item can be checked
* @defaultvalue false
*/
canCheck?: boolean;
/**
* Whether or not this menu item is currently checked.
* @defaultvalue false
*/
checked?: boolean;
/**
* Whether or not this menu item is a splitButton.
* @defaultvalue false
*/
split?: boolean;
/**
* Any custom data the developer wishes to associate with the menu item.
*/
data?: any;
/**
* Callback for when the menu item is invoked. If `ev.preventDefault()` is called in `onClick`,
* the click will not close the menu.
*
* Only for ContextualMenu items, returning true will dismiss the menu even if `ev.preventDefault()`
* was called (does not apply for button or CommandBar sub-menu items).
*/
onClick?: (ev?: React.MouseEvent<HTMLElement> | React.KeyboardEvent<HTMLElement>, item?: IContextualMenuItem) => boolean | void;
/**
* Navigate to this URL when the menu item is clicked.
*/
href?: string;
/**
* Target window when using `href`.
*/
target?: string;
/**
* Link relation setting when using `href`.
* If `target` is `_blank`, `rel` is defaulted to a value to prevent clickjacking.
*/
rel?: string;
/**
* Properties to apply to a submenu to this item.
*
* The ContextualMenu will provide default values for `target`, `onDismiss`, `isSubMenu`,
* `id`, `shouldFocusOnMount`, `directionalHint`, `className`, and `gapSpace`, all of which
* can be overridden.
*/
subMenuProps?: IContextualMenuProps;
/**
* Method to provide the classnames to style the individual items inside a menu.
* @deprecated Use `styles` prop of `IContextualMenuItemProps` to leverage mergeStyles API.
*/
getItemClassNames?: (theme: ITheme, disabled: boolean, expanded: boolean, checked: boolean, isAnchorLink: boolean, knownIcon: boolean, itemClassName?: string, dividerClassName?: string, iconClassName?: string, subMenuClassName?: string, primaryDisabled?: boolean) => IMenuItemClassNames;
/**
* Optional IContextualMenuItemProps overrides to customize behaviors such as item styling via `styles`.
*/
itemProps?: Partial<IContextualMenuItemProps>;
/**
* Method to provide the classnames to style the Vertical Divider of a split button inside a menu.
* Default value is the `getSplitButtonVerticalDividerClassNames` func defined in `ContextualMenu.classnames.ts`.
* @defaultvalue getSplitButtonVerticalDividerClassNames
*/
getSplitButtonVerticalDividerClassNames?: (theme: ITheme) => IVerticalDividerClassNames;
/**
* Properties to apply to render this item as a section.
* This prop is mutually exclusive with `subMenuProps`.
*/
sectionProps?: IContextualMenuSection;
/**
* Additional CSS class to apply to the menu item.
*/
className?: string;
/**
* Additional styles to apply to the menu item
* @deprecated in favor of the `styles` prop to leverage mergeStyles API.
*/
style?: React.CSSProperties;
/**
* Custom accessible label for the element.
* If no override is specified, the `aria-label` attribute will contain the item name.
*/
ariaLabel?: string;
/**
* Title (tooltip) text displayed when hovering over an item.
*/
title?: string;
/**
* Method to custom render this menu item.
* For keyboard accessibility, the top-level rendered item should be a focusable element
* (like an anchor or a button) or have the `data-is-focusable` property set to true.
*
* @param item - Item to render. Will typically be of type `IContextualMenuItem`.
* (When rendering a command bar item, will be `ICommandBarItemProps`.)
* @param dismissMenu - Function to dismiss the menu. Can be used to ensure that a custom menu
* item click dismisses the menu. (Will be undefined if rendering a command bar item.)
*/
onRender?: (item: any, dismissMenu: (ev?: any, dismissAll?: boolean) => void) => React.ReactNode;
/**
* Method to customize sub-components rendering of this menu item.
*
* @param props - Props used to pass into render functions
* @param defaultRenders - Default render functions that renders default sub-components
*/
onRenderContent?: (props: IContextualMenuItemProps, defaultRenders: IContextualMenuItemRenderFunctions) => React.ReactNode;
/**
* A function to be executed on mouse down. This is executed before an `onClick` event and can
* be used to interrupt native on click events as well. The click event should still handle
* the commands. This should only be used in special cases when react and non-react are mixed.
*/
onMouseDown?: (item: IContextualMenuItem, event: React.MouseEvent<HTMLElement>) => void;
/**
* Optional override for the menu button's role. Defaults to `menuitem` or `menuitemcheckbox`.
*/
role?: string;
/**
* When rendering a custom menu component that is passed in, the component might also be a list of
* elements. We want to keep track of the correct index our menu is using based off of
* the length of the custom list. It is up to the user to increment the count for their list.
*/
customOnRenderListLength?: number;
/**
* Keytip for this contextual menu item
*/
keytipProps?: IKeytipProps;
/**
* @deprecated Use subMenuProps.items instead.
*/
items?: IContextualMenuItem[];
/**
* Any additional properties to use when custom rendering menu items.
*/
[propertyName: string]: any;
/**
* Detailed description of the menu item for the benefit of screen readers.
*/
ariaDescription?: string;
/**
* This prop is no longer used. All contextual menu items are now focusable when disabled.
* @deprecated in 6.38.2 will be removed in 7.0.0
*/
inactive?: boolean;
/**
* Text of the menu item.
* @deprecated Use `text` instead.
*/
name?: string;
/**
* Flag which indicates that, when the item is clicked, the 'target' for the click event should be
* overridden to reflect the launch target from the root menu.
* This avoids a situation where the 'target' of the event may wind up detached from the DOM
* when the menu is dismissed in response to the click.
*/
preferMenuTargetAsEventTarget?: boolean;
}
/**
* {@docCategory ContextualMenu}
*/
export interface IContextualMenuSection extends React.ClassAttributes<any> {
/**
* The items to include inside the section.
*/
items: IContextualMenuItem[];
/**
* The optional section title.
*/
title?: string | IContextualMenuItem;
/**
* If set to true, the section will display a divider at the top of the section.
*/
topDivider?: boolean;
/**
* If set to true, the section will display a divider at the bottom of the section.
*/
bottomDivider?: boolean;
}
/**
* {@docCategory ContextualMenu}
*/
export interface IMenuItemStyles extends IButtonStyles {
/**
* Styles for a menu item that is an anchor link.
*/
item?: IStyle;
/**
* Styles for the content inside the button/link of the menuItem.
*/
linkContent?: IStyle;
/**
* Styles for a menu item that is an anchor link.
*/
anchorLink?: IStyle;
/**
* Default icon color style for known icons.
*/
iconColor?: IStyle;
/**
* Default style for checkmark icons.
*/
checkmarkIcon?: IStyle;
/**
* Styles for the submenu icon of a menu item.
*/
subMenuIcon?: IStyle;
/**
* Styles for a divider item of a ConextualMenu.
*/
divider?: IStyle;
}
/**
* {@docCategory ContextualMenu}
*/
export interface IContextualMenuStyleProps {
theme: ITheme;
className?: string;
}
/**
* {@docCategory ContextualMenu}
*/
export interface IContextualMenuStyles {
/**
* Style override for the contextual menu title.
*/
title: IStyle;
/**
* Style for the container which parents all menu items.
*/
container: IStyle;
/**
* Base styles for the root element of all ContextualMenus.
*/
root: IStyle;
/**
* Styles for the header item of a ContextualMenu
*/
header: IStyle;
/**
* Styles for the list that contains all menuItems.
*/
list: IStyle;
/**
* SubComponent styles.
*/
subComponentStyles: IContextualMenuSubComponentStyles;
}
/**
* {@docCategory ContextualMenu}
*/
export interface IContextualMenuSubComponentStyles {
/** Styles for the callout that hosts the ContextualMenu options. */
callout: IStyleFunctionOrObject<ICalloutContentStyleProps, any>;
/** Styles for each menu item. */
menuItem: IStyleFunctionOrObject<IContextualMenuItemStyleProps, any>;
}