HTML
<div
class="content"
x-data
@colorchange="$el.style.backgroundColor = $event.detail.hex"
>
<div
class="card"
x-data="{ currentTab: 'Colors' }"
@tab-change="currentTab = $event.detail"
>
<div class="tabs" x-data="tabs()">
<template x-for="tab in items" :key="tab">
<button
class="tab"
x-bind:class="{ 'selected': tab === current }"
x-text="tab"
x-on:click="
changeTab(tab)
$dispatch('tab-change', tab)
"
></button>
</template>
</div>
<div x-show="currentTab === 'Colors'" class="card-content">
<div x-data="colors()">
<h2 class="title" x-bind:style="'color:' + getCurrentColor().hex">
Pick a color
</h2>
<div class="colors">
<template x-for="color in list" :key="color.name">
<!-- Template Literals are allowed to use with x-bindings -->
<div
class="color"
x-bind:style="`background-color: ${color.hex}`"
@click="
changeColor(color.name)
$dispatch('colorchange', color)
"
></div>
</template>
</div>
</div>
</div>
<div x-show="currentTab === 'Quotes'" class="card-content">
<div x-data="quotes()" x-init="fetchQuote()">
<div class="quote">
<p class="text" x-text='`"${quote.quote}"`'></p>
<p class="author" x-text="'~ ' + quote.author"></p>
</div>
<h2 class="error" x-show="Boolean(error)" x-text="error"></h2>
<div class="button-container">
<button class="button" @click="fetchQuote()" x-show="!loading">
Refresh
</button>
<div x-show="loading" class="lds-dual-ring"></div>
</div>
</div>
</div>
<div x-show="currentTab === 'About'" class="card-content">
<div x-data="{ open: false }" class="button-container">
<button x-show="!open" class="button" @click="open = true">
Show content
</button>
<p x-show.transition="open" class="credits">
A lot of thanks to
<a
class="mention"
href="https://twitter.com/calebporzio"
target="_blank"
>
@calebporzio
</a>
for this incredible and useful library.
<br />
<br />
<a class="mention" href="https://speckyboy.com/" target="_blank">
Speckyboy
</a>
for this fancy and awesome design idea.
<br />
<br />
And finally thanks to
<a
class="mention"
href="https://github.com/shevabam"
target="_blank"
>Shevabam</a
>
for an amazing Breaking Bad Quotes API.
</p>
</div>
</div>
</div>
<footer class="footer">
<p>
Coded by
<a
href="https://github.com/jhonny9550"
target="_blank"
class="mention mention-alt"
>jhonny9550</a
>
</p>
</footer>
</div>
<!--
https://medium.com/@jhonny9550/alpine-js-ser%C3%A1-tu-mejor-aliado-d5d9a8756edb
-->CSS
body {
margin: 0;
}
html,
body,
.content {
height: 100%;
}
*,
*::after,
*::before {
box-sizing: border-box;
}
* {
font-family: Verdana, Geneva, Tahoma, sans-serif !important;
}
.content {
align-items: center;
background-color: #47a1df;
display: flex;
padding: 48px;
}
.card {
border-radius: 8px;
flex: 1;
margin: 0 auto;
max-width: 800px;
overflow: hidden;
}
.tabs {
display: flex;
}
.tab {
background-color: transparent;
border: none;
color: #fff;
cursor: pointer;
flex-grow: 1;
font-size: 18px;
padding: 12px;
}
.tab:focus {
outline: none;
}
.tab.selected {
background-color: #fff;
border-radius: 8px 8px 0 0;
color: #424242;
}
.card-content {
background-color: #fff;
min-height: 300px;
padding: 48px 24px;
}
.title {
font-weight: 400;
text-align: center;
}
.colors {
display: flex;
justify-content: center;
padding: 12px 0;
}
.color {
border-radius: 50%;
box-shadow: 0 6px 3px rgba(0, 0, 0, 0.13);
cursor: pointer;
height: 50px;
margin: 0 12px;
width: 50px;
}
.color:hover {
transform: scale(1.2);
}
.error {
color: rgb(255, 66, 66);
text-align: center;
}
.quote {
color: #424242;
font-size: 16px;
margin: 0 auto;
max-width: 50%;
padding: 24px;
}
.quote > .text {
font-style: italic;
}
.quote > .author {
font-weight: 600;
text-align: right;
}
.button {
background-color: transparent;
border: 1px solid #3A87BB;
border-radius: 5px;
color: #3A87BB;
cursor: pointer;
font-size: 16px;
padding: 10px 24px;
}
.button-container {
text-align: center;
}
.credits {
padding: 12px;
}
.mention {
color: #3A87BB;
font-size: 20px;
text-decoration: none;
}
.mention-alt {
color: #424242;
}
.footer {
bottom: 0;
color: #FFF;
font-size: 24px;
left: 0;
position: fixed;
text-align: center;
width: 100%;
}
/* Loader */
.lds-dual-ring {
display: inline-block;
width: 44px;
height: 44px;
}
.lds-dual-ring:after {
content: " ";
display: block;
width: 40px;
height: 40px;
margin: 3px;
border-radius: 50%;
border: 6px solid #424242;
border-color: #424242 transparent #424242 transparent;
animation: lds-dual-ring 1.2s linear infinite;
}
@keyframes lds-dual-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
@media only screen and (max-width: 600px) {
.content {
padding: 12px;
}
.card-content {
min-height: 300px;
padding: 24px 0;
}
.color {
height: 36px;
width: 36px;
}
.quote {
max-width: unset;
}
}
JS
function tabs() {
return {
current: 'Colors',
items: ['Colors', 'Quotes', 'About'],
changeTab(tab) {
this.current = tab;
}
};
}
function colors() {
return {
list: [
{ hex: '#2DCC72', name: 'green' },
{ hex: '#D64A4B', name: 'red' },
{ hex: '#8E46AC', name: 'purple' },
{ hex: '#3A87BB', name: 'blue' },
{ hex: '#BFC4C8', name: 'gray' }
],
selected: 'blue',
changeColor(name) {
this.selected = name;
},
getCurrentColor() {
return this.list.find(c => c.name === this.selected);
}
};
}
function quotes() {
return {
quote: {},
error: null,
loading: false,
async fetchQuote() {
const apiUrl = 'https://breaking-bad-quotes.herokuapp.com/v1/quotes';
this.loading = true;
try {
const result = await fetch(apiUrl);
const [quote] = await result.json();
this.quote = quote;
} catch (error) {
this.error = 'Oops. Something went wrong.';
}
this.loading = false;
}
};
}
Deja tu comentario