Skip to content
Home » All Blogs » Shopping Cart UI

Shopping Cart UI

When creating an online shopping cart, Vue JS can be used to create a representation of the shopping cart. Vue JS is a popular JavaScript framework that enables developers to build interactive and user-friendly applications. Using Vue JS for the shopping cart, developers can create an easy-to-use and responsive interface that makes it easy for customers to browse, add products, and go to finish. Additionally, Vue’s reactive data binding ensures that all shopping cart updates are mirrored in real time, giving customers exactly what they want. Overall, Vue JS is a powerful tool for developing compelling and powerful shopping cart experiences.

Demo

I would recommend you don’t just copy and paste the code, just look at the code and type by understanding it.

VueJS – Code

<template lang="pug">
.wrapper
  .screen.-left
    .app-bar
     img.logo(src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/1315882/pngwave.png")
    .title Picked items
    .shop-items
      .item(v-for="item in shopItems")
        .item-block
          .image-area(:style="{backgroundColor: item.color}")
            img.image(:src="item.image")
          .name {{ item.name }}
          .description {{ item.description }}
          .bottom-area
            .price ${{ item.price }}
            .button(@click="addToCart(item)" :ref="'addButton' + item.id" :class="{'-active': item.inCart}")
              transition(name="buttonText" mode="out-in")
                p(v-if="!item.inCart") ADD TO CART
                .cover(v-else)
                  .check
  .screen.-right(ref="cartItems")
    .app-bar
     img.logo(src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/1315882/pngwave.png")
    .title Your cart
    transition(name="noContent")
      .no-content(v-if="$data.cartItems.length === 0")
        p.text Your cart is empty.
    .cart-items
      transition-group(name="cartList" tag="div")
        .cart-item(v-for="item in $data.cartItems" :key="item.id")
          .left
            .cart-image
              .image-wrapper
                img.image(:src="item.image")
          .right
            .name {{item.name}}
            .price ${{item.price}}
            .count
              .button(@click="decrement(item)") <
              .number {{item.count}}
              .button(@click="increment(item)") >
    
</template>

<script>
export default {
  data() {
    return {
      shopItems: [],
      cartItems: []
    };
  },
  mounted: function () {
    axios
      .get("https://s3-us-west-2.amazonaws.com/s.cdpn.io/1315882/shoes.json")
      .then((res) => {
        this.$data.shopItems = res.data.shoes;
      });
  },
  methods: {
    addToCart(item) {
      if (!item.inCart) {
        item.inCart = true;
        const newItem = Object.assign({}, item, { count: 1 });
        this.$data.cartItems.push(newItem);

        const animationTarget = this.$refs[`addButton${item.id}`];
        gsap.to(animationTarget, {
          width: 46,
          duration: 0.8,
          ease: "power4"
        });
      }
      this.$nextTick(() => {
        this.$refs.cartItems.scrollTop = this.$refs.cartItems.scrollHeight;
      });
    },

    decrement(item) {
      item.count--;
      const targetShopItem = this.$data.shopItems.find(
        (shopItem) => shopItem.id === item.id
      );

      this.$nextTick(function () {
        if (item.count === 0) {
          const animationTarget = this.$refs[`addButton${targetShopItem.id}`];
          gsap.to(animationTarget, {
            width: 136,
            duration: 0.8,
            ease: "power4"
          });
          targetShopItem.inCart = false;
          const targetIndex = this.$data.cartItems.findIndex(
            (cartItem) => cartItem.id === item.id
          );
          this.$data.cartItems.splice(targetIndex, 1);
        }
      });
    },

    increment(item) {
      item.count++;
    }
  }
};
</script>

<style lang="scss">
$white: #fff;
$yellow: #f6c90e;
$black: #303841;

body {
  font-family: "Rubik", sans-serif;
  color: $black;
}

.wrapper {
  height: 100vh;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;
  flex-wrap: wrap;
  padding: 40px 20px;
  max-width: 720px;
  margin: 0 auto;

  &::before {
    content: "";
    display: block;
    position: fixed;
    width: 300%;
    height: 100%;
    top: 50%;
    left: 50%;
    border-radius: 100%;
    transform: translateX(-50%) skewY(-8deg);
    background-color: $yellow;
    z-index: -1;
    animation: wave 8s ease-in-out infinite alternate;
  }

  @keyframes wave {
    0% {
      transform: translateX(-50%) skew(0deg, -8deg);
    }

    100% {
      transform: translateX(-30%) skew(8deg, -4deg);
    }
  }
}

.screen {
  background-color: $white;
  box-sizing: border-box;
  width: 340px;
  height: 600px;
  box-shadow: 0 3.2px 2.2px rgba(0, 0, 0, 0.02),
    0 7px 5.4px rgba(0, 0, 0, 0.028), 0 12.1px 10.1px rgba(0, 0, 0, 0.035),
    0 19.8px 18.1px rgba(0, 0, 0, 0.042), 0 34.7px 33.8px rgba(0, 0, 0, 0.05),
    0 81px 81px rgba(0, 0, 0, 0.07);
  border-radius: 30px;
  overflow-y: scroll;
  padding: 0 28px;
  position: relative;
  margin-bottom: 20px;

  &::before {
    content: "";
    display: block;
    position: absolute;
    width: 300px;
    height: 300px;
    border-radius: 100%;
    background-color: $yellow;
    top: -20%;
    left: -50%;
    z-index: 0;
  }

  &::-webkit-scrollbar {
    display: none;
  }

  > .title {
    font-size: 24px;
    font-weight: bold;
    margin: 20px 0;
    position: relative;
  }
}

.app-bar {
  padding: 12px 0;
  position: relative;

  > .logo {
    display: block;
    width: 50px;
  }
}

.shop-items {
  position: relative;
}

.item-block {
  padding: 40px 0 70px;

  &:first-child {
    padding-top: 0;
  }

  > .image-area {
    border-radius: 30px;
    height: 380px;
    display: flex;
    align-items: center;
    overflow: hidden;

    > .image {
      display: block;
      width: 100%;
      filter: drop-shadow(0 30px 20px rgba(0, 0, 0, 0.2));
      transform: rotate(-24deg);
      margin-left: -16px;
    }
  }

  > .name {
    font-size: 20px;
    font-weight: bold;
    margin: 26px 0 20px;
    line-height: 1.5;
  }

  > .description {
    font-size: 13px;
    color: #777;
    line-height: 1.8;
    margin-bottom: 20px;
  }

  > .bottom-area {
    display: flex;
    justify-content: space-between;
    align-items: center;

    > .price {
      font-size: 18px;
      font-weight: bold;
    }

    > .button {
      cursor: pointer;
      background-color: $yellow;
      font-weight: bold;
      font-size: 14px;
      box-sizing: border-box;
      height: 46px;
      padding: 16px 20px;
      border-radius: 100px;
      box-shadow: 0 3px 6px rgba(0, 0, 0, 0.2);
      transition: box-shadow 0.4s, background-color 0.2s;
      user-select: none;
      white-space: nowrap;
      position: relative;
      display: flex;
      align-items: center;
      overflow: hidden;

      &:hover {
        background-color: lighten($yellow, 10%);
        box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
      }

      &.-active {
        pointer-events: none;
        cursor: default;
      }

      > .cover {
        width: 16px;
        height: 16px;
        position: absolute;
        display: flex;
        justify-content: center;
        align-items: center;

        > .check {
          width: 100%;
          height: 100%;
          transform: translate(-100%, -73%) rotate(-45deg);
          position: absolute;
          left: 50%;
          top: 50%;

          &::before,
          &::after {
            content: "";
            display: block;
            background-color: $black;
            position: absolute;
            left: 0;
            bottom: 0;
            border-radius: 10px;
          }

          &::before {
            width: 3px;
            height: 50%;
          }

          &::after {
            width: 100%;
            height: 3px;
          }
        }
      }
    }
  }
}

.cart-items {
  position: relative;
}

.no-content {
  position: relative;

  > .text {
    font-size: 14px;
  }
}

.cart-item {
  display: flex;
  padding: 20px 0;

  > .right {
    > .name {
      font-size: 14px;
      font-weight: bold;
      line-height: 1.5;
      margin-bottom: 10px;
    }

    > .price {
      font-size: 20px;
      font-weight: bold;
      margin-bottom: 16px;
    }

    > .count {
      display: flex;
      align-items: center;

      > .number {
        font-size: 14px;
        margin: 0 14px;
        width: 20px;
        text-align: center;
      }

      .button {
        cursor: pointer;
        width: 28px;
        height: 28px;
        border-radius: 100%;
        background-color: #eee;
        font-size: 16px;
        font-weight: bold;
        display: flex;
        justify-content: center;
        align-items: center;
        transition: 0.2s;
        user-select: none;

        &:hover {
          background-color: #ddd;
        }
      }
    }
  }
}

.cart-image {
  width: 90px;
  height: 90px;
  border-radius: 100%;
  background-color: #eee;
  margin-right: 34px;

  > .image-wrapper {
    > .image {
      display: block;
      width: 140%;
      transform: rotate(-28deg) translateY(-40px);
      filter: drop-shadow(0 30px 20px rgba(0, 0, 0, 0.2));
    }
  }
}

.buttonText-leave-active,
.buttonText-enter-active {
  transition: opacity 0.2s, top 0.35s;
}
.buttonText-leave-to,
.buttonText-enter {
  opacity: 0;
}

.cartList-enter-active {
  transition: all 2s;

  > .right {
    > .name,
    > .price {
      transition: 0.4s;
    }

    > .name {
      transition-delay: 0.7s;
    }

    > .price {
      transition-delay: 0.85s;
    }

    > .count {
      transition: opacity 0.4s;
      transition-delay: 1s;
    }
  }

  .cart-image {
    transition: 0.5s cubic-bezier(0.79, 0.01, 0.22, 1);

    > .image-wrapper {
      transition: 0.5s cubic-bezier(0.79, 0.01, 0.22, 1) 0.1s;
    }
  }
}

.cartList {
  &-enter {
    > .right {
      > .name,
      > .price {
        opacity: 0;
        transform: translateX(30px);
      }

      .count {
        opacity: 0;
      }
    }

    .cart-image {
      transform: scale(0);

      > .image-wrapper {
        transform: scale(0);
      }
    }
  }

  &-leave-active {
    transition: 0.7s cubic-bezier(0.79, 0.01, 0.22, 1);
    position: absolute;
  }

  &-leave-to {
    transform: scale(0);
    opacity: 0;
  }

  &-move {
    transition: 0.7s cubic-bezier(0.79, 0.01, 0.22, 1);
  }
}

.noContent {
  &-enter-active,
  &-leave-active {
    transition: opacity 0.5s;
    position: absolute;
  }

  &-enter,
  &-leave-to {
    opacity: 0;
  }
}
</style>

Written By : @anoncodes

Code Credit :@ma-ro

Hope you find this post helpful 💖


Related Post

Leave a Reply

Your email address will not be published. Required fields are marked *

www.000webhost.com