Converting bullet point list to checkboxes once requirements have been satisfied

I am working on developing a password validator with specific regex conditions in Material UI that transitions from bullet points to checkboxes when the criteria are satisfied. https://i.sstatic.net/b0pgb.png

Initially, I attempted to use the npm library NiceInputPassword, but it did not allow me to easily update the state. As a result, I have decided to revert back to using regular Material UI components. Although I have researched documentation on lists in Material UI, I have not found any information on how to convert bullet points to checkboxes like shown in the provided image.

Answer №1

If you want to fulfill all your needs, utilize the @mui/material and @mui/icons-material libraries in this manner:

import { TextField } from "@mui/material";
import { useEffect, useState } from "react";
import "./styles.css";
import CheckCircleIcon from "@mui/icons-material/CheckCircle";
import CircleIcon from "@mui/icons-material/Circle";

function checkUppercase(str) {
  for (let i = 0; i < str.length; i++) {
    if (
      str.charAt(i) === str.charAt(i).toUpperCase() &&
      str.charAt(i).match(/[a-z]/i)
    ) {
      return true;
    }
  }
  return false;
}

const SPECIAL_CHARS = "!@#$%^&*()";

function checkSpecialChars(str) {
  const alreadyFoundChars = [];
  for (let i = 0; i < str.length; i++) {
    const currentChar = str[i];
    if (!alreadyFoundChars.includes(currentChar)) {
      if (SPECIAL_CHARS.includes(currentChar)) {
        alreadyFoundChars.push(currentChar);
      }
    }
  }
  return alreadyFoundChars.length >= 3;
}

const getIcon = (isChecked) => {
  const smallDotIcon = <CircleIcon sx={{ fontSize: "0.4rem" }} />;
  const checkCircleIcon = <CheckCircleIcon sx={{ fontSize: "0.8rem" }} />;
  const iconToBeRendered = isChecked ? checkCircleIcon : smallDotIcon;

  return (
    <div
      style={{
        height: "20px",
        width: "15px",
        display: "flex",
        alignItems: "center",
        justifyContent: "center"
      }}
    >
      {iconToBeRendered}
    </div>
  );
};

const prepareHelperText = (value) => {
  const firstIcon = getIcon(value.length >= 8);
  const secondIcon = getIcon(checkUppercase(value));
  const thirdIcon = getIcon(checkSpecialChars(value));

  return (
    <div>
      <div style={{ display: "flex" }}>
        {firstIcon}
        Must contain at least 8 characters
      </div>
      <div style={{ display: "flex" }}>
        {secondIcon} Must contain at least 1 uppercase letter
      </div>
      <div style={{ display: "flex" }}>
        {thirdIcon} Must contain 3 of the 4 types of characters !@#$%^&*()
      </div>
    </div>
  );
};

export default function App() {
  const [value, setValue] = useState("");
  const [helperText, setHelperText] = useState("");

  useEffect(() => {
    setHelperText(prepareHelperText(value));
  }, [value]);

  return (
    <div className="App">
      <TextField
        type="password"
        label="Password"
        value={value}
        onChange={(e) => setValue(e.target.value)}
        helperText={helperText}
        sx={{
          "& .Mui-focused": {
            color: "purple"
          },
          "& label.Mui-focused": {
            color: "purple !important"
          },
          "& .MuiOutlinedInput-root": {
            "&.Mui-focused fieldset": {
              borderColor: "purple"
            }
          }
        }}
      />
    </div>
  );
}

To see a demonstration of this solution in action, visit this sandbox.

Answer №2

To achieve your desired outcome using the available libraries and components, there are a few steps involved which I will explain in detail.

When working with React-Nice-Input-Password, you can provide a custom class name for different states such as success by utilizing

<NiceInputPassword successClassName="custom-success"
. By adding this prop, you can style the bullet points accordingly using CSS selectors like
.input-password__description li.custom-success:before
. Consider experimenting with less specific selectors for customization possibilities.

The interesting part comes when styling the bullet points. You can set the background-color: transparent, then add a background image using a Data URL referencing an SVG code like the CheckCircle from MUI Icons with customized properties such as width, height, and fill color.

.input-password__description li.custom-success:before {
  background-color: transparent;
  background-image: url('data:image/svg+xml;utf-8,<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 24 24"><path fill="%232196F3" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"></path></svg>');
}

If you wish to customize the color further, you have options like adjusting the fill property or using the filter CSS property to modify specific elements.

Remember to import the CSS file appropriately into your project for the styles to take effect, like import './custom.css';.

For reference, here is a sandbox showcasing the described changes in action with varying colors for the success bullet points:

https://codesandbox.io/s/reactniceinputpassword-forked-od5r1y?fontsize=14&hidenavigation=1&theme=dark

Additional resources for further reading:

  • Guide on changing SVG fill color in base-64 background image data
  • Using Material Design Icon as CSS background-image value

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best method for creating a top margin that is dependent on the height of the browser?

Is there a way to make the CSS margin: top; on my HTML main_content element relative to the browser window? I want the main_content to always stay at the bottom of the browser window. How can I achieve this? I attempted the following code, but it didn&apo ...

