0

I'm trying to create a custom consent checkbox using Material-UI v3.9.3's Checkbox.

Reason: Custom coz, the requirement is to make it with a specific background(white for the Checkbox area) and foreground(orange for the check icon) color.

Implementation so far: I've implemented it using custom CSS.

index.js:

import React, { useState } from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import Checkbox from "@material-ui/core/Checkbox";
import { withStyles, makeStyles } from "@material-ui/styles";

import "./style.css";

const useStyles =  makeStyles({
  checkbox: {
    padding: 0,
    width: 24,
    height: 24
  },
  icon: {
    borderRadius: 3,
    width: 24,
    height: 24,
    boxShadow: "inset 0 0 0 1px rgba(16,22,26,.2), inset 0 -1px 0 rgba(16,22,26,.1)",
    backgroundColor: "#ffffff",
    "input:hover ~ &": {
      backgroundColor: "#f5f8fa"
    },
    "input:disabled ~ &": {
      boxShadow: "none",
      background: "rgba(206,217,224,.5)"
    }
  },
  root: {
    background: "linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)",
    border: 0,
    borderRadius: 3,
    boxShadow: "0 3px 5px 2px rgba(255, 105, 135, .3)",
    color: "white",
    height: 48,
    padding: "0 30px"
  },
  checkedIcon: {
    borderRadius: 2,
    "&:before": {
      display: "block",
      width: 24,
      height: 24,
      backgroundImage:
        "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Crect width='23' height='23' x='.5' y='.5' fill='%23FFF' fill-rule='nonzero' stroke='%23999' rx='4'/%3E%3Ctext fill='%23F2410A' font-size='20' font-weight='bold'%3E%3Ctspan x='1' y='18'%3E✓%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A\")",
      content: '""'
    },
    "input:hover ~ &": {
      backgroundColor: "#106ba3"
    }
  }
});

const App = props => {
  const classes = useStyles();
  const [consentGiven, setConsentGiven] = useState(false);
  const handleChange = event => {
    !consentGiven && setConsentGiven(true);
  };

  return (
    <div>
      <Checkbox
        className={classes.checkbox}
        checked={consentGiven}
        color="primary"
        onChange={handleChange}
        icon={<span className={classes.icon} />}
        checkedIcon={<span className={classes.checkedIcon} />}
        inputProps={{
          "aria-label": "primary checkbox"
        }}
      />
    </div>
  );
};

render(<App />, document.getElementById("root"));

index.html:

<div id="root"></div>

Here's a Sample StackBlitz with the minimal code required to reproduce the issue.

The issue: The solution seems to work perfectly in Chrome. But in IE, once the user checks the checkbox, it disappers.

Expected Behavior: The Checkbox, once checked, should stay visible with the checked state on IE.

SiddAjmera
  • 38,129
  • 5
  • 72
  • 110
  • 1
    Okay, so whosoever marked to close the question, did you get a chance to have a look at the Sample StackBlitz that I've attached? It basically has the minimal implementation in place. :) I've also included the issue that it's disappearing in IE on click. Can you please also comment and maybe let me know what other information would be required? – SiddAjmera Nov 25 '19 at 03:18
  • Not yet implemented, but EDGE itself is the recommended by Microsoft. Since the support has ended for IE most of the newer things don’t work on it – krishna_tandon Nov 25 '19 at 05:06
  • 1
    I try to open your Stackblitz sample in IE browser but it did not load. IT showing blank page. Then I tested it with Edge browser and I seen the similar issue. I check the code and found that 'MuiPrivateSwitchBase-input-10' CSS class was applied on it. It has opacity set as 0. If you uncheck this property then it display the checkbox with checked sign in black color. So you can try to check those CSS files may help to narrow down the issue. https://i.postimg.cc/zv47HJ1P/115.gif I suggest you to post a code sample only using Matirial UI. So we can also try to test it with IE. – Deepak-MSFT Nov 25 '19 at 07:55
  • I actually did that already. But that doesn't solve the problem at hand. I'm just not able to figure out why it won't work on IE. Both Stackblitz and Codesandbox don't work on IE. But just the deployed App would open up properly. It also shows the styles in red giving an indication that there's an issue with the styles, even though it applies the styles – SiddAjmera Nov 25 '19 at 08:54
  • You are required to post a [mcve] here, **within your question**, and not any third party site. – Rob Nov 25 '19 at 13:33
  • Do you mean you are not able to produce the issue with just using the Matirial UI? It can be possible that some CSS code written your react app causing the issue. – Deepak-MSFT Nov 27 '19 at 09:24
  • No offense but I'm not quite sure if you've answered any Angular/React related questions here on StackOverflow. Coz we(OPs of Angular and React) use off-site tools like StackBliz and CodeSandbox all the time. Like I said, it's easier for the person who's genuinely interested in answering questions as they have a starting point to work with where they also have feedback of the changes they are making in the code. This was my sincere last attempt to make you understand my perspective. Cheers! – SiddAjmera Dec 08 '19 at 21:44

