Search code examples
javascriptreactjsmixinscompositionreusability

How to compose react-textarea-autosize with react-mentions


It's now clear to me that mixins and inheritance are generally considered bad and composition is the way to go, this from:

https://medium.com/@dan_abramov/mixins-are-dead-long-live-higher-order-components-94a0d2f9e750

https://facebook.github.io/react/blog/2016/07/13/mixins-considered-harmful.html


Now, what to do when you find two components that specialize in different things and you want a component that is the result of both behaviors mixed? For instance, I want a textarea that both grows automatically when text goes beyond initial rows, and allow mentions inside (aka. mix react-mentions with react-textarea-autosize)

  • How am I supposed to compose both in a way that works?
  • Am I supposed to code a brand new component copying/merging the inner code from both components?
  • What's the ReactJs way to compose in such scenarios?

Solution

  • I came across the same issue. With react-mention you don't have to use the react-text-autosize as you can achieve the same behavior with css which can auto grow the textarea generated. Consider following example

    <MentionsInput
       value={content}
       placeholder="Add a comment"
       onChange={this.onChange}
       className="mentionWrapper">
            <Mention
              trigger="@"
              data={users}
              className="mentionedFriend"
              displayTransform={(id, display) => `@${display}`}
            />
    </MentionsInput>
    

    For this i've used the following styles

    .mentionWrapper {
      width: 100%;
      background: transparent;
      font-size: 0.9rem;
      color: #a9b5c4;
     }
     .mentionWrapper .mentionWrapper__control {
       border-radius: 25px;
       border: 1px solid #3a546f;
       min-height: 45px;
      }
    
     .mentionWrapper .mentionWrapper__control .mentionWrapper__highlighter {
      padding: 0.7rem 1rem;
     }
    
     .mentionWrapper .mentionWrapper__control .mentionWrapper__input {
      padding: 0.7rem 1rem;
      outline: 0;
      border: 0;
      resize: none;
      outline: none;
      font-size: 0.9rem;
      color: #7288a3;
      border-color: #3a546f;
      overflow: hidden;
     }
    
    .mentionWrapper .mentionWrapper__control .mentionWrapper__input::placeholder {
      color: #7288a3;
     }
    
    .mentionWrapper__suggestions {
      background-color: rgba(0, 0, 0, 0.6) !important;
      padding: 10px;
      -webkit-box-shadow: 0px 0px 11px 0px rgba(0, 0, 0, 0.75);
     -moz-box-shadow: 0px 0px 11px 0px rgba(0, 0, 0, 0.75);
     box-shadow: 0px 0px 11px 0px rgba(0, 0, 0, 0.75);
     border-radius: 0.8rem;
     }
    
    .mentionWrapper__suggestions .mentionWrapper__suggestions__list {
      font-size: 14px;
     }
    
    .mentionWrapper
    .mentionWrapper__suggestions
    .mentionWrapper__suggestions__item--focused {
     color: #ffffff;
     border-bottom: 1px solid #3a546f;
     font-weight: 600;
    }
    
    .mentionedFriend {
      color: #7288a3;
      text-decoration: underline;
     }
    

    Key point here is that i've applied a min-height of 45px to "control" div which is append by react-mention package. By doing so you will get the attached result. enter image description here