Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

boilerplate for common Material-UI Menu, Popover and Popper use cases

License

NotificationsYou must be signed in to change notification settings

jcoreio/material-ui-popup-state

Repository files navigation

CircleCICoverage Statussemantic-releasenpm version

Takes care of the boilerplate for common Menu, Popover and Popper use cases.

Provides aCustom React Hook that keeps track of the local state for a single popup, and functions to connect trigger, toggle, andpopover/menu/popper components to the state.

Also provides aRender Props Component thatkeeps track of the local state for a single popup, and passes the state andmutation functions to a child render function.

Requirements

Requires MUI >= 5.0.0 and React >= 16.8.0.For MUI v4 you'll needmaterial-ui-popup-state@^1.9.3.

Table of Contents

Installation

npm install --save material-ui-popup-state

Examples with React Hooks

Menu

import*asReactfrom'react'importButtonfrom'@mui/material/Button'importMenufrom'@mui/material/Menu'importMenuItemfrom'@mui/material/MenuItem'import{usePopupState,bindTrigger,bindMenu,}from'material-ui-popup-state/hooks'constMenuPopupState=()=>{constpopupState=usePopupState({variant:'popover',popupId:'demoMenu'})return(<div><Buttonvariant="contained"{...bindTrigger(popupState)}>        Open Menu</Button><Menu{...bindMenu(popupState)}><MenuItemonClick={popupState.close}>Cake</MenuItem><MenuItemonClick={popupState.close}>Death</MenuItem></Menu></div>)}exportdefaultMenuPopupState

Popover

importReactfrom'react'importPropTypesfrom'prop-types'import{withStyles}from'@mui/material/styles'importTypographyfrom'@mui/material/Typography'importButtonfrom'@mui/material/Button'importPopoverfrom'@mui/material/Popover'import{usePopupState,bindTrigger,bindPopover,}from'material-ui-popup-state/hooks'conststyles=(theme)=>({typography:{margin:theme.spacing.unit*2,},})constPopoverPopupState=({ classes})=>{constpopupState=usePopupState({variant:'popover',popupId:'demoPopover',})return(<div><Buttonvariant="contained"{...bindTrigger(popupState)}>        Open Popover</Button><Popover{...bindPopover(popupState)}anchorOrigin={{vertical:'bottom',horizontal:'center',}}transformOrigin={{vertical:'top',horizontal:'center',}}><TypographyclassName={classes.typography}>          The content of the Popover.</Typography></Popover></div>)}PopoverPopupState.propTypes={classes:PropTypes.object.isRequired,}exportdefaultwithStyles(styles)(PopoverPopupState)

Popper

importReactfrom'react'importPropTypesfrom'prop-types'import{withStyles}from'@mui/material/styles'importTypographyfrom'@mui/material/Typography'importButtonfrom'@mui/material/Button'importPopperfrom'@mui/material/Popper'import{usePopupState,bindToggle,bindPopper,}from'material-ui-popup-state/hooks'importFadefrom'@mui/material/Fade'importPaperfrom'@mui/material/Paper'conststyles=(theme)=>({typography:{padding:theme.spacing.unit*2,},})constPopperPopupState=({ classes})=>{constpopupState=usePopupState({variant:'popper',popupId:'demoPopper'})return(<div><Buttonvariant="contained"{...bindToggle(popupState)}>        Toggle Popper</Button><Popper{...bindPopper(popupState)}transition>{({ TransitionProps})=>(<Fade{...TransitionProps}timeout={350}><Paper><TypographyclassName={classes.typography}>                The content of the Popper.</Typography></Paper></Fade>)}</Popper></div>)}PopperPopupState.propTypes={classes:PropTypes.object.isRequired,}exportdefaultwithStyles(styles)(PopperPopupState)

React Hooks API

Bind Functions

