ChatBox UX example

사이드바를 클릭하면 채팅방이 열리고, 이에 따라 위치 조정이 됨 vue.js의 transition-group을 이용

HTML

<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<script src="https://unpkg.com/[email protected]"></script>
<div id="app">
  <div>
    <p>ChatBox Order : {{orders}}</p>
    <hr>
    <sidebar :chats="chats" v-on:push-chat="pushChat"></sidebar>
    <hr>
    <chats :chats="openedChats" v-on:close-chat="closeChat"></chats>
  </div>
</div>

<template id="sidebar">
  <div>
    <div v-for="(value, key, index) in chats" @click="openChat(key)" class="sidebar-item">
      {{value}} - {{key}}
    </div>
  </div>
</template>

<template id="chats">
  <transition-group name="list">
    <!-- https://vuejs.org/v2/guide/transitions.html#List-Move-Transitions -->
    <div v-for="(value, key, index) in chats" v-bind:key="key" class="chat-item">
    {{value}} - {{key}} <span @click="close(key)">x</span>
    </div>
  </transition-group>
</template>

CSS

.sidebar-item, .chat-item {
  margin: 10 0px;
  border: 1px solid tomato;
  display: block;
  width: 100px;
  user-select: none;
  cursor: pointer;
}

.chat-item {
 height: 300px;
 display: inline-block;
 margin-right: 10px;
}

.list-enter-active, .list-leave-active {
  transition: all 1s;
}
.list-enter, .list-leave-to /* .list-leave-active for <2.1.8 */ {
  opacity: 0;
  transform: translateY(30px);
}

.list-move {
  transition: transform 1s;
}

JavaScript

var data = {
  "chat1": {
    messages: []
  },
  "chat2": {
    messages: []
  },
  "chat3": {
    messages: []
  },
  "chat4": {
    messages: []
  },
  "chat5": {
    messages: []
  },
  "chat6": {
    messages: []
  }
}


Vue.component('sidebar', {
  template: '#sidebar',
  props: ['chats'],
  methods: {
    openChat: function(key) {
      this.$emit('push-chat', key)
    }
  }
})

Vue.component('chats', {
  template: '#chats',
  props: ['chats'],
  methods: {
  	close: function (key) {
      this.$emit('close-chat', key)
    }
	}
})

new Vue({
  el: '#app',
  data: function() {
    return {
      chats: data,
      orders: []
    }
  },
  computed: {
    openedChats: function() {
      return _.pick(this.chats, this.orders);
    }
  },
  methods: {
    pushChat: function(chat) {
      var indexOfChat = this.orders.indexOf(chat)
      // return if exists and index 0 
      if (indexOfChat === 0) {
      	return;
			}
    	// push if not exists 
      if (indexOfChat === -1) {
        this.orders.push(chat)
        indexOfChat = this.orders.indexOf(chat)
      }

      // move index 0 if opened chat exists
      var to = 0;
      var from = indexOfChat
      this.orders.splice(to, 0, this.orders.splice(from, 1)[0]);
    },
    closeChat: function (chatKey) {
    	var targetIndex = this.orders.indexOf(chatKey)
      this.orders.splice(targetIndex, 1)
    }
  }
})