The Wayback Machine - https://web.archive.org/web/20210709120341/https://github.com/mui-org/material-ui/issues/20856
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Checkbox] You can click through an overlay to check a checkbox #20856

Open
steverecio opened this issue Apr 30, 2020 · 13 comments
Open

[Checkbox] You can click through an overlay to check a checkbox #20856

steverecio opened this issue Apr 30, 2020 · 13 comments

Comments

@steverecio
Copy link

@steverecio steverecio commented Apr 30, 2020

Paper component (elevation=1) accepts clicks from UI elements underneath. I have the following code:

<Popper>
  <Paper>
     <ClickAwayListener>
         // some stuff here
     </ClickAwayListener>
  </Paper>
</Popper>

Any elements (buttons, checkboxes, etc) that sit below the popper / paper component above, accept click events. The component should block any click events from flowing to components underneath it.

Tech Version
Material-UI v4.9.9
React v16.8.0
Browser Chrome
TypeScript
etc.
@eps1lon
Copy link
Member

@eps1lon eps1lon commented Apr 30, 2020

Could you share a codesandbox and describe the expected and current behavior in more detail? It's not clear why a clickawaylistener should prevent click events.

@steverecio
Copy link
Author

@steverecio steverecio commented Apr 30, 2020

@eps1lon https://codesandbox.io/s/material-demo-mu35u?file=/demo.js

Notice how you can still toggle the checkbox underneath the paper when the popper is open.

Note: This seems to only be the case with MUI checkboxes. I tested it with a simple html button and I'm unable to trigger the click event in that case (when its underneath the paper).

@joshwooding joshwooding changed the title Paper component accepts clicks from elements below You can click through a Popper to check a checkbox Apr 30, 2020
@oliviertassinari
Copy link
Member

@oliviertassinari oliviertassinari commented May 3, 2020

I have no idea how to explain this behavior. Adding a z-index: 1 on the Popper solves the issue, however, it's not something we can apply. I would propose we ignore the issue.

@mrcoles
Copy link

@mrcoles mrcoles commented May 5, 2020

the issue @steverecio is seeing appears to be more with the '@material-ui/core/Checkbox' element than the 'Popper'. Upon inspecting the rendered “Checkbox” it has an invisible (opacity: 0;) checkbox that ends up rendering above the popper, because the same checkbox has z-index: 1;.

It’s not clear to me that the z-index setting on the hidden input is necessary or why there isn’t a different solution without z-index—I see Checkbox.js gets it from SwitchBase.js. However, I see it was added in this PR #17389 to fix this bug: #17366

@oliviertassinari
Copy link
Member

@oliviertassinari oliviertassinari commented May 7, 2020

Looking back at history, we have #18905 that is very related. I would propose this resolution: in the documentation, we encourage setting a z-index to the Popper component.

@oliviertassinari
Copy link
Member

@oliviertassinari oliviertassinari commented May 9, 2020

@steverecio You can manually set a z-index on the Popper element to solve the issue.

@steverecio
Copy link
Author

@steverecio steverecio commented Mar 22, 2021

Here is a code sandbox: https://codesandbox.io/s/material-demo-forked-mldm9?file=/demo.js:0-674

Note that the button is unclickable but the Checkbox accepts clicks / hovers when it should not be receiving user input.

I would suggest re-opeing this issue as z-index does not fix this example.

@oliviertassinari
Copy link
Member

@oliviertassinari oliviertassinari commented Mar 28, 2021

@steverecio Thanks for the reproduction. I have further simplified it down to https://codesandbox.io/s/material-demo-forked-hq39t?file=/demo.js.

import React from "react";

export default function SimpleModal() {
  return (
    <div>
      <div style={{ display: "flex" }}>
        <input defaultChecked type="checkbox" style={{ zIndex: 1 }} />
      </div>
      <input defaultChecked type="checkbox" style={{ position: 'absolute', zIndex: 1 }} />
      <br />
      text bellow the overlay
      <div
        style={{
          position: "fixed",
          backgroundColor: "rgba(0, 0, 0, 0.2)",
          top: 0,
          left: 0,
          right: 0,
          bottom: 0
        }}
      />
    </div>
  );
}

Screenshot 2021-03-28 at 20 00 09

I can reproduce it in Firefox, Safari, Chrome, Edge, so it seems to be per the spec.
The zIndex is present to fix #17366.

@oliviertassinari
Copy link
Member

@oliviertassinari oliviertassinari commented Mar 28, 2021

One solution is:

diff --git a/packages/material-ui/src/internal/SwitchBase.js b/packages/material-ui/src/internal/SwitchBase.js
index 16d9fd3e21..d731d5f85f 100644
--- a/packages/material-ui/src/internal/SwitchBase.js
+++ b/packages/material-ui/src/internal/SwitchBase.js
@@ -36,7 +36,6 @@ const SwitchBaseInput = experimentalStyled('input')({
   left: 0,
   margin: 0,
   padding: 0,
-  zIndex: 1,
 });

 /**
@@ -141,6 +140,7 @@ const SwitchBase = React.forwardRef(function SwitchBase(props, ref) {
       ref={ref}
       {...other}
     >
+      {checked ? checkedIcon : icon}
       <SwitchBaseInput
         autoFocus={autoFocus}
         checked={checkedProp}
@@ -159,7 +159,6 @@ const SwitchBase = React.forwardRef(function SwitchBase(props, ref) {
         value={value}
         {...inputProps}
       />
-      {checked ? checkedIcon : icon}
     </SwitchBaseRoot>
   );
 });

but it breaks https://next.material-ui.com/components/radio-buttons/#customized-radios and https://next.material-ui.com/components/checkboxes/#customized-checkbox. We would need to fix them with:

diff --git a/docs/src/pages/components/checkboxes/CustomizedCheckbox.tsx b/docs/src/pages/components/checkboxes/CustomizedCheckbox.tsx
index 6be50606d1..19dc8ba76c 100644
--- a/docs/src/pages/components/checkboxes/CustomizedCheckbox.tsx
+++ b/docs/src/pages/components/checkboxes/CustomizedCheckbox.tsx
@@ -13,10 +13,10 @@ const Icon = styled('span')({
     outline: '2px auto rgba(19,124,189,.6)',
     outlineOffset: 2,
   },
-  'input:hover ~ &': {
+  '.MuiCheckbox-root:hover &': {
     backgroundColor: '#ebf1f5',
   },
-  'input:disabled ~ &': {
+  '.MuiCheckbox-root.Mui-disabled &': {
     boxShadow: 'none',
     background: 'rgba(206,217,224,.5)',
   },
@@ -35,7 +35,7 @@ const CheckedIcon = styled(Icon)({
       "1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='%23fff'/%3E%3C/svg%3E\")",
     content: '""',
   },
-  'input:hover ~ &': {
+  '.MuiCheckbox-root:hover &': {
     backgroundColor: '#106ba3',
   },
 });
diff --git a/docs/src/pages/components/radio-buttons/CustomizedRadios.tsx b/docs/src/pages/components/radio-buttons/CustomizedRadios.tsx
index bc780d19a5..87416589f9 100644
--- a/docs/src/pages/components/radio-buttons/CustomizedRadios.tsx
+++ b/docs/src/pages/components/radio-buttons/CustomizedRadios.tsx
@@ -17,10 +17,10 @@ const Icon = styled('span')({
     outline: '2px auto rgba(19,124,189,.6)',
     outlineOffset: 2,
   },
-  'input:hover ~ &': {
+  '.MuiRadio-root:hover &': {
     backgroundColor: '#ebf1f5',
   },
-  'input:disabled ~ &': {
+  '.MuiRadio-root.Mui-disabled &': {
     boxShadow: 'none',
     background: 'rgba(206,217,224,.5)',
   },
@@ -36,7 +36,7 @@ const CheckedIcon = styled(Icon)({
     backgroundImage: 'radial-gradient(#fff,#fff 28%,transparent 32%)',
     content: '""',
   },
-  'input:hover ~ &': {
+  '.MuiRadio-root:hover &': {
     backgroundColor: '#106ba3',
   },
 });

A breaking change.


The only other alternative I can think of is to make the lack of z-index easier to spot (not requiring an interaction) with:

diff --git a/packages/material-ui/src/internal/SwitchBase.js b/packages/material-ui/src/internal/SwitchBase.js
index 16d9fd3e21..4d1a93d3bf 100644
--- a/packages/material-ui/src/internal/SwitchBase.js
+++ b/packages/material-ui/src/internal/SwitchBase.js
@@ -23,6 +23,7 @@ const useUtilityClasses = (styleProps) => {
 const SwitchBaseRoot = experimentalStyled(IconButton)({
   /* Styles applied to the root element. */
   padding: 9,
+  zIndex: 1,
 });

 const SwitchBaseInput = experimentalStyled('input')({
@oliviertassinari oliviertassinari changed the title You can click through a Popper to check a checkbox [Checkbox] You can click through an overlay to check a checkbox Mar 28, 2021
@oliviertassinari
Copy link
Member

@oliviertassinari oliviertassinari commented Mar 30, 2021

It seems we don't get any preference on the direction we should take. In this case, I would recommend the first one. Solve once for all.

@steverecio
Copy link
Author

@steverecio steverecio commented Mar 30, 2021

@oliviertassinari Thanks for looking into this. I would vote for whichever solution is default for native html input checkboxes. As long as the solution is easy to find / documented, then the default being most similar to html has my vote.

@mare1601
Copy link

@mare1601 mare1601 commented Jun 27, 2021

Hi! Thread seems quiet and I'd love to snag this issue - will tackle if that's cool 😊

@mare1601
Copy link

@mare1601 mare1601 commented Jul 3, 2021

My solution wasn't up to snuff - someone else is welcome to take the ticket 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

5 participants