1

I want text entry to be highlighted with different colors depending on the character entered.

My hunch is that it is possible to do this by adding <span> elements with the appropriate styling inside of a contenteditable div.

Is there a better way?

2 Answers 2

1

Hi Please check this example. I used material-ui

import React, {useState} from 'react';
import Box from '@material-ui/core/Box';
import TextField from "@material-ui/core/TextField";

export default function BackgroundColor() {
    const [text, setText] = useState('');
    const [color, setColor] = useState('');

    function changeHandler(event) {
        setText(event.target.value);
        if(event.target.value.toLowerCase() === 'a'){
            setColor("primary.main");
        }
        else if(event.target.value.toLowerCase() === 'b'){
            setColor("secondary.main");
        }
        else if(event.target.value.toLowerCase() === 'c'){
            setColor("error.main");
        }
        else{
            setColor("info.main");
        }
    }
    return (
        <div>
            <TextField id="standard-basic" label="Standard" helperText="Type A or B or C" onChange={changeHandler} />
            <Box color={color}>
                {text}
            </Box>
        </div>
    );
}
Sign up to request clarification or add additional context in comments.

3 Comments

thanks for the suggestion. this solution colors the entire textfield while I want to have individual characters have their own background
@Anisotropic, I have updated my answer. can you please check that?
The short answer is no, there is no better way. You need each character to be its own SPAN in order to have its own background-color. And storing that as a state can be quite interesting. Maybe you should just store it as HTML and call some sort of render function.
1

Depending on the complexity, you can also consider using Ace Editor

import React, { useState } from "react";
import AceEditor from "react-ace-builds";
import "./yamlHighlightRules";
import "ace-builds/src-noconflict/theme-github";
import "ace-builds/src-noconflict/ace";
import "./styles.css";

export default function App() {
  const [text, setText] = useState("This is the most amazing initial text.");

  const handleChange = input => {
    setText(input);
  };

  return (
    <div className="App">
      <AceEditor
        mode="yaml"
        theme="github"
        name="editor"
        fontSize={15}
        showPrintMargin={true}
        showGutter={false}
        highlightActiveLine={false}
        value={text}
        onChange={handleChange}
        setOptions={{
          showLineNumbers: true,
          tabSize: 2,
          readOnly: false
        }}
        height={"600px"}
        width={"100%"}
      />
    </div>
  );
}

And then I edited an existing set of yaml highlighting rules, it's easier not starting from scratch.

import ace from "ace-builds/src-min-noconflict/ace";
import "ace-builds/src-noconflict/mode-text";

ace.define("ace/mode/yaml_highlight_rules", [], function(require, exports) {
  const oop = require("../lib/oop");
  const TextHighlightRules = require("./text_highlight_rules")
    .TextHighlightRules;

  const YamlHighlightRules = function() {
    this.$rules = {
      start: [
        {
          token: "highlight",
          regex: /amazing/
        }
      ]
    };
    this.normalizeRules();
  };

  oop.inherits(YamlHighlightRules, TextHighlightRules);

  exports.YamlHighlightRules = YamlHighlightRules;
});

The token is your css class. Just add the prefix ace_ to it. Then you define a regular expression to determine what gets that class.

.ace_highlight {
  background-color: yellow;
}

Here is a codesandbox where you can see it working. And here are the docs on defining your own modes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.