2016-07-28 19:25:38 +00:00
< div align = "center" >
< br > < b > Emoji Mart< / b > is a Slack-like customizable< br > emoji picker component for React
2017-04-19 13:17:59 +00:00
< br > < a href = "https://missive.github.io/emoji-mart" > Demo< / a > • < a href = "https://github.com/missive/emoji-mart/releases" > Changelog< / a >
2019-03-16 17:26:09 +00:00
< br > < a href = "https://travis-ci.org/nolanlawson/emoji-mart" > < img src = "https://travis-ci.org/nolanlawson/emoji-mart.svg?branch=master" alt = "Build Status" > < / a >
2018-07-31 19:12:58 +00:00
< br > < br > < img width = "338" alt = "picker" src = "https://user-images.githubusercontent.com/436043/43481399-d9b60acc-94d3-11e8-9b3b-e5f2db8f0bd1.png" >
2017-11-08 05:32:56 +00:00
< br > < br > < a title = "Team email, team chat, team tasks, one app" href = "https://missiveapp.com" > < img width = "30" alt = "Missive | Team email, team chat, team tasks, one app" src = "https://user-images.githubusercontent.com/436043/32532559-0d15ddfc-c400-11e7-8a24-64d0157d0cb0.png" > < / a >
2016-07-28 19:35:11 +00:00
< br > Brought to you by the < a title = "Team email, team chat, team tasks, one app" href = "https://missiveapp.com" > Missive< / a > team
2016-07-28 19:25:38 +00:00
< / div >
2016-06-01 00:53:01 +00:00
2017-05-05 01:18:48 +00:00
## Installation
`npm install --save emoji-mart`
2016-07-28 19:25:38 +00:00
## Components
### Picker
2016-06-01 00:53:01 +00:00
```jsx
2018-03-13 06:21:55 +00:00
import 'emoji-mart/css/emoji-mart.css'
2016-07-28 19:25:38 +00:00
import { Picker } from 'emoji-mart'
2016-06-01 00:53:01 +00:00
2016-10-19 01:21:10 +00:00
< Picker set = 'emojione' / >
2018-03-15 19:36:07 +00:00
< Picker onSelect = {this.addEmoji} / >
2016-10-19 01:21:10 +00:00
< Picker title = 'Pick your emoji…' emoji = 'point_up' / >
< Picker style = {{ position: ' absolute ' , bottom: ' 20px ' , right: ' 20px ' } } / >
2016-10-27 03:22:59 +00:00
< Picker i18n = {{ search: ' Recherche ' , categories: { search: ' R é sultats de recherche ' , recent: ' R é cents ' } } } / >
2016-07-28 19:25:38 +00:00
```
| Prop | Required | Default | Description |
| ---- | :------: | ------- | ----------- |
2017-04-04 15:26:02 +00:00
| **autoFocus** | | `false` | Auto focus the search input when mounted |
2016-07-28 19:25:38 +00:00
| **color** | | `#ae65c5` | The top bar anchors select and hover color |
2017-05-25 17:28:18 +00:00
| **emoji** | | `department_store` | The emoji shown when no emojis are hovered, set to an empty string to show nothing |
2017-04-07 21:09:30 +00:00
| **include** | | `[]` | Only load included categories. Accepts [I18n categories keys ](#i18n ). Order will be respected, except for the `recent` category which will always be the first. |
2017-04-04 15:56:08 +00:00
| **exclude** | | `[]` | Don't load excluded categories. Accepts [I18n categories keys ](#i18n ). |
2017-05-24 15:36:48 +00:00
| **custom** | | `[]` | [Custom emojis ](#custom-emojis ) |
2017-10-07 17:32:49 +00:00
| **recent** | | | Pass your own frequently used emojis as array of string IDs |
2016-07-28 19:25:38 +00:00
| **emojiSize** | | `24` | The emoji width and height |
2018-03-15 19:36:07 +00:00
| **onClick** | | | Params: `(emoji, event) => {}` . Not called when emoji is selected with `enter` |
| **onSelect** | | | Params: `(emoji) => {}` |
2018-03-02 18:33:14 +00:00
| **onSkinChange** | | | Params: `(skin) => {}` |
2016-07-28 19:25:38 +00:00
| **perLine** | | `9` | Number of emojis per line. While there’ s no minimum or maximum, this will affect the picker’ s width. This will set *Frequently Used* length as well (`perLine * 4`) |
2016-10-27 03:22:59 +00:00
| **i18n** | | [`{…}` ](#i18n ) | [An object ](#i18n ) containing localized strings |
2017-02-17 15:15:12 +00:00
| **native** | | `false` | Renders the native unicode emoji |
2017-05-27 17:52:49 +00:00
| **set** | | `apple` | The emoji set: `'apple', 'google', 'twitter', 'emojione', 'messenger', 'facebook'` |
2016-10-27 01:31:56 +00:00
| **sheetSize** | | `64` | The emoji [sheet size ](#sheet-sizes ): `16, 20, 32, 64` |
2017-04-04 15:46:11 +00:00
| **backgroundImageFn** | | ```((set, sheetSize) => …)``` | A Fn that returns that image sheet to use for emojis. Useful for avoiding a request if you have the sheet locally. |
2017-05-27 17:26:02 +00:00
| **emojisToShowFilter** | | ```((emoji) => true)``` | A Fn to choose whether an emoji should be displayed or not |
2017-09-28 02:02:30 +00:00
| **showPreview** | | `true` | Display preview section |
2018-03-02 20:08:52 +00:00
| **showSkinTones** | | `true` | Display skin tones picker |
2017-10-07 03:34:06 +00:00
| **emojiTooltip** | | `false` | Show emojis short name when hovering (title) |
2018-03-02 18:45:33 +00:00
| **skin** | | | Forces skin color: `1, 2, 3, 4, 5, 6` |
| **defaultSkin** | | `1` | Default skin color: `1, 2, 3, 4, 5, 6` |
2018-08-10 18:11:28 +00:00
| **skinEmoji** | | | The emoji used to pick a skin tone. Uses an emoji-less skin tone picker by default |
2016-07-28 19:25:38 +00:00
| **style** | | | Inline styles applied to the root element. Useful for positioning |
| **title** | | `Emoji Mart™` | The title shown when no emojis are hovered |
2018-07-30 21:06:23 +00:00
| **notFoundEmoji** | | `sleuth_or_spy` | The emoji shown when there are no search results |
2018-07-30 20:52:41 +00:00
| **notFound** | | | [Not Found ](#not-found ) |
2018-06-22 21:23:42 +00:00
| **icons** | | `{}` | [Custom icons ](#custom-icons ) |
2016-06-01 00:53:01 +00:00
2016-10-27 03:22:59 +00:00
#### I18n
```js
search: 'Search',
2019-03-09 21:03:00 +00:00
clear: 'Clear', // Accessible label on "clear" button
2017-04-18 15:20:17 +00:00
notfound: 'No Emoji Found',
2018-08-10 18:10:55 +00:00
skintext: 'Choose your default skin tone',
2016-10-27 03:22:59 +00:00
categories: {
search: 'Search Results',
recent: 'Frequently Used',
people: 'Smileys & People',
nature: 'Animals & Nature',
foods: 'Food & Drink',
activity: 'Activity',
places: 'Travel & Places',
objects: 'Objects',
symbols: 'Symbols',
flags: 'Flags',
2017-05-24 15:36:48 +00:00
custom: 'Custom',
2019-03-10 17:57:43 +00:00
},
categorieslabel: 'Emoji categories', // Accessible title for the list of categories
2019-03-09 22:19:24 +00:00
skintones: {
1: 'Default Skin Tone',
2: 'Light Skin Tone',
3: 'Medium-Light Skin Tone',
4: 'Medium Skin Tone',
5: 'Medium-Dark Skin Tone',
6: 'Dark Skin Tone',
},
2016-10-27 03:22:59 +00:00
```
2016-10-27 01:31:56 +00:00
#### Sheet sizes
Sheets are served from [unpkg ](https://unpkg.com ), a global CDN that serves files published to [npm ](https://www.npmjs.com ).
2018-04-30 00:55:13 +00:00
| Set | Size (`sheetSize: 16`) | Size (`sheetSize: 20`) | Size (`sheetSize: 32`) | Size (`sheetSize: 64`) |
| --------- | ---------------------- | ---------------------- | ---------------------- | ---------------------- |
| apple | 334 KB | 459 KB | 1.08 MB | 2.94 MB |
| emojione | 315 KB | 435 KB | 1020 KB | 2.33 MB |
| facebook | 322 KB | 439 KB | 1020 KB | 2.50 MB |
| google | 301 KB | 409 KB | 907 KB | 2.17 MB |
2018-08-08 10:22:28 +00:00
| messenger | 325 KB | 449 KB | 1.05 MB | 2.69 MB |
2018-04-30 00:55:13 +00:00
| twitter | 288 KB | 389 KB | 839 KB | 1.82 MB |
#### Datasets
While all sets are available by default, you may want to include only a single set data to reduce the size of your bundle.
2018-04-30 03:05:55 +00:00
| Set | Size (on disk) |
| --------- | -------------- |
| all | 570 KB |
| apple | 484 KB |
| emojione | 485 KB |
| facebook | 421 KB |
| google | 483 KB |
| messenger | 197 KB |
| twitter | 484 KB |
2018-04-30 00:55:13 +00:00
To use these data files (or any other custom data), use the `NimblePicker` component:
```js
import data from 'emoji-mart/data/messenger.json'
import { NimblePicker } from 'emoji-mart'
< NimblePicker set = 'messenger' data = {data} / >
```
2016-10-27 01:31:56 +00:00
#### Examples of `emoji` object:
2016-07-28 19:25:38 +00:00
```js
2016-06-01 00:53:01 +00:00
{
2016-07-28 19:25:38 +00:00
id: 'smiley',
name: 'Smiling Face with Open Mouth',
2016-06-01 00:53:01 +00:00
colons: ':smiley:',
2017-05-31 19:17:20 +00:00
text: ':)',
2016-06-01 00:53:01 +00:00
emoticons: [
'=)',
'=-)'
],
2017-06-21 18:03:01 +00:00
skin: null,
2016-07-28 19:25:38 +00:00
native: '😃'
}
{
id: 'santa',
name: 'Father Christmas',
colons: ':santa::skin-tone-3:',
2017-05-31 19:17:20 +00:00
text: '',
2016-07-28 19:25:38 +00:00
emoticons: [],
skin: 3,
native: '🎅🏼'
2016-06-01 00:53:01 +00:00
}
2017-05-24 15:36:48 +00:00
{
id: 'octocat',
name: 'Octocat',
2018-09-27 10:25:27 +00:00
colons: ':octocat:',
2017-05-31 19:17:20 +00:00
text: '',
2017-05-24 15:36:48 +00:00
emoticons: [],
custom: true,
2019-03-15 00:39:38 +00:00
imageUrl: 'https://github.githubassets.com/images/icons/emoji/octocat.png'
2017-05-24 15:36:48 +00:00
}
2016-06-01 00:53:01 +00:00
```
2016-07-28 19:25:38 +00:00
### Emoji
```jsx
import { Emoji } from 'emoji-mart'
2017-12-28 09:39:15 +00:00
< Emoji emoji = {{ id: ' santa ' , skin: 3 } } size = {16} / >
< Emoji emoji = ':santa::skin-tone-3:' size = {16} / >
< Emoji emoji = 'santa' set = 'emojione' size = {16} / >
2016-07-28 19:25:38 +00:00
```
| Prop | Required | Default | Description |
| ---- | :------: | ------- | ----------- |
| **emoji** | ✓ | | Either a string or an `emoji` object |
| **size** | ✓ | | The emoji width and height. |
2016-11-01 15:54:25 +00:00
| **native** | | `false` | Renders the native unicode emoji |
2016-07-28 19:25:38 +00:00
| **onClick** | | | Params: `(emoji, event) => {}` |
| **onLeave** | | | Params: `(emoji, event) => {}` |
| **onOver** | | | Params: `(emoji, event) => {}` |
2018-07-31 18:02:56 +00:00
| [**fallback** ](#unsupported-emojis-fallback ) | | | Params: `(emoji, props) => {}` |
2016-10-19 01:21:10 +00:00
| **set** | | `apple` | The emoji set: `'apple', 'google', 'twitter', 'emojione'` |
2016-10-27 01:31:56 +00:00
| **sheetSize** | | `64` | The emoji [sheet size ](#sheet-sizes ): `16, 20, 32, 64` |
2017-09-28 01:30:58 +00:00
| **backgroundImageFn** | | ```((set, sheetSize) => `https://unpkg.com/emoji-datasource@3.0.0/sheet_${set}_${sheetSize}.png` )``` | A Fn that returns that image sheet to use for emojis. Useful for avoiding a request if you have the sheet locally. |
2016-10-27 01:04:05 +00:00
| **skin** | | `1` | Skin color: `1, 2, 3, 4, 5, 6` |
2017-10-07 03:34:06 +00:00
| **tooltip** | | `false` | Show emoji short name when hovering (title) |
2018-01-09 20:18:08 +00:00
| [**html** ](#using-with-dangerouslysetinnerhtml ) | | `false` | Returns an HTML string to use with `dangerouslySetInnerHTML` |
2016-07-28 19:25:38 +00:00
2018-01-09 19:19:57 +00:00
#### Unsupported emojis fallback
Certain sets don’ t support all emojis (i.e. Messenger & Facebook don’ t support `:shrug:` ). By default the Emoji component will not render anything so that the emojis’ don’ t take space in the picker when not available. When using the standalone Emoji component, you can however render anything you want by providing the `fallback` props.
To have the component render `:shrug:` you would need to:
```js
< Emoji
set={'messenger'}
emoji={'shrug'}
size={24}
2018-07-31 18:02:56 +00:00
fallback={(emoji, props) => {
return emoji ? `:${emoji.short_names[0]}:` : props.emoji
2018-01-09 19:19:57 +00:00
}}
/>
```
2018-01-09 20:14:54 +00:00
#### Using with `dangerouslySetInnerHTML`
The Emoji component being a [functional component ](https://medium.com/missive-app/45-faster-react-functional-components-now-3509a668e69f ), you can call it as you would call any function instead of using JSX. Make sure you pass `html: true` for it to return an HTML string.
```js
< span dangerouslySetInnerHTML = {{
__html: Emoji({
html: true
set: 'apple'
emoji: '+1'
size: 24
})
}}>< / span >
```
2018-03-02 19:15:49 +00:00
#### Using with `contentEditable`
Following the `dangerouslySetInnerHTML` example above, make sure the wrapping `span` sets `contenteditable="false"` .
```js
< div contentEditable = {true} >
Looks good to me
< span contentEditable = {false} dangerouslySetInnerHTML = {{
__html: Emoji({
html: true
set: 'apple'
emoji: '+1'
size: 24
})
}}>< / span >
< / div >
```
2017-05-24 15:36:48 +00:00
## Custom emojis
2018-11-30 14:27:55 +00:00
You can provide custom emojis which will show up in their own category. You can either use a single image as imageUrl or use a spritesheet as shown in the second object.
2017-05-24 15:36:48 +00:00
```js
import { Picker } from 'emoji-mart'
const customEmojis = [
{
name: 'Octocat',
short_names: ['octocat'],
2017-05-31 19:17:20 +00:00
text: '',
2017-05-24 15:36:48 +00:00
emoticons: [],
keywords: ['github'],
2019-03-15 00:39:38 +00:00
imageUrl: 'https://github.githubassets.com/images/icons/emoji/octocat.png'
2017-05-24 15:36:48 +00:00
},
2018-11-30 14:27:55 +00:00
{
name: 'Test Flag',
short_names: ['test'],
text: '',
emoticons: [],
keywords: ['test', 'flag'],
spriteUrl: 'https://unpkg.com/emoji-datasource-twitter@4.0.4/img/twitter/sheets-256/64.png',
sheet_x: 1,
sheet_y: 1,
size: 64,
sheetColumns: 52,
sheetRows: 52,
},
2017-05-24 15:36:48 +00:00
]
< Picker custom = {customEmojis} / >
```
2018-06-21 15:56:40 +00:00
## Not Found
You can provide a custom Not Found object which will allow the appearance of the not found search results to change. In this case, we change the default 'sleuth_or_spy' emoji to Octocat when our search finds no results.
```js
import { Picker } from 'emoji-mart'
2019-03-15 00:39:38 +00:00
const notFound = () => < img src = 'https://github.githubassets.com/images/icons/emoji/octocat.png' / >
2018-06-21 15:56:40 +00:00
< Picker notFound = {notFound} / >
```
2018-06-22 21:23:42 +00:00
## Custom icons
You can provide custom icons which will override the default icons.
```js
import { Picker } from 'emoji-mart'
const customIcons = {
categories: {
2019-03-15 00:39:38 +00:00
recent: () => < img src = 'https://github.githubassets.com/images/icons/emoji/octocat.png' / > ,
2018-06-22 21:23:42 +00:00
foods: () => < svg role = "img" viewBox = "0 0 24 24" xmlns = "http://www.w3.org/2000/svg" > < path d = "M0 0l6.084 24H8L1.916 0zM21 5h-4l-1-4H4l3 12h3l1 4h13L21 5zM6.563 3h7.875l2 8H8.563l-2-8zm8.832 10l-2.856 1.904L12.063 13h3.332zM19 13l-1.5-6h1.938l2 8H16l3-2z" / > < / svg > ,
people: () => < svg xmlns = "http://www.w3.org/2000/svg" width = "16" height = "16" viewBox = "0 0 16 16" > < path d = "M3 2l10 6-10 6z" > < / path > < / svg >
}
}
< Picker icons = {customIcons} / >
```
2016-07-28 19:25:38 +00:00
## Headless search
The `Picker` doesn’ t have to be mounted for you to take advantage of the advanced search results.
```js
import { emojiIndex } from 'emoji-mart'
emojiIndex.search('christmas').map((o) => o.native)
// => [🎄, 🎅🏼, 🔔, 🎁, ⛄️, ❄️]
```
2018-04-30 00:55:13 +00:00
### With custom data
```js
import data from 'emoji-mart/datasets/messenger'
import { NimbleEmojiIndex } from 'emoji-mart'
let emojiIndex = new NimbleEmojiIndex(data)
emojiIndex.search('christmas')
```
2017-11-03 00:57:29 +00:00
## Storage
By default EmojiMart will store user chosen skin and frequently used emojis in `localStorage` . That can however be overwritten should you want to store these in your own storage.
```js
import { store } from 'emoji-mart'
store.setHandlers({
getter: (key) => {
// Get from your own storage (sync)
},
setter: (key, value) => {
// Persist in your own storage (can be async)
}
})
```
Possible keys are:
| Key | Value | Description |
2017-11-08 03:04:41 +00:00
| --- | ----- | ----------- |
2017-11-03 00:57:29 +00:00
| skin | `1, 2, 3, 4, 5, 6` | |
| frequently | `{ 'astonished': 11, '+1': 22 }` | An object where the key is the emoji name and the value is the usage count |
| last | 'astonished' | (Optional) Used by `frequently` to be sure the latest clicked emoji will always appear in the “Recent” category |
2016-07-28 19:25:38 +00:00
## Features
### Powerful search
#### Short name, name and keywords
Not only does **Emoji Mart** return more results than most emoji picker, they’ re more accurate and sorted by relevance.
2017-11-08 05:32:03 +00:00
< img width = "338" alt = "summer" src = "https://user-images.githubusercontent.com/436043/32532567-179f1be4-c400-11e7-885e-df6e9b52c665.png" >
2016-07-28 19:25:38 +00:00
#### Emoticons
The only emoji picker that returns emojis when searching for emoticons.
2017-11-08 05:32:03 +00:00
< img width = "338" alt = "emoticons" src = "https://user-images.githubusercontent.com/436043/32532570-1be0dd28-c400-11e7-90cd-f33396277602.png" >
2016-07-28 19:25:38 +00:00
#### Results intersection
For better results, **Emoji Mart** split search into words and only returns results matching both terms.
2017-11-08 05:32:03 +00:00
< img width = "338" alt = "high-five" src = "https://user-images.githubusercontent.com/436043/32532573-1f4a9d1e-c400-11e7-8656-921bc6c09732.png" >
2016-07-28 19:25:38 +00:00
### Fully customizable
#### Anchors color, title and default emoji
2017-11-08 05:32:03 +00:00
< img width = "338" alt = "customizable-color" src = "https://user-images.githubusercontent.com/436043/32532582-302dc9e4-c400-11e7-9b97-f37c447231ca.png" > < br > < img width = "338" alt = "pick-your-emoji" src = "https://user-images.githubusercontent.com/436043/32532585-34546faa-c400-11e7-9c9d-fbbe830d4368.png" >
2016-07-28 19:25:38 +00:00
#### Emojis sizes and length
2017-11-08 05:32:03 +00:00
< img width = "296" alt = "size-and-length" src = "https://user-images.githubusercontent.com/436043/32532590-381f67de-c400-11e7-86f6-328e30d6b116.png" >
2016-07-28 19:25:38 +00:00
#### Default skin color
As the developer, you have control over which skin color is used by default.
2017-11-08 05:32:03 +00:00
< img width = "205" alt = "skins" src = "https://user-images.githubusercontent.com/436043/32532858-0a559560-c402-11e7-8680-f77f780a5a49.png" >
2016-07-28 19:25:38 +00:00
It can however be overwritten as per user preference.
2017-11-08 05:32:03 +00:00
< img width = "98" alt = "customizable-skin" src = "https://user-images.githubusercontent.com/436043/32532883-2c620e7c-c402-11e7-976c-50d32be0566c.png" >
2016-07-28 19:25:38 +00:00
#### Multiple sets supported
2017-05-27 17:52:49 +00:00
Apple / Google / Twitter / EmojiOne / Messenger / Facebook
2016-07-28 19:25:38 +00:00
2017-12-08 21:57:32 +00:00
< img width = "214" alt = "sets" src = "https://user-images.githubusercontent.com/436043/33786868-d4226e60-dc38-11e7-840a-e4cf490f5f4a.png" >
2016-07-28 19:25:38 +00:00
## Not opinionated
**Emoji Mart** doesn’ t automatically insert anything into a text input, nor does it show or hide itself. It simply returns an `emoji` object. It’ s up to the developer to mount/unmount (it’ s fast!) and position the picker. You can use the returned object as props for the `EmojiMart.Emoji` component. You could also use `emoji.colons` to insert text into a textarea or `emoji.native` to use the emoji.
2019-03-17 00:18:06 +00:00
## Usage outside React
**Emoji Mart** can be used with React alternatives such as [Preact ](https://preactjs.com/ ), [Inferno ](https://www.infernojs.org/ ), and [react-lite ](https://github.com/Lucifier129/react-lite ).
Furthermore, you can use it as a [custom element ](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements ) using [remount ](https://github.com/rstacruz/remount ), meaning that you can use it within any JavaScript framework (or vanilla JS).
For an end-to-end example of how to do this, see [emoji-mart-outside-react ](https://github.com/nolanlawson/emoji-mart-outside-react ).
2018-12-18 21:54:21 +00:00
## Optimizing for production
### Modern/ES builds
**Emoji Mart** comes in three flavors:
```
dist
dist-es
dist-modern
```
- `dist` is the standard build with the highest level of compatibility.
- `dist-es` is the same, but uses ES modules for better tree-shaking.
- `dist-modern` removes features not needed in modern evergreen browsers (i.e. latest Chrome, Edge, Firefox, and Safari).
The default builds are `dist` and `dist-es` . (In Webpack, one or the other will be chosen based on your [resolve main fields ](https://webpack.js.org/configuration/resolve/#resolve-mainfields ).)
If you want to use `dist-modern` , you must explicitly import it:
```js
import { Picker } from 'emoji-mart/dist-modern/index.js'
```
Using something like Babel, you can transpile the modern build to suit your own needs.
### Removing prop-types
2018-12-18 19:24:52 +00:00
To remove [prop-types ](https://github.com/facebook/prop-types ) in production, use [babel-plugin-transform-react-remove-prop-types ](https://github.com/oliviertassinari/babel-plugin-transform-react-remove-prop-types ):
```bash
npm install --save-dev babel-plugin-transform-react-remove-prop-types
```
Then add to your `.babelrc` :
```json
"plugins": [
[
"transform-react-remove-prop-types",
{
"removeImport": true,
"additionalLibraries": [
"../../utils/shared-props"
]
}
]
]
```
You'll also need to ensure that Babel is transpiling `emoji-mart` , e.g. [by not excluding `node_modules` in `babel-loader` ](https://github.com/babel/babel-loader#usage ).
2016-07-29 16:29:32 +00:00
## Development
2019-03-08 02:47:45 +00:00
```bash
yarn build
2016-07-29 16:29:32 +00:00
```
2019-03-08 02:47:45 +00:00
In two separate tabs:
```bash
yarn start
yarn storybook
```
The storybook is hosted at `localhost:6006` , and the code will be built on-the-fly.
2016-07-28 19:25:38 +00:00
## 🎩 Hat tips!
2016-07-28 19:35:11 +00:00
Powered by [iamcal/emoji-data ](https://github.com/iamcal/emoji-data ) and inspired by [iamcal/js-emoji ](https://github.com/iamcal/js-emoji ).< br >
2016-07-28 19:25:38 +00:00
🙌🏼 [Cal Henderson](https://github.com/iamcal).
< br > < br >
< div align = "center" >
2017-11-08 05:32:03 +00:00
< a title = "Team email, team chat, team tasks, one app" href = "https://missiveapp.com" > < img width = "64" alt = "Missive | Team email, team chat, team tasks, one app" src = "https://user-images.githubusercontent.com/436043/32532559-0d15ddfc-c400-11e7-8a24-64d0157d0cb0.png" > < / a >
2016-07-28 19:35:11 +00:00
< br > < a title = "Team email, team chat, team tasks, one app" href = "https://missiveapp.com" > Missive< / a > mixes team email and threaded group chat for productive teams.
< br > A single app for all your internal and external communication and a full work management solution.
2016-07-28 19:25:38 +00:00
< / div >