Vue list animations - Step 2

by Julien1138

HTML

<script src="https://code.jquery.com/jquery-3.4.1.slim.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.css">
<div id="app">
  <div class="row p-2">
    <div class="col-6">
      <h2>List</h2>
      <transition-group class="list-group" name="fruit-list" tag="ul">
        <li class="list-group-item fruit-list-item" v-for="item in items" :key="item.id">
          <div class="d-flex align-items-center">
           <div>
            {{ item.name }}
           </div>
           <div class="ml-auto">
            <button type="button" class="btn btn-danger btn-sm">
              X
            </button>
           </div>
          </div>
        </li>
      </transition-group>
      <h3>Number of items: {{ items.length }}</h3>
    </div>
    <div class="col-6">
      <h2>Table</h2>
      <table class="table mb-0">
        <thead>
          <tr>
            <th scope="col">Fruit</th>
            <th scope="col">Quantity</th>
          </tr>
        </thead>
        <tbody name="fruit-table" is="transition-group">
          <tr class="fruit-table-item" v-for="item in items" :key="item.id">
            <td scope="row">
                {{ item.name }}
            </td>
            <td>
                {{ item.quantity }}
            </td>
          </tr>
        </tbody>
      </table>
      <h3>Total quantity: {{ totalQuantity }}</h3>
    </div>
  </div>
</div>

CSS

.fruit-list-item {
  transition: all 1s;
}
.fruit-list-enter {
  max-height: 0px !important;
  padding-top: 0px !important;
  padding-bottom: 0px !important;
  overflow: hidden;
}
.fruit-list-enter-to {
  max-height: 80px;
}

.fruit-table-item {
  transition: all 1s;
}
.fruit-table-item > * {
  transition: all 1s;
  overflow: hidden;
}
.fruit-table-enter {
  line-height: 0 !important;
}
.fruit-table-enter > * {
  padding-top: 0px !important;
  padding-bottom: 0px !important;
}
.fruit-table-enter-to {
  line-height: 1.5;
}

Vue

new Vue({
  el: "#app",
  
  data() {
  	return {
      items: [
        {
          id: 1,
          name: "Bananas",
          quantity: 5
        }, {
          id: 2,
          name: "Apples",
          quantity: 3
        }, {
          id: 4,
          name: "Oranges",
          quantity: 1
        }, {
          id: 5,
          name: "Stawberries",
          quantity: 25
        },
      ]
    }
  },
  
  computed: {
  	totalQuantity() {
    	return this.items.reduce((total, item) => {
      	return total + item.quantity
      }, 0)
    },
  },
  
  mounted() {
  	this.addItem()
  },
  
  methods: {
  	addItem() {
    	this.items.splice(2, 0, {
      	id: 3,
      	name: "Kiwis",
      	quantity: 8
      })
      setTimeout(() => {
      	this.moveItems()
      }, 2000)
    },
    moveItems() {
      this.items = this.items.reverse()
      setTimeout(() => {
      	this.removeItem()
      }, 2000)
    },
    removeItem() {
      this.items.splice(2, 1)
      setTimeout(() => {
      	this.addItem()
      }, 2000)
    }
  }
})