1

enter image description here

enter image description here

enter image description here

I have a basic icon, I would like to make sure that if for example I receive a message that I have not yet read, the icon shows me the number of unread messages.

As seen in the image above.

So how can I make sure that having a basic icon it can show me a badge on it with a number set by me.

For example, as you can see, discord changes automatically.

The first image is a normal icon.

The second image is used when there are unread messages.

The third image is used when a user is tagged, but this number increases, so I don't think there are as many images with all possible numbers, I think they are generated based on the normal image.

Can anyone help me out?

Paul
  • 3,644
  • 9
  • 47
  • 113

1 Answers1

1

This question has two parts:

  1. How to add a badge to an icon?
  2. How to change the favicon dynamically?

I am using NextJS and thus my answer will show how I did it using NextJS. For vanilla React, see for example Dynamically changing favicon in react.js (which doesn't deal with part 1 of the question).

For part 1, I use an SVG favicon that is generated by a JavaScript function which looks something like this:

export const faviconString = (badge?: string | number) => {
  let svgFavicon =
    '<svg viewBox="0 0 100 100" width="100%" height="100%"  xmlns="http://www.w3.org/2000/svg">';
  svgFavicon +=
    '<rect x="0" y="0" width="100%" height="100%" fill="#2196f3" rx="0" ry="0"></rect>';

  if (badge) {
    svgFavicon += '<circle cx="67" cy="33" r="30" fill="red"></circle>';
    svgFavicon +=
      '<text font-family="sans-serif" x="68" y="47.7" font-size="3em" fill="white" text-anchor="middle">';
    if (
      !(typeof badge === 'string' && badge.length > 1) &&
      !(typeof badge === 'number' && badge > 9)
    ) {
      svgFavicon += badge;
    }
    svgFavicon += '</text>';
  }
  svgFavicon += '</svg>';

  const svgFaviconEncoded = Buffer.from(svgFavicon).toString('base64');
  const svgFaviconWithPrefix = `data:image/svg+xml;base64,${svgFaviconEncoded}`;
  return svgFaviconWithPrefix;
};

The favicon is a blue square. Mine is slightly more complicated but for brevity I reduced it. Note that the SVG is in a string and not an SVG react component or separate SVG file. At the end, it is base64-encoded and the prefix needed to use it as a Data URL is added.

Before the closing SVG tag, some logic is introduced that draws a red circle and, if applicable, a number or a string is drawn on top of that.

For part 2, I use the next/head component and a regular old useEffect, something like this:

useEffect(() => {
  const newFavicon = faviconString(unreadMessages);
  setFavicon(newFavicon);
}, [unreadMessages]);

and in the return statement:

<Head>
  <link rel="icon" href={favicon} key="favicon" />
</Head>

If you want an icon that's not an SVG icon, sorry. Good luck!