material-ui-popup-state/hooks exports several helper functions you can use toconnect components easily:

  • anchorRef: creates aref function to pass to theanchorEl(by default, thecurrentTarget of the mouse event that triggered the popupis used; only useanchorRef if you want a different element to be the anchor).
  • bindMenu: creates props to control aMenu component.
  • bindPopover: creates props to control aPopover component.
  • bindPopper: creates props to control aPopper component.
  • bindDialog: creates props to control aDialog component.
  • bindTrigger: creates props for a component that opens the popup when clicked.
  • bindContextMenu: creates props for a component that opens the popup on when right clicked (contextmenu event).NOTE:bindPopover/bindMenu will position the Popover/Menu to thecontextmenu event location. To positionusing thecontextmenu target element instead, passanchorReference="anchorEl" after{...bindPopover(popupState)}/{...bindMenu(popupState)}.
  • bindToggle: creates props for a component that toggles the popup when clicked.
  • bindHover: creates props for a component that opens the popup while hovered.NOTE: Seethis guidance if you are usingbindHover withPopover orMenu.
  • bindFocus: creates props for a component that opens the popup while focus.
  • bindDoubleClick: creates props for a component that opens the popup while double click.

To use one of these functions, you should call it with the objectreturned byusePopupState and spread the return value into the desiredelement:

import*asReactfrom'react'importButtonfrom'@mui/material/Button'importMenufrom'@mui/material/Menu'importMenuItemfrom'@mui/material/MenuItem'import{usePopupState,bindTrigger,bindMenu,}from'material-ui-popup-state/hooks'constMenuPopupState=()=>{constpopupState=usePopupState({variant:'popover',popupId:'demoMenu'})return(<div><Buttonvariant="contained"{...bindTrigger(popupState)}>        Open Menu</Button><Menu{...bindMenu(popupState)}><MenuItemonClick={popupState.close}>Cake</MenuItem><MenuItemonClick={popupState.close}>Death</MenuItem></Menu></div>)}exportdefaultMenuPopupState

usePopupState

This is aCustom Hook that usesuseState internally, therefore theRules of Hooks apply tousePopupState.

usePopupState Props

variant ('popover','popper', or'dialog',required)

Use'popover' if your popup is aPopover orMenu; use'popper' if yourpopup is aPopper.

Right now this only affects whetherbindTrigger/bindToggle/bindHover returnanaria-controls prop or anaria-describedby prop.

popupId (string,optional)

Theid for the popup component. It will be passed to the child props so thatthe trigger component may declare the same id in an ARIA prop.

Defaults toReact.useId() ifReact.useId exists; in older versions of Reactyou will have to manually provide apopupId.

disableAutoFocus (boolean,optional)

Iftrue, will not steal focus when the popup is opened. (AndbindPopover/bindMenu will injectdisableAutoFocus,disableEnforceFocus, anddisableRestoreFocus).

Defaults totrue when the popup is opened by thebindHover orbindFocus element.

usePopupState return value

An object with the following properties:

  • open([eventOrAnchorEl]): opens the popup. You must pass in an anchor element or an event with acurrentTarget, otherwise the popup will not position properly and you will get a warning; MUI needs an anchor element to position the popup.
  • close(): closes the popup
  • toggle([eventOrAnchorEl]): opens the popup if it is closed, or closes the popup if it is open. If the popup is currently closed, you must pass an anchor element or an event with acurrentTarget, otherwise the popup will not position properly and you will get a warning; MUI needs an anchor element to position the popup.
  • setOpen(open, [eventOrAnchorEl]): sets whether the popup is open. Ifopen is truthy, you must pass in an anchor element or an event with acurrentTarget, otherwise the popup will not position properly and you will get a warning; MUI needs an anchor element to position the popup.
  • isOpen:true/false if the popup is open/closed
  • anchorEl: the current anchor element
  • anchorPosition: the current anchor position
  • setAnchorEl: sets the anchor element (thecurrentTarget of the triggeringmouse event is used by default unless you have calledsetAnchorEl)
  • popupId: thepopupId prop you passed toPopupState
  • variant: thevariant prop you passed toPopupState

Examples with Render Props

Menu

import*asReactfrom'react'importButtonfrom'@mui/material/Button'importMenufrom'@mui/material/Menu'importMenuItemfrom'@mui/material/MenuItem'importPopupState,{bindTrigger,bindMenu}from'material-ui-popup-state'constMenuPopupState=()=>(<PopupStatevariant="popover"popupId="demoMenu">{(popupState)=>(<React.Fragment><Buttonvariant="contained"{...bindTrigger(popupState)}>          Open Menu</Button><Menu{...bindMenu(popupState)}><MenuItemonClick={popupState.close}>Cake</MenuItem><MenuItemonClick={popupState.close}>Death</MenuItem></Menu></React.Fragment>)}</PopupState>)exportdefaultMenuPopupState

Popover

