Edit in JSFiddle

const Balloon = {
  template: `<div class="conversation-balloon" :class="speaker">
  <div class="avatar">
    <img src="https://avatars3.githubusercontent.com/u/15647466?v=3&s=88">
    <p class="name">{{ name }}</p>
  </div>
  <p class="message">{{ message }}</p>
</div>`,
  props: {
    name: {
      type: String,
      required: true
    },
    speaker: {
      type: String,
      required: true,
      validator: value => {
        return ['my', 'other'].includes(value);
      }
    },
    message: {
      type: String,
      required: true
    }
  }
};

const ChatForm = {
  template: `<div class="chat-form">
  <div class="form-container">
    <input type="text" class="message" v-model="message">
    <button class="submit" @click="submit">送信</button>
  </div>
</div>`,
  props: {
    applyEvent: {
      type: String,
      required: true
    }
  },
  data () {
    return {
      message: ''
    }
  },
  methods: {
    submit () {
      this.$emit(this.applyEvent, this.message)
      this.message = '';
    }
  }
};

const app = new Vue({
  el: '#app',
  components: {
    balloon: Balloon,
    chatForm: ChatForm
  },
  data () {
    return {
    	chatLogs: [
         { name: 'わたしだよ', speaker: 'my', message: 'hello'.repeat(10) },
         { name: 'bot', speaker: 'other', message: 'hello world' }
      ]
    }
  },
  methods: {
    submit (value) {
      this.chatLogs.push({
        name: 'わたしだよ',
        speaker: 'my',
        message: value
      });
      
      this.botSubmit();
      this.scrollDown();
    },
    botSubmit () {
      setTimeout(() => {
        this.chatLogs.push({
          name: 'bot',
          speaker: 'other',
          message: 'hello world'
        });
        
        this.scrollDown();
      }, 1000);
    },
    scrollDown () {
      const target = this.$el.querySelector('.chat-timeline');
      setTimeout(() => {
      	const height = target.scrollHeight - target.offsetHeight;
        target.scrollTop += 10;

        if (height <= target.scrollTop) {
          return;
        } else {
          this.scrollDown();
        }
      }, 0);
    }
  }
});
<div id="app">
  <main class="main-container">
    <div class="chat-timeline">
      <balloon 
        v-for="chat in chatLogs"
        :speaker="chat.speaker"
        :name="chat.name"
        :message="chat.message">
      </balloon>
    </div>
    <chat-form
      @submit-message="submit"
      apply-event="submit-message">
    </chat-form>
  </main>
</div>
/* base */
body {
  font-size: 62.5%;
  box-sizing: border-box;
}
button {
  background-color: transparent;
  border: none;
  cursor: pointer;
  outline: none;
  padding: 0;
  appearance: none;
}

/* timeline */
$tl-background-color: #88A4D4;
$my-balloon-color: #85FF49;
$other-balloon-color: #FFFFFF;

.chat-timeline {
  position: fixed;
  top: 0;
  bottom: 40px;
  left: 0;
  right: 0;
  
  min-width: 480px;
  padding: 30px;
  
  background-color: $tl-background-color;
  overflow-y: auto;

  display: flex;
  flex-direction: column;

  > .conversation-balloon {
    margin-bottom: 30px;
  }
}

.conversation-balloon {
  &.my {
    text-align: right;
    > .avatar {
      float: right;
    }
    > .message {
      margin-right: 20px;
      background-color: $my-balloon-color;
      text-align: left;

      &::before {
        right: -20px;
        transform: rotate(-25deg);
        border-left: 18px solid $my-balloon-color;
      }
    }
  }

  &.other {
    text-align: left;
    > .avatar {
      float: left;
    }
    > .message {
      margin-left: 20px;
      background-color: $other-balloon-color;
      
      &::before {
        left: -20px;
        transform: rotate(25deg);
        border-right: 18px solid $other-balloon-color;
      }
    }
  }
  
  >.avatar {
    width: 80px;
    
    // floatは各コンポーネントで定義
    &::after {
      clear: both;
    }
    
    > img {
      display: block;
      margin: 0 auto;
      width: 60px;
      height: 60px;
      border-radius: 50%;
      
      margin-bottom: 5px;
    }
    > .name {
      width: 100%;
      text-align: center;
      color: white;
      font-size: 0.8rem;
      word-wrap: break-word;
    }
  }
  
  > .message {
    display: inline-block;
    max-width: 280px;
    padding: 10px 30px;
    border-radius: 30px;
    font-size: 1.3rem;
    min-height: 30px;
    word-wrap: break-word;
    
    position: relative;
    
    &::before {
      content: '';
      display: block;
      position: absolute;
      top: 5px;
      border: 8px solid transparent;
      // left/right, border-right, tranform は各コンポーネントで定義
    }
  }
}

/* form */
.chat-form {
  position: fixed;
  bottom: 0;
  right: 0;
  left: 0;

  background-color: white;
}
.form-container {
  position: relative;
  height: 40px;
  > .message {
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 80px;
    width: 100%;
    
    font-size: 1.3rem;
    padding: 0 20px;
  }
  > .submit {
    position: absolute;
    top: 0;
    bottom: 0;
    right: 0;
    
    width: 80px;
    text-align: center;
    background-color: #4F83E1;
    color: white;
    font-size: 1.6rem;
  }
}