Input Box with Character Counter  in React

Input Box with Character Counter in React

There is requirement of having Character Counter Feature on Input Fields or Text Boxes.

Therefore, my strategy is to develop a higher order component that can accept any text box or input field.

This HOC accepts a children, charLimit, count and optionally a style object

so Let's create a Functional component called CharCounter

import React from 'react';
import { PropTypes } from 'prop-types';

const CharCounter = () => {
  return (
    <div>
      CharCounter
    </div>
  );
};

CharCounter.propTypes = {};

export default CharCounter;

If you don't use propTypes then just ignore that part

Now, wherever we need a character counter, we can call this component like this.

Although antd components were utilised in the examples below, the normal input field and Text Area both support the maxLength attribute.

CharCounter HOC with input field

charcounter HOC with TextBox

we can pass the length of the state in the count prop.
Accept these props in our HOC

import React from 'react';
import { PropTypes } from 'prop-types';

const CharCounter = ({children, count,style , charLimit = 0,}) => {
  return (
    <div>
      {children}
      <small> 
        {`count : ${count}/${charLimit}`}
      </small>
    </div>
  );
};

CharCounter.propTypes = {
  charLimit: PropTypes.number.isRequired,
  count: PropTypes.number.isRequired,
  children: PropTypes.objectOf(PropTypes.any).isRequired,
  style: PropTypes.objectOf(PropTypes.any).isRequired,
};

export default CharCounter;

Let's add a little style.

import React from 'react';
import { PropTypes } from 'prop-types';
import styled from 'styled-components';

const CharCounter = ({children, count,style , charLimit = 0,}) => {
  ;
  return (
    <LimitTextBox style={style}>
      {children}
      <small>
        {`count : ${count}/${charLimit}`}
      </small>
    </LimitTextBox>
  );
};

CharCounter.propTypes = {
  charLimit: PropTypes.number.isRequired,
  count: PropTypes.number.isRequired,
  children: PropTypes.objectOf(PropTypes.any).isRequired,
  style: PropTypes.objectOf(PropTypes.any).isRequired,
};

export default CharCounter;

const LimitTextBox = styled.div`
  display: flex;
  flex-direction: column;
  align-items: end;

  small {
    line-height: 1;
  }
`;

When our text reaches the character limit, let's change its colour to red.

we will decalre a function called getCounterColor
this function will return the color of the counter

 const getCounterColor = () => {
    if (charLimit - count <= Math.round(charLimit * 0.25)) {
      return 'red';
    }
    return 'black';
  };

Final Code :

import React from 'react';
import { PropTypes } from 'prop-types';
import styled from 'styled-components';

const CharCounter = ({children, count,style , charLimit = 0,}) => {
  const getCounterColor = () => {
    if (charLimit - count <= Math.round(charLimit * 0.25)) {
      return 'red';
    }
    return 'black';
  };
  return (
    <LimitTextBox style={style}>
      {children}
      <small
        style={{ color: getCounterColor() }}
      >
        {`count : ${count}/${charLimit}`}
      </small>
    </LimitTextBox>
  );
};

CharCounter.propTypes = {
  charLimit: PropTypes.number.isRequired,
  count: PropTypes.number.isRequired,
  children: PropTypes.objectOf(PropTypes.any).isRequired,
  style: PropTypes.objectOf(PropTypes.any).isRequired,
};

export default CharCounter;

const LimitTextBox = styled.div`
  display: flex;
  flex-direction: column;
  align-items: end;

  small {
    line-height: 1;
  }
`;