importReactfrom'react'importPropTypesfrom'prop-types'import{withStyles}from'@mui/material/styles'importTypographyfrom'@mui/material/Typography'importButtonfrom'@mui/material/Button'importPopoverfrom'@mui/material/Popover'importPopupState,{bindTrigger,bindPopover}from'material-ui-popup-state'conststyles=(theme)=>({typography:{margin:theme.spacing.unit*2,},})constPopoverPopupState=({ classes})=>(<PopupStatevariant="popover"popupId="demoPopover">{(popupState)=>(<div><Buttonvariant="contained"{...bindTrigger(popupState)}>          Open Popover</Button><Popover{...bindPopover(popupState)}anchorOrigin={{vertical:'bottom',horizontal:'center',}}transformOrigin={{vertical:'top',horizontal:'center',}}><TypographyclassName={classes.typography}>            The content of the Popover.</Typography></Popover></div>)}</PopupState>)PopoverPopupState.propTypes={classes:PropTypes.object.isRequired,}exportdefaultwithStyles(styles)(PopoverPopupState)

Mouse Over Interaction

importReactfrom'react'importPropTypesfrom'prop-types'import{withStyles}from'@mui/material/styles'importTypographyfrom'@mui/material/Typography'importHoverPopoverfrom'material-ui-popup-state/HoverPopover'importPopupState,{bindHover,bindPopover}from'material-ui-popup-state'conststyles=(theme)=>({popover:{pointerEvents:'none',},paper:{padding:theme.spacing.unit,},})constHoverPopoverPopupState=({ classes})=>(<PopupStatevariant="popover"popupId="demoPopover">{(popupState)=>(<div><Typography{...bindHover(popupState)}>          Hover with a Popover.</Typography><HoverPopover{...bindPopover(popupState)}className={classes.popover}classes={{paper:classes.paper,}}anchorOrigin={{vertical:'bottom',horizontal:'center',}}transformOrigin={{vertical:'top',horizontal:'center',}}><Typography>The content of the Popover.</Typography></HoverPopover></div>)}</PopupState>)HoverPopoverPopupState.propTypes={classes:PropTypes.object.isRequired,}exportdefaultwithStyles(styles)(HoverPopoverPopupState)

Popper

importReactfrom'react'importPropTypesfrom'prop-types'import{withStyles}from'@mui/material/styles'importTypographyfrom'@mui/material/Typography'importButtonfrom'@mui/material/Button'importPopperfrom'@mui/material/Popper'importPopupState,{bindToggle,bindPopper}from'material-ui-popup-state'importFadefrom'@mui/material/Fade'importPaperfrom'@mui/material/Paper'conststyles=(theme)=>({typography:{padding:theme.spacing.unit*2,},})constPopperPopupState=({ classes})=>(<PopupStatevariant="popper"popupId="demoPopper">{(popupState)=>(<div><Buttonvariant="contained"{...bindToggle(popupState)}>          Toggle Popper</Button><Popper{...bindPopper(popupState)}transition>{({ TransitionProps})=>(<Fade{...TransitionProps}timeout={350}><Paper><TypographyclassName={classes.typography}>                  The content of the Popper.</Typography></Paper></Fade>)}</Popper></div>)}</PopupState>)PopperPopupState.propTypes={classes:PropTypes.object.isRequired,}exportdefaultwithStyles(styles)(PopperPopupState)

Render Props API

Bind Functions

material-ui-popup-state exports several helper functions you can use toconnect components easily:

  • anchorRef: creates aref function to pass to theanchorEl(by default, thecurrentTarget of the mouse event that triggered the popupis used; only useanchorRef if you want a different element to be the anchor).
  • bindMenu: creates props to control aMenu component.
  • bindPopover: creates props to control aPopover component.
  • bindPopper: creates props to control aPopper component.
  • bindDialog: creates props to control aDialog component.
  • bindTrigger: creates props for a component that opens the popup when clicked.
  • bindContextMenu: creates props for a component that opens the popup on when right clicked (contextmenu event).NOTE:bindPopover/bindMenu will position the Popover/Menu to thecontextmenu event location. To positionusing thecontextmenu target element instead, passanchorReference="anchorEl" after{...bindPopover(popupState)}/{...bindMenu(popupState)}.
  • bindToggle: creates props for a component that toggles the popup when clicked.
  • bindHover: creates props for a component that opens the popup while hovered.NOTE: Seethis guidance if you are usingbindHover withPopover orMenu.
  • bindFocus: creates props for a component that opens the popup while hovered.

