<div id="app">
<form id="book-search" @submit.prevent="search">
<label>
<span>Search for a book</span>
<input type="text" v-model:trim="searchTerm" placeholder="⌕">
</label>
<button type="submit">Search</button>
</form>
<ol class="search-results">
<li class="search-result" v-for="book in searchResults.items">
<img :src="'http://books.google.com/books/content?id=' + book.id + '&printsec=frontcover&img=1&zoom=1&source=gbs_api'" class="search-result--thumbnail">
<ul class="search-result--info">
<li class="search-result--title">{{ book.volumeInfo.title }}</li>
<li v-if="book.volumeInfo.authors" class="search-result--authors">
by {{ bookAuthors(book) }}
</li>
<li v-if="book.volumeInfo.publishedDate" class="search-result--published">
<span>Published </span> {{ book.volumeInfo.publishedDate }}
</li>
</ul>
</li>
</ol>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/106403/allthebooks%5B1%5D.jpg" id="all-the-books" v-if="searchResults.items">
</div>
$smallScreen: 550px;
$largeScreen: 1600px;
@function between($to, $from, $toWidth, $fromWidth) {
$slope: ($to - $from) / ($toWidth - $fromWidth);
$base: $from - $slope * $fromWidth;
@return calc(#{$base} + #{100vw * $slope});
}
@mixin between($property, $to, $from, $toWidth: $smallScreen, $fromWidth: $largeScreen) {
#{$property}: $to;
@media (min-width: $toWidth) {
#{$property}: between($to, $from, $smallScreen, $largeScreen);
}
@media (min-width: $fromWidth) {
#{$property}: $from;
}
}
:root {
@include between(font-size, 15px, 24px);
}
*,*:before,*:after { box-sizing: inherit }
html {
box-sizing: border-box;
height: 100%;
display: flex;
}
body {
margin: auto;
background-color: #faf7f6;
color: #805466;
}
#app {
padding: 5%;
}
#book-search {
display: flex;
align-items: flex-end;
}
label span {
display: block;
font-size: .9rem;
font-weight: bold;
}
input {
padding: .2rem .5rem;
border-radius: .25rem;
border: 2px solid #f3edeb;
margin-top: .25rem;
margin-right: .25rem;
box-shadow: 0 .4rem 1rem -.4rem #d4b1a5;
}
button {
background: rebeccapurple;
position: relative;
color: white;
border: none;
padding: 0 .75rem;
border-radius: .25rem;
font-size: .6rem;
line-height: 2.8;
text-transform: uppercase;
box-shadow: 0 .4rem 1rem -.4rem purple;
}
.search-results {
padding-left: 0;
li + li {
margin-top: .5rem
}
}
.search-result {
background-color: white;
position: relative;
border: 2px solid #f3edeb;
border-radius: .25rem;
overflow: hidden;
box-shadow: 0 1rem 1rem -.75rem #dfc8c0;
display: flex;
align-items: center;
}
.search-result--thumbnail {
flex: none;
width: 15%;
width: 4rem;
height: auto;
align-self: flex-start;
}
.search-result--info {
display: flex;
height: 100%;
flex-direction: column;
justify-content: space-around;
padding: .5rem;
list-style: none;
}
.search-result--title {
font-size: 1rem;
font-weight: bold;
color: #65002a;
}
.search-result--authors {
font-size: .9rem
}
.search-result--published {
font-size: .8rem;
}
#all-the-books {
width: 100%;
}
View Compiled
new Vue({
el: '#app',
data() {
return {
searchTerm: '',
searchResults: [],
}
},
methods: {
search() {
axios.get(`https://www.googleapis.com/books/v1/volumes?q=` + this.searchTerm)
.then(response => {
this.searchResults = response.data
})
.catch(e => {
console.log(e)
})
},
bookAuthors(book) {
let authors = book.volumeInfo.authors;
if (authors.length < 3) {
authors = authors.join(' and ')
}
else if (authors.length > 2) {
let lastAuthor = ' and ' + authors.slice(-1);
authors.pop()
authors = authors.join(', ')
authors += lastAuthor
}
return authors
}
}
});
View Compiled
This Pen doesn't use any external CSS resources.