JSFiddle - React, Tailwind, and code Playground
by zhouyulong
HTML
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
<div id="app">
<div class="header">
<h2>Comics</h2>
<div>
<button @click="showCart = !showCart" v-show="!verified">
{{ items.length + (items.length > 1 || items.length === 0 ? " items" : " item") }}
</button>
</div>
</div>
<div class="cart" v-show="showCart">
<div v-show="items.length > 0">
<ul>
<li v-for="item in items" transition="fade">
<p><strong>{{ item.quantity }}</strong> - {{ item.name }} <i class="fa fa-trash" @click="removeFromCart(item)"></i></p>
</li>
</ul>
<div><button @click="verified = true, showCart = false">Check out</button></div>
</div>
<div v-show="items.length === 0">
<p>Your cart is empty!</p>
</div>
</div>
<div class="container">
<div class="shop" v-show="!verified">
<h3>New Arrivals</h3>
<ul>
<li v-for="item in shop">
<div>
<h5>{{ item.name }}</h5>
<p>${{ item.price }}</p>
<button @click="addToCart(item)">Add to cart</button>
</div>
</li>
</ul>
</div>
<div class="checkout" v-show="verified">
<h3>Your Cart</h3>
<h5 v-for="item in items"><strong>{{ item.quantity }}</strong> - {{ item.name }}<span>${{ item.price * item.quantity }}</span></h5>
<hr />
<div class="row">
<div class="u-pull-right">
<h5>Total: <span>{{ total | currency }}</span></h5>
<button>Looks Good</button>
</div>
</div>
</div>
</div>
</div>
SCSS
body {
height: 100%;
background: linear-gradient(to top, #FF6B83, lighten(#FF6B83, 15%)) no-repeat fixed;
}
#app {
font-family: 'Roboto Slab', serif;
}
.header {
height: 80px;
h2 {
color: #fff;
font-family: 'Rock Salt';
float: left;
font-weight: bolder;
margin: 10px 20px;
}
button {
border: 0;
background: #FFDBE0;
transition: all .1s ease-out;
&:hover {
background: darken(#FFDBE0, 2%);
}
}
div {
float: right;
display: inline;
margin: 10px;
}
}
li {
list-style: none;
}
.fa {
cursor: pointer;
margin-left: 5px;
}
.fade-transition {
transition: all 0.2s ease-out;
}
.fade-enter, .fade-leave {
opacity: 0;
}
.cart {
> div {
z-index: 100;
background: #fff;
padding: 20px 30px;
position: absolute;
right: 30px;
box-shadow: 2px 2px 6px 0 rgba(0, 0, 0, 0.3);
div {
text-align: center;
}
}
ul, li, p {
margin-bottom: 0;
}
button {
margin: 20px 0 10px;
text-transform: uppercase;
text-decoration: none;
font-weight: bold;
letter-spacing: 2px;
}
}
.shop {
h3 {
position: absolute;
top: -85px;
left: -30px;
color: rgba(255, 255, 255, 0.3);
font-family: sans-serif;
font-size: 4em;
font-weight: bold;
letter-spacing: -2px;
}
ul {
margin-top: 90px;
}
li div {
padding: 30px;
background: #fff;
margin-bottom: 20px;
box-shadow: 1px 1px 6px 0 rgba(0, 0, 0, 0.3);
}
button {
color: white;
border: 0;
background: #00ADB5;
margin: 0;
transition: all .1s ease-out;
&:hover {
background: darken(#00ADB5, 5%)
}
}
}
.checkout {
background: #fff;
box-shadow: 1px 1px 6px 0 rgba(0, 0, 0, 0.3);
margin-top: 90px;
padding: 50px 60px;
h3 {
position: absolute;
top: -85px;
left: -30px;
color: rgba(255, 255, 255, 0.3);
font-family: sans-serif;
font-size: 4em;
font-weight: bold;
letter-spacing: -2px;
}
...
JavaScript
const shop = [
{
name: "One-Punch Man, Vol. 5",
price: 10.02,
quantity: 0
},
{
name: "Batman '66, Vol. 5",
price: 9.98,
quantity: 0
},
{
name: "Dragon Ball Freeza Arc, Vol. 1",
price: 15.98,
quantity: 0
},
{
name: "Uzumaki: Spiral into Horror, Vol. 1",
price: 4.84,
quantity: 0
},
{
name: "Superman: Red Son (New Edition)",
price: 10.93,
quantity: 0
}
];
const vm = new Vue({
el: "#app",
data: {
items: [],
shop: shop,
showCart: false,
verified: false
},
computed: {
total() {
var total = 0;
for(var i = 0; i < this.items.length; i++) {
total += this.items[i].price;
}
return total;
}
},
methods: {
addToCart(item) {
item.quantity += 1;
this.items.push(item);
},
removeFromCart(item) {
item.quantity -= 1;
this.items.splice(this.items.indexOf(item), 1);
}
}
});