##trix #emojis ๐ฌ๐ง
Add Emojis to Trix Editor for Ruby on Rails
Jeanro Krupa
Jeanro Krupa
3 min read
We added a cool feature at Komin.io it's emojis support for rich text editor Trix
To enable that 3 steps:
To enable that 3 steps:
- ย Add an emojis library like emojis-mart
- Customize Trix toolbar to toggle the emoji picker
- ย When an emojis is selected, add into the editor
Disclaimers:
- โ ๏ธ Our customisation of Trix editor could be fairly optimize ๐ย
- Yes you could do ctrl + cmd + space to toggle the native emojis, but our users are not always tech savy
First lets customize trix toolbar, as mentionned there are probably betters ways to do that. But we basically went into the package to copy the html of the toolbar. We have 2 differents toolbar in our app. One "Long" the other one short for stuff like comments.
Here is a part of the js codeย
import Trix from 'trix' ; import translations from "./trix-translations.json"
if (document.documentElement.lang == "fr" ) { Trix.config.lang = translations[document.documentElement.lang] } Trix.config.toolbar.getDefaultHTML = toolbarDefaultHTML; document.addEventListener("trix-before-initialize", updateToolbars); function toolbarDefaultHTML(shorty) { return shorty === "true" ? short() : long() } function updateToolbars(event) { const toolbars = document.querySelectorAll('trix-toolbar'); toolbars.forEach((toolbar) => (toolbar.innerHTML = Trix.config.toolbar.getDefaultHTML(toolbar.closest('.richtext').dataset.short))); } function long() { const {lang} = Trix.config; return ` <div class=' w-full h-fit overflow-x-auto' data-controller="emoji-picker"> <div class='flex w-fit gap-28 h-12 py-1 px-1 rounded-lg bg-gray-100 items-center mb-4 overflow-auto'> <div class='flex gap-5 h-full overflow-auto'> <div class='relative flex gap-2 h-full items-center justify-start w-fit px-1 py-1'> <button type="button" class="trix-button trix-button--icon trix-button--icon-bold" data-trix-attribute="bold" data-trix-key="b" title="${lang.bold}" tabindex="-1">${lang.bold}</button> <button type="button" class="trix-button trix-button--icon trix-button--icon-italic" data-trix-attribute="italic" data-trix-key="i" title="${lang.italic}" tabindex="-1">${lang.italic}</button> <button type="button" class="trix-button trix-button--icon trix-button--icon-strike" data-trix-attribute="strike" title="${lang.strike}" tabindex="-1">${lang.strike}</button> <button type="button" class="trix-button trix-button--icon trix-button--icon-link" data-trix-attribute="href" data-trix-action="link" data-trix-key="k" title="${lang.link}" tabindex="-1">${lang.link}</button> <div data-controller="dropdown" class="relative"> <button type="button" class="trix-button " data-trix-attribute="emoji" title="${lang.emojis}" data-action="dropdown#toggle click@window->dropdown#hide">๐</button> <div data-emoji-picker-target="pickerContainer" class="hidden transition transform origin-top-right fixed z-50 ml-12" data-dropdown-target="menu"> </div> </div> </div> .... other elements.... </div> </div> `
You can see the `emoji-picker` controller references that we will add later. We use for the the dropdown tailwind-stimulus-components library.
So when we click on the emoji symbol we expect the emoji-picker to be toggled. Let's create the `emoji_picker_controller.js` and add the library:
` yarn add emoji-mart`
`yarn add @emoji-mart/data` optional you can lazy load the data to optimize
When the controller connects:
So when we click on the emoji symbol we expect the emoji-picker to be toggled. Let's create the `emoji_picker_controller.js` and add the library:
` yarn add emoji-mart`
`yarn add @emoji-mart/data` optional you can lazy load the data to optimize
When the controller connects:
- We find the input part of the trix editor to be able to add the selected emojis in it
- We create a Picker object
- When the emoji is selected we insert the emoji where the cursor is.
- That's it
import { Controller } from 'stimulus'; import data from '@emoji-mart/data' import { Picker } from 'emoji-mart' export default class extends Controller { static targets = ['pickerContainer'] connect() { this.trixEditorElement = this.element.closest('trix-toolbar').nextElementSibling this.picker = new Picker({ data: data, parent: this.pickerContainerTarget, onEmojiSelect: (emoji) => { // We insert the emoji at the current cursor position const trixEditor = this.trixEditorElement.editor const currentPosition = trixEditor.getSelectedRange()[0] trixEditor.setSelectedRange([currentPosition, currentPosition]) trixEditor.insertString(emoji.native) } }) } }