React-toolbox: Possible to use Menu without IconMenu?

Created on 24 Jul 2016  Â·  3Comments  Â·  Source: react-toolbox/react-toolbox

From the docs it seems to me that I should be able to use the Menu component separately from the IconMenu wrapper. What I want is to use a Button styled with my custom Button theme to control a menu rather than just showing a single icon.

But I don't see a way to hook into the show/hide functionality, and I can't even get the Menu to respond to props I pass in like active={false} -- it just draws into the page regardless. I tried injecting my Button component as the icon prop, but that ends up creating a button DOM component inside another button, and leaves a blank clickable area where the icon would be.

I've been tearing my hair out about this for days. Is it possible? If not, could you clarify in the docs that the Menu is separately stylable but isn't a standalone component?

Most helpful comment

Well, I'm not sure if you are falling into some kind of issue. The only thing to need to make sure is that the wrapper element around the component is positioned relatively. From this point you can do whatever you want. Try this in the playground:

class ButtonMenu extends React.Component {
  state = { active: false };
  handleButtonClick = () => this.setState({ active: !this.state.active });
  handleMenuHide = () => this.setState({ active: false });
  render () {
    return (
      <div style={{ display: 'inline-block', position: 'relative' }}>
        <Button primary raised onClick={this.handleButtonClick} label="Hello" />
        <Menu position="topLeft" active={this.state.active} onHide={this.handleMenuHide}>
          {this.props.children}
        </Menu>
      </div>
    );
  }
}

return (
  <ButtonMenu>
    <MenuItem value='download' icon='get_app' caption='Download' />
    <MenuItem value='help' icon='favorite' caption='Favorite' />
    <MenuItem value='settings' icon='open_in_browser' caption='Open in app' />
    <MenuItem value='signout' icon='delete' caption='Delete' disabled />
  </ButtonMenu>
);

All 3 comments

Well, I'm not sure if you are falling into some kind of issue. The only thing to need to make sure is that the wrapper element around the component is positioned relatively. From this point you can do whatever you want. Try this in the playground:

class ButtonMenu extends React.Component {
  state = { active: false };
  handleButtonClick = () => this.setState({ active: !this.state.active });
  handleMenuHide = () => this.setState({ active: false });
  render () {
    return (
      <div style={{ display: 'inline-block', position: 'relative' }}>
        <Button primary raised onClick={this.handleButtonClick} label="Hello" />
        <Menu position="topLeft" active={this.state.active} onHide={this.handleMenuHide}>
          {this.props.children}
        </Menu>
      </div>
    );
  }
}

return (
  <ButtonMenu>
    <MenuItem value='download' icon='get_app' caption='Download' />
    <MenuItem value='help' icon='favorite' caption='Favorite' />
    <MenuItem value='settings' icon='open_in_browser' caption='Open in app' />
    <MenuItem value='signout' icon='delete' caption='Delete' disabled />
  </ButtonMenu>
);

In fact you can even create a <div /> as a normal square element and then catch the exact position of where it was clicked. Then create another element with fixed position at that exact x,y and make a menu active positioned under that last div. This would allow you to render a menu in the exact place where the user clicked. You can achieve it using the Portal component which is internal and placed under the hoc folder in react-toolbox!

That worked perfectly, thank you! I still don't know why I couldn't get Menu to see its active prop, but pasting your code worked... ¯_(ツ)_/¯

For the reference of anyone else seeing this thread, this is how I set up the Portal element. I didn't need the menu to show up at mouseX, mouseY, so it just appears at the bottom of the button, similar to a system menu.

<div className="menuContainer" style={{ display: 'inline-block' }}>
  <div ref="menuOverlayContainer"
    style={{ display: 'inline-block', position: 'relative', top: '15px'}}>
  </div>
  <IconButton primary raised label="Bookmarks" icon={<MdBookmark />}
    onClick={this.handleButtonClick}
  />
  <Portal container={this.refs.menuOverlayContainer} className="portalDiv">
    <Menu position="topLeft" active={this.state.active} onHide={this.handleMenuHide}>
      {this.props.children}
    </Menu>
  </Portal>
</div>

Thank you so much for your help!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

dbrrt picture dbrrt  Â·  3Comments

kodermax picture kodermax  Â·  4Comments

fraenku picture fraenku  Â·  3Comments

thomasthiebaud picture thomasthiebaud  Â·  4Comments

delacruz-dev picture delacruz-dev  Â·  4Comments