To use one of these functions, you should call it with the propsPopupStatepassed to your child function, and spread the return value into the desiredelement:

import*asReactfrom'react'importButtonfrom'@mui/material/Button'importMenufrom'@mui/material/Menu'importMenuItemfrom'@mui/material/MenuItem'importPopupState,{bindTrigger,bindMenu}from'material-ui-popup-state'constMenuPopupState=()=>(<PopupStatevariant="popover"popupId="demoMenu">{(popupState)=>(<React.Fragment><Buttonvariant="contained"{...bindTrigger(popupState)}>          Open Menu</Button><Menu{...bindMenu(popupState)}><MenuItemonClick={popupState.close}>Cake</MenuItem><MenuItemonClick={popupState.close}>Death</MenuItem></Menu></React.Fragment>)}</PopupState>)exportdefaultMenuPopupState

PopupState Props

variant ('popover','popper', or'dialog',required)

Use'popover' if your popup is aPopover orMenu; use'popper' if yourpopup is aPopper.

Right now this only affects whetherbindTrigger/bindToggle/bindHover returnanaria-controls prop or anaria-describedby prop.

popupId (string,optional)

Theid for the popup component. It will be passed to the child props so thatthe trigger component may declare the same id in an ARIA prop.

Defaults toReact.useId() ifReact.useId exists; in older versions of Reactyou will have to manually provide apopupId.

disableAutoFocus (boolean,optional)

Iftrue, will not steal focus when the popup is opened. (AndbindPopover/bindMenu will injectdisableAutoFocus,disableEnforceFocus, anddisableRestoreFocus).

Defaults totrue when the popup is opened by thebindHover orbindFocus element.

children ((popupState: InjectedProps) => ?React.Node,required)

The render function. It will be called with an object containing the followingprops (exported as theInjectedProps type):

  • open([eventOrAnchorEl]): opens the popup
  • close(): closes the popup
  • toggle([eventOrAnchorEl]): opens the popup if it is closed, or closes the popup if it is open.
  • setOpen(open, [eventOrAnchorEl]): sets whether the popup is open.
  • isOpen:true/false if the popup is open/closed
  • anchorEl: the current anchor element
  • anchorPosition: the current anchor position
  • setAnchorEl: sets the anchor element (thecurrentTarget of the triggeringmouse event is used by default unless you have calledsetAnchorEl)
  • popupId: thepopupId prop you passed toPopupState
  • variant: thevariant prop you passed toPopupState

UsingPopover andMenu withbindHover

MUI'sModal (used byPopover andMenu) blocks pointer events to all other components, interfering withbindHover(the popover or menu will open when the mouse enters thebindHover element, but won't close when the mouse leaves). You canuse the following components to work around this:

importHoverMenufrom'material-ui-popup-state/HoverMenu'importHoverPopoverfrom'material-ui-popup-state/HoverPopover'

These are just wrapper components that pass inline styles to preventModal from blocking pointer events.

Chaining event handlers

What if you need to perform additional actions inonClick, but it's being injected by{...bindTrigger(popupState)} etc?

There are two options:

Chaining event handlers manually

This is the most straightforward, explicit option.

constbutton=(<Button{...bindTrigger(popupState)}onClick={(e:React.MouseEvent)=>{bindTrigger(popupState).onClick(e)performCustomAction(e)}}>    Open Menu</Button>)

Usingmaterial-ui-popup-state/chainEventHandlers

If you don't like the above option, you can use the providedmaterial-ui-popup-state/chainEventHandlers helper:

import{chainEventHandlers}from'material-ui-popup-state/chainEventHandlers'constbutton=(<Button{...chainEventHandlers(bindTrigger(popupState),{onClick:(e:React.MouseEvent)=>{bindTrigger(popupState).onClick(e)performCustomAction(e)},})}>    Open Menu</Button>)

chainEventHandlers accepts a variable number of props arguments and combines any function props of the same nameinto a function that invokes the chained functions in sequence. For all other properties the behavior is likeObject.assign.

Warning

chainEventHandlers doesn't memoize the combined event handler functions, so they will cause components torerender. If you need memoized functions, you will need to perform the memoization with your own code, for exampleusingReact.useCallback andchaining event handlers manually.


[8]ページ先頭

©2009-2025 Movatter.jp