Skip to content

Instantly share code, notes, and snippets.

@koistya
Last active July 15, 2022 04:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save koistya/eb8f22f03d6609e01a3be2507950052d to your computer and use it in GitHub Desktop.
Save koistya/eb8f22f03d6609e01a3be2507950052d to your computer and use it in GitHub Desktop.
Show Material UI menu on text selection
import React from 'react';
import Menu from '@material-ui/core/Menu';
import RootRef from '@material-ui/core/RootRef';
import Typography from '@material-ui/core/Typography';

class MyComponent extends React.Component {
  componentDidMount() {
    document.addEventListener('selectionchange', this.handleSelect);
  }

  componentWillUnmount() {
    document.removeEventListener('selectionchange', this.handleSelect);
  }

  state = { anchorEl: null };
  text = React.createRef();
  
  handleSelect = () => {
    const sel = window.getSelection();
    const { current: el } = this.text;

    if (!sel.toString()) return;

    // Check if the selection is made on the target (text) node
    if (sel.anchorNode.parentNode === el || sel.focusNode.parentNode === el) {
      this.setState({ anchorEl: el });
    }
  };

  closeMenu = () => {
    this.setState({ anchorEl: null }):
  };
  
  render() {
    return (
      <div>
        <Typography variant="title">Example</Typography>
        <RootRef rootRef={this.text}>
          <Typography variant="body1">
            Lorem Ipsum is simply dummy text of the printing and typesetting industry.
          </Typography>
        </RootRef>
        <Menu
          anchorEl={this.state.anchorEl}
          open={Boolean(this.state.anchorEl)}
          onClose={this.closeMenu}
        >
          OK OK OK
        </Menu>
      </div>
    );
  }
}

References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment