DEV Community

Cover image for How to apply a skin tone to an emoji? πŸ§›πŸ§›πŸ»πŸ§›πŸΌπŸ§›πŸ½πŸ§›πŸΎπŸ§›πŸΏ
YURII DE.
YURII DE.

Posted on

How to apply a skin tone to an emoji? πŸ§›πŸ§›πŸ»πŸ§›πŸΌπŸ§›πŸ½πŸ§›πŸΎπŸ§›πŸΏ

πŸ§‘β€πŸ’» Applying Skin Tones to Emojis in JavaScript: A Fun Guide

DEMO πŸ‘€
CDN

Introduction

Welcome to the world of emojis! πŸŽ‰ Emojis are a universal language, transcending borders and bringing a touch of personality to our digital conversations. But have you ever wondered how to change the skin tone of an emoji programmatically? Whether it's to add a personal touch or to represent diversity, modifying emoji skin tones can be a fun and useful feature. In this article, written with Qit.tools, we'll explore how to create a function to apply skin tones to emojis in JavaScript. Ready? Let's dive in! 🌊

The Function Breakdown

Here's the function we'll be working with:

export type SkinTone = '' | 'none' | 'light' | 'mediumLight' | 'medium' | 'mediumDark' | 'dark';

/**
 * Apply skin tones to an emoji.
 * Visit us at: https://qit.tools
 *
 * πŸͺ„ Qit.tools
 * @copyright Copyright (c) 2024 Qit.tools.
 * @see https://github.com/Qit-tools/skin-tone
 * @see https://www.npmjs.com/package/@qit.tools/skin-tone
 *
 * Change emoji skin tones effortlessly. πŸ§›πŸ§›πŸ»πŸ§›πŸΌπŸ§›πŸ½πŸ§›πŸΎπŸ§›πŸΏ
 * RGI Emoji Modifier Sequence.
 *
 * @param {string} emoji - The original emoji string.
 * @param {SkinTone} tone - The skin tone to apply. If empty, returns the original emoji.
 * @returns {string} The emoji string with skin tones applied where applicable.
 */
export default function skinTone(emoji: string, tone?: SkinTone): string {
  if (!tone) {
    return emoji;
  }
  const skinToneMap = {
    none: '',
    light: '\u{1F3FB}',
    mediumLight: '\u{1F3FC}',
    medium: '\u{1F3FD}',
    mediumDark: '\u{1F3FE}',
    dark: '\u{1F3FF}',
  };

  let zwj = '\u200D';

  // Hand Shake πŸ§‘β€πŸ€β€πŸ§‘
  if (emoji.includes('\u200d\ud83e\udd1d\u200d')) {
    zwj = '\u200d\ud83e\udd1d\u200d';
  }

  const parts = emoji.split(zwj);
  const modifiedParts = parts.map((part) => {
    const basePart = part.replace(/\p{Emoji_Modifier}/gu, '');

    if (/\p{Emoji_Modifier_Base}/u.test(basePart)) {
      return basePart.replace(/(\p{Extended_Pictographic}+)(\uFE0F?)/u, `$1${skinToneMap[tone]}`);
    }
    return part;
  });

  return modifiedParts.join(zwj);
}
Enter fullscreen mode Exit fullscreen mode

Let's break down the key aspects of this function.

Key Aspects

1. Type Definition

First, we define the SkinTone type, which includes various skin tone options:

export type SkinTone = '' | 'none' | 'light' | 'mediumLight' | 'medium' | 'mediumDark' | 'dark';
Enter fullscreen mode Exit fullscreen mode

This type helps ensure that our function receives only valid skin tone values.

2. Function Parameters

The skinTone function accepts two parameters:

  • emoji: The original emoji string.
  • tone: The skin tone to apply.

If no tone is provided, the function returns the original emoji.

3. Skin Tone Map

We create a map to associate skin tone names with their respective Unicode modifiers:

const skinToneMap = {
  none: '',
  light: '\u{1F3FB}',
  mediumLight: '\u{1F3FC}',
  medium: '\u{1F3FD}',
  mediumDark: '\u{1F3FE}',
  dark: '\u{1F3FF}',
};
Enter fullscreen mode Exit fullscreen mode

4. Zero Width Joiner (ZWJ)

A Zero Width Joiner (ZWJ) is used to join multiple emoji characters into a single composite emoji. For example, the handshake emoji πŸ§‘β€πŸ€β€πŸ§‘ uses ZWJs to combine two people emojis. Our function checks if the emoji includes a handshake sequence and adjusts the ZWJ accordingly:

let zwj = '\u200D';

if (emoji.includes('\u200d\ud83e\udd1d\u200d')) {
  zwj = '\u200d\ud83e\udd1d\u200d';
}
Enter fullscreen mode Exit fullscreen mode

5. Splitting and Modifying Emoji Parts

We split the emoji string by the ZWJ and map over the parts to apply the skin tone where applicable:

const parts = emoji.split(zwj);
const modifiedParts = parts.map((part) => {
  const basePart = part.replace(/\p{Emoji_Modifier}/gu, '');

  if (/\p{Emoji_Modifier_Base}/u.test(basePart)) {
    return basePart.replace(/(\p{Extended_Pictographic}+)(\uFE0F?)/u, `$1${skinToneMap[tone]}`);
  }
  return part;
});
Enter fullscreen mode Exit fullscreen mode

Here, we:

  • Remove any existing skin tone modifiers.
  • Check if the part is an emoji modifier base.
  • Apply the new skin tone.

6. Joining the Modified Parts

Finally, we join the modified parts back together with the ZWJ:

return modifiedParts.join(zwj);
Enter fullscreen mode Exit fullscreen mode

Conclusion

And there you have it! πŸ₯³ With just a few lines of code, we've created a function that can dynamically apply skin tones to emojis. Whether you're building a chat application or simply want to add a touch of diversity to your project, this function can come in handy. So go ahead, play around with it, and bring some color to your emojis! 🌈

Remember, in the world of programming, a little creativity goes a long way. And if all else fails, just add more emojis. 😜

Happy coding! πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»


Ready-made library.

πŸ—οΈ Install

πŸŽ‰ NPM

npm i @qit.tools/skin-tone

🧁 Bun

bun add @qit.tools/skin-tone

🌟 PNPM

pnpm add @qit.tools/skin-tone

🧢 Yarn

yarn add @qit.tools/skin-tone


πŸŽ“ How to use

NodeJS

// Import by default
import skinTone from "@qit.tools/skin-tone";

console.log(skinTone("🧁", "dark")); // 🧁
console.log(skinTone("πŸ§‘πŸΏβ€πŸ€β€πŸ§‘πŸΏ", "light")); // πŸ§‘πŸ»β€πŸ€β€πŸ§‘πŸ»
Enter fullscreen mode Exit fullscreen mode

Browser

// https://unpkg.com/@qit.tools/skin-tone@0.6.2/dist/browser/latest.min.js

document.addEventListener("DOMContentLoaded", () => {
    console.log(skinTone("πŸ§‘πŸ»β€πŸ€β€πŸ§‘πŸ»", "dark"));
});
Enter fullscreen mode Exit fullscreen mode

Top comments (0)