How can I display names in a condensed format using initials in React and change the background colour?

57 Views Asked by At

I am making a website and I want to display names in a condensed format using initials. For example, Thomas Shelby should be shown as TS. Now Taylor Swift will also be shown as TS. In such a case, i want the background color for Taylor Swift's TS to be different. The default background color for all initials is light blue. So if its TS and MJ, both will be light blue. See the photo below. How do I do this in React?

I get the names from props, filtering and mapping as (elem, i) and ive got the name formatting to just the initials to work.

This is how I'm formatting the name

const initials = elm.name.split(' ')
                    .filter((n, index) => index===0 || index===elm.name.split(' ').length - 1)
                    .map(n=>n[0])
                    .join('').toUpperCase();

And then im doing a return statement inside the map function which returns the name class inside of an anchor tag. This is how im displaying the initials, the "name" class has the default background color of light blue <span className="name" style={{ backgroundColor }}>{initials} </span>

This is what i want Example

What i have tried is writing a function for this after i finish the formatting for initials.

const backgroundColor = getBackgroundColor(initials);

  const [existingInitials, setExistingInitials] = useState(new Set());

 //Color change based on initials 
  function getBackgroundColor(initials) {
    if (existingInitials.has(initials)) {
      return getRandomColor(); // Return a random color if initials already exist
    } else {
      existingInitials.add(initials);
      return '#DFF2FF'; // light blue
    }
  }

This is assigning a random color to the first initial as well (IF i have an MJ and then another MJ, this code gives a random background color for both MJs which i dont want. I want the first MJ to have light blue and the second to have a random color)

1

There are 1 best solutions below

1
Reyno On

Instead of a random color I'd suggest using a predefined set of colors. After x amount you can just loop them again. This way all colors look good in your design but you can also tell same initials apart.

In the example below the color order will always be: red, green, blue, yellow, pink, cyan.

The example is in vanilla JS but can easily be translated to React.

const colors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff', '#00ffff']; // After six we can probably loop since they are far enough apart.

// Demo function to generate an avatar.
function createAvatar(color, text) {
  const div = document.createElement('div');
  div.classList.add('avatar');
  div.style.background = color;
  div.textContent = text;
  document.body.appendChild(div);
}

const existing = {};
const initials = ['TS', 'BM', 'TS', 'JK', 'TS', 'NF', 'TS', 'TS', 'TS', 'TS'];

for(const initial of initials) {
  existing[initial] ??= 0; // Set count to 0 if it doesn't exist.
  
  const color = colors[existing[initial] % colors.length];
  createAvatar(color, initial);
  
  existing[initial]++;
}
body {
  display: flex;
}

.avatar {
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: #ffffff;
}