How to apply a skin tone to an emoji? 🧛🧛🏻🧛🏼🧛🏽🧛🏾🧛🏿
Tags: javascript, typescript, programming, emoji
Published: 2024-05-15 18:43:34

# 🧑‍💻 Applying Skin Tones to Emojis in JavaScript: A Fun Guide

**[DEMO](https://codepen.io/dejurin/pen/QWRwPXY)** 👀
**[CDN](https://unpkg.com/browse/@qit.tools/skin-tone/)**

## 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](https://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:

```javascript
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);
}
```

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:

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

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:

```javascript
const skinToneMap = {
  none: '',
  light: '\u{1F3FB}',
  mediumLight: '\u{1F3FC}',
  medium: '\u{1F3FD}',
  mediumDark: '\u{1F3FE}',
  dark: '\u{1F3FF}',
};
```

### 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:

```javascript
let zwj = '\u200D';

if (emoji.includes('\u200d\ud83e\udd1d\u200d')) {
  zwj = '\u200d\ud83e\udd1d\u200d';
}
```

### 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:

```javascript
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;
});
```

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:

```javascript
return modifiedParts.join(zwj);
```

## 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

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

console.log(skinTone("🧁", "dark")); // 🧁
console.log(skinTone("🧑🏿‍🤝‍🧑🏿", "light")); // 🧑🏻‍🤝‍🧑🏻
```

### Browser

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

document.addEventListener("DOMContentLoaded", () => {
    console.log(skinTone("🧑🏻‍🤝‍🧑🏻", "dark"));
});
```