How to use Javascript to pause an HTML5 video when closed

I am new to coding and currently working on a project in Adobe Edge Animate. I have managed to create a return button that allows users to close out of a video and go back to the main menu. However, I am facing an issue where the video audio continues to p ...

The contenteditable div's selectAll feature doesn't function properly when it gains focus

I'm working with divs in a table structure and here's an example: <div contenteditable="true" onfocus="document.execCommand('selectAll',false,null)">Something</div> Clicking on a div to focus works perfectly, selectin ...

"Disappearing Act: The Mysterious Vanishing of the JS

When I run my project using a node server, I have to execute three commands in the command prompt every time: npm install node server grunt serve I included a pagination directive from Git-hub in my project. However, every time I initialize the project ...

Customizing Material UI Stepper styles using CSS API

I am trying to customize the text color (represented by an SVG Icon) in Material UI StepIcon for active and completed steps only. Currently, I have successfully changed the icon color for those steps. This is how my custom MuiTheme appears: export default ...

Transforming the current date() into a distinctive format, encompassing the utilization of T

Background In my Angular UI, I have a datepicker that is defined as: <date-picker name="contractEndDate" date="employee.contractEndDate"></date-picker> When the button is clicked, the contractEndDate value changes from null to the current da ...

Utilizing the Node -r flag within npm scripts on Azure App Service: A step-by-step guide

I need assistance with running a Node site on an Azure App Service. The issue arises when trying to start the server with the specified line in my package.json scripts. "scripts": { ... "serve": "node -r dotenv-a ...

Executing Selenium WebDriver to interact with a hidden element

Hello, I am interested in learning how to interact with hidden elements and disable them using Selenium WebDriver. I've managed to achieve this with Selenium 1 by using the following code: selenium.click(id="idOfHiddenField"); Unfortunately, this a ...

Learn how to troubleshoot and resolve a bug in the mobile Chrome browser that pertains to the position fixed feature

On the mobile version of Firefox, everything works perfectly. However, there seems to be a bug in Chrome with the fixed positioning. When scrolling, the header should change from absolute to fixed and the height should go from 65 to 35 pixels. Unfortunatel ...

How can I make a checkbox checked in AngularJS?

Hello, I am currently working on a web application using AngularJS. Within this application, I have a form where I am populating values into a multi-select dropdown. <li ng-repeat="p in locations"> <input type="checkbox" ng-checked="master" n ...

Using React Native to submit FormData to a C# API

I have encountered an issue with sending two pieces of information from my React Native app to my C# API. The specific problem arises when I attempt to send a UserId along with a picture. While using form-data on Postman shows that the information success ...

The TD border is slicing through the div and is placed on the table in IE standards, causing it

Below is the HTML code where the div is being cut by the table border when the page is in standards mode. Interestingly, if I remove the <!DOCTYPE html>, then it works fine as expected. The issue of the outside div not behaving properly on the table ...

The importance of manually loading extensions and utilizing Ajax effectively for renderPartial

Within my yii application, I have implemented Tabs and am loading content via ajax using renderPartial(). To prevent redundant script loading, I have set processOutput to false. As a result, I aim to manually load all necessary scripts once on the index pa ...

How can I make a recently added row clickable in an HTML table?

I have a table where each row is given the class ".clickablerow". I've set up an onclick function so that when a row is clicked, a dialog box appears allowing me to insert text above or below as a new row. The issue I'm facing is that even though ...

Tips for making a slide-in animation that doesn't require adjusting the browser size

As I work on an animation where an img object and text slide in from outside the frame of the webpage upon page load, everything seems to be running smoothly. But there's one glaring issue: right at the start of the page load, the webpage resizes for ...

Stop the duplication of the HTML content to ensure only one copy is saved

Recently, I have been coding a feature that saves the HTML of the currently displayed page to another file upon pressing a button. However, I encountered an issue where if the button is pressed multiple times quickly, the saved file contains incorrect HTML ...

A URL that quickly updates live content from a backend script

As a beginner, I am seeking guidance as to where to start on my journey of learning. I need assistance in creating a script that can efficiently fit within a small URI space and constantly updates itself with information from a server script. My target bro ...

Ways to eliminate text following a string substitution

When running the code below with keys assigned to summer, spring, fall, and winter, the output for ins would be: ['req.body.summer, req.body.spring, req.body.fall, req.body.winter'] I need to eliminate the surrounding string from the replace co ...

My ng-view html is unexpectedly displaying as plain string. What steps should I take to resolve this issue?

Why is my ng-view HTML displaying as plain text? How can I resolve this issue? I have encountered an error, here is the screenshot for reference: Unfortunately, I am unable to upload images at the moment. ...

What is the best way to show the initial 20 words on the screen, followed by the next 20 words using

Within a single tag, I have a string as shown in the example below. My goal is to display the first 20-25 words on screen, then continue with the next set of words, and so forth. Once 20 words are displayed, the remaining text should be hidden. <p>Lo ...