1 Answers1

1

The question was originally answered on twitter by Alexey Zuev on Twitter here

Just posting it here with a detailed explanation so that it might help someone. As Alexey mentioned in his tweet:

It's an issue with inlining svg into background css property in IE.

Just follow this answer Inline SVG in CSS and you will be able to fix the issue like here

At least it works in Edge :)

The FIX

  1. I went to https://mothereff.in/url and pasted the url encoded svg string there:

    Input:

    "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Crect width='23' height='23' x='.5' y='.5' fill='%23FFF' fill-rule='nonzero' stroke='%23999' rx='4'/%3E%3Ctext fill='%23F2410A' font-size='20' font-weight='bold'%3E%3Ctspan x='1' y='18'%3E✓%3C/tspan%3E%3C/text%3E%3C/g%3E%3C/svg%3E%0A\")"
    

    Output:

    "url(\"data:image/svg xml,<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><g fill='none' fill-rule='evenodd'><rect width='23' height='23' x='.5' y='.5' fill='#FFF' fill-rule='nonzero' stroke='#999' rx='4'/><text fill='#F2410A' font-size='20' font-weight='bold'><tspan x='1' y='18'>✓</tspan></text></g></svg>
    \")"
    
  2. Take the generated svg(from <svg till </svg>) and use btoa to encode the svg to Base64. While doing that, you'll get an error saying:

    VM116:1 Uncaught DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.

    Now the reason for this is because of this tick mark sign() that we have in our svg. So we'll first need to convert it into an extended special HTML code, which, for the sign, is &#10004; (Source)

  3. Now that we have an svg that can be encoded properly which looks like this:

    <svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><g fill='none' fill-rule='evenodd'><rect width='23' height='23' x='.5' y='.5' fill='#FFF' fill-rule='nonzero' stroke='#999' rx='4'/><text fill='#F2410A' font-size='20' font-weight='bold'><tspan x='1' y='18'>&#10004;</tspan></text></g></svg>
    

    We can pass it via btoa to generate a Base64 encoded string:

    const base64UrlString = btoa("<svg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'><g fill='none' fill-rule='evenodd'><rect width='23' height='23' x='.5' y='.5' fill='#FFF' fill-rule='nonzero' stroke='#999' rx='4'/><text fill='#F2410A' font-size='20' font-weight='bold'><tspan x='1' y='18'>&#10004;</tspan></text></g></svg>");
    
    console.log('Here is the generated Base64 Encoded String: ', base64UrlString);
  4. Finally, instead of the inline svg that we used earlier, we can now use the Base64 Encoded String:

    backgroundImage: "url(\"data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHdpZHRoPScyNCcgaGVpZ2h0PScyNCcgdmlld0JveD0nMCAwIDI0IDI0Jz48ZyBmaWxsPSdub25lJyBmaWxsLXJ1bGU9J2V2ZW5vZGQnPjxyZWN0IHdpZHRoPScyMycgaGVpZ2h0PScyMycgeD0nLjUnIHk9Jy41JyBmaWxsPScjRkZGJyBmaWxsLXJ1bGU9J25vbnplcm8nIHN0cm9rZT0nIzk5OScgcng9JzQnLz48dGV4dCBmaWxsPScjRjI0MTBBJyBmb250LXNpemU9JzIwJyBmb250LXdlaWdodD0nYm9sZCc+PHRzcGFuIHg9JzEnIHk9JzE4Jz7inJM8L3RzcGFuPjwvdGV4dD48L2c+PC9zdmc+\")",
    

    And it should render properly in IE as well.

Here's a Working Code Sample on StackBlitz for your ref.

SiddAjmera
  • 38,129
  • 5
  • 72
  • 110