skip to Main Content

How can any click events be disabled for props.children?

const Example = props => (
  <div>
    <div>This can be clicked</div>
    {props.children} /* These can't be clicked */
  </div>
)

I am rendering a PDF page using react-pdf and want the user to be able to drag a custom selection marquee (like in Photoshop…). As it is, the PDF page under or inside the marquee element still registers mouse events upon dragging, like text selection.

3

Answers


  1. Chosen as BEST ANSWER

    Use CSS Grid to put a div on top!

    A transparent div rendered on top of another div will intercept click events.

    CSS Grid can be used (abused?) to make a single grid area (using grid-template-areas) and assign multiple elements to it (using grid-area).

    JSX

    const ClickGuard = ({allow, block}) => (
      <div className='click-guard-area'>
        <div className='click-guard-allowed'>{props.allow}</div>
        <div className='click-guard-block' />
        <div className='click-guard-blocked'>{props.block}</div>
      </div>
    )
    

    CSS

    .click-guard-area {
      display: grid;
      grid-template-areas: 'click-guard';
      height: 100%;
      width: 100%;
    }
    
    .click-guard-allowed {
      grid-area: click-guard;
      height: 100%;
      width: 100%;
      z-index: 2;
    }
    
    .click-guard-block {
      grid-area: click-guard;
      height: 100%;
      width: 100%;
      z-index: 1;
    }
    
    .click-guard-blocked {
      grid-area: click-guard;
      height: 100%;
      width: 100%;
    }
    

    Note that ClickGuard expects two props: allow and block. These should be JSX. The React docs explain passing React elements here.

    <ClickGuard
       allow={<div>I can be clicked!</div>}
       block={<div>No clicks for me. 😞</div>}
    />
    

  2. You cannot change the props within an element thus its children props.
    An alternative solution may be possible with React.cloneElement,
    Here is a simple peace of code for you:

    const Example = props => (
      <div>
        <div>This can be clicked</div>
        {props.children.map((child)=>
            React.cloneElement(child, {
              disabled: true
            })
        )}
      </div>
    )
    Login or Signup to reply.
  3. There is an easy, but not robust way to do this:

    const Example = props => (
      <div style={{pointerEvents:'none'}}>
        <div style={{pointerEvents:'auto'}}>This can be clicked</div>
        {props.children}
      </div>
    )
    

    It is not robust, because if any of the children have pointer-events set to auto, they will be clickable too. See if it fits your needs. Also, it will kill hover and other mouse events.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search