How to extend theme of draft-js-emoji-plugin

1.4k views Asked by At

I need to extend only several CSS rules in draft-js-emoji-plugin.

Documented way is to pass theme object to configuration:

const theme = {
  emojiSelectButton: 'someclassname'
};
const emojiPlugin = createEmojiPlugin({theme});

Unfortunately, this overwrites entire theme classnames instead of adding single one. Based on comments in the code this behavior is by design:

// Styles are overwritten instead of merged as merging causes a lot of confusion.
//
// Why? Because when merging a developer needs to know all of the underlying
// styles which needs a deep dive into the code. Merging also makes it prone to
// errors when upgrading as basically every styling change would become a major
// breaking change. 1px of an increased padding can break a whole layout.

In related issue developers suggested to import draft-js-emoji-plugin/lib/plugin.css and extend it in code. Anyway, each classname in this file has suffixes (CSS modules) and they might be changed so it's reliable.

I don't know how can I apply several fixes without coping entire theme.

2

There are 2 answers

1
prince On

a better method would be to import {defaultTheme} from 'draft-js-emoji-plugin' and then extend it as below:

import emojiPlugin, { defaultTheme } from 'draft-js-emoji-plugin';

// say i need to extend the emojiSelectPopover's css then.

defaultTheme.emojiSelectPopover = defaultTheme.emojiSelectPopover + " own-class"

// own class is a class with your required enhanced css. this helps in preserving the old css.

const emojiPlugin  = createEmojiPlugin({
    theme : defaultTheme
})

and hence use the plugin as you like.

0
Saulo Furuta On

It's nice to have such flexibility, but it really is a pain to rewrite all classes. What I did was to extract all class names to an object, and with styled-components, interpolated the classNames to the css definition. This way you can extend whatever you want, without worrying about styling a suffixed class (and it changing when they bump a version) In this gist I've just copied all styles in v2.1.1 of draft-js-emoji-plugin

const theme = {
  emoji: 'my-emoji',
  emojiSuggestions: 'my-emojiSuggestions',
  emojiSuggestionsEntry: 'my-emojiSuggestionsEntry',
  // ...
  emojiSelect: 'emojiSelect',
  emojiSelectButton: 'emojiSelectButton',
  emojiSelectButtonPressed: 'emojiSelectButtonPressed',
}

const StyledEmojiSelectWrapper = styled.div`
  .${theme.emojiSelect} {
      display: inline-block;
    }
  .${theme.emojiSelectButton}, .${theme.emojiSelectButtonPressed} {
    margin: 0;
    padding: 0;
    width: 2.5em;
    height: 1.5em;
    box-sizing: border-box;
    line-height: 1.2em;
    font-size: 1.5em;
    color: #888;
    background: #fff;
    border: 1px solid #ddd;
    border-radius: 1.5em;
    cursor: pointer;
  }
  .${theme.emojiSelectButton}:focus, .${theme.emojiSelectButtonPressed}:focus {
    outline: 0;
    /* reset for :focus */
  }
  // ...
`

export const GlobalStyleForEmojiSelect = createGlobalStyle`
  .${theme.emoji} {
    background-position: center;
    //...
  }

export default (props) => (
  <StyledEmojiSelectWrapper>
    <GlobalStyleForEmojiSelect />
    <EmojiSelect /> // lib button component
  </StyledEmojiSelectWrapper>
)