<div id="app">
<div class="wrap">
<section v-if="errored">
<p>We're sorry, we're not able to retrieve this information at the moment, please try back later</p>
</section>
<section v-else>
<div v-if="loading">Loading...</div>
<div class="name--header">
<div class="name">{{ info.name }} <a class="connect-button" :href="info.instant_invite" target="_blank">Connect</a></div>
<div class="discord">
<a href="https://discordapp.com/" class="discord--link" target="_blank">Powered By:<img src="https://cdn.prod.website-files.com/6257adef93867e50d84d30e2/6257d23c5fb25be7e0b6e220_Open%20Source%20Projects%20_%20Discord-7.svg" alt="Discord Logo" /></a>
</div>
</div>
<div class="channels">
<div class="channels--header">Channels</div>
<div class="channels--body">
<ul class="channels--list--wrap" v-for="channel in sortedChannels">
<li class="channel--name">{{ channel.name }}</li>
</ul>
</div>
</div>
<div class="users">
<div class="users--header">{{ info.members.length }} Members Online</div>
<div class="users--body">
<div class="user" v-for="users in info.members">
<span class="user--game" v-for="gameName in users.game">{{ gameName }}</span>
<div class="image--wrap">
<div class="user--status" :class="'status--' + users.status">
</div>
<img class="user--image" :src="users.avatar_url">
</div>
<span class="username">{{ users.username }}</span>
</div>
</div>
</div>
</section>
</div>
</div>
@import url('https://fonts.googleapis.com/css?family=Montserrat:400,700');
//vars
@blue: hsl(190, 50%, 50%);
@green: hsl(150, 50%, 50%);
@dark-blue: hsl(190, 50%, 45%);
@white: #fff;
@black: #111;
@off-black: #222;
@soft-corners: 0.3rem;
@underline: linear-gradient(
to bottom,
transparent 95%,
@black 95%,
);
@underline-light: linear-gradient(
to bottom,
transparent 95%,
@white 100%,
);
//mixins
.bs(@d: 5px, @a: 0.3){
box-shadow: 0 @d @d rgba(0,0,0,@a);
}
.bg-gradient(@col1, @col2){
background: linear-gradient(
to top,
@col1 0%,
@col2 * 1.5 100%
);
}
*{
box-sizing: border-box;
}
html,body{
height: 100%;width: 100%;margin: 0;
background: @black;
font-family: 'Montserrat', sans-serif;
}
.wrap{
height: 100%;width: 100%;
display: flex;
flex-flow: column;
color: @white;
}
.name--header{
width: 100%;
background: @dark-blue;
font-size: 200%;
text-shadow: 0px 0px 5px rgba(0,0,0,0.4);
color: @white;
display: flex;
align-items: center;
padding: 2rem 1rem ;
border-bottom: 0.3rem solid @white;
.bs();
justify-content: space-between;
& .name{
font-weight: 500;
}
& .discord{
font-size: 50%;
& a{
color: white;
text-decoration: none;
outline: none;
}
}
}
.channels{
margin: 1rem;;
.bs();
display: block;
&--header{
font-size: 150%;
font-weight: 500;
color: @white;
padding: 1rem;
.bg-gradient(@blue, @blue);
border-top-left-radius: @soft-corners;
border-top-right-radius: @soft-corners;
}
&--body{
background: @off-black;
margin: 0;
padding: 1rem;
border-bottom-left-radius: @soft-corners;
border-bottom-right-radius: @soft-corners;
}
}
.channel--name{
margin: 0.3rem 0;
padding: 0.2rem 0;
background: @underline-light;
}
.users{
margin: 1rem;;
.bs();
display: block;
flex-direction: column;
&--header{
font-size: 150%;
font-weight: 500;
.bg-gradient(@green, @green);
color: @white ;
padding: 1rem;
border-top-left-radius: @soft-corners;
border-top-right-radius: @soft-corners;
}
&--body{
background: @off-black;
margin: 0;
padding: 1rem;
display: flex;
flex-flow: column;
border-bottom-left-radius: @soft-corners;
border-bottom-right-radius: @soft-corners;
}
}
.user{
display: flex;
flex-flow: row wrap;
align-items: center;
font-size: 110%;
margin: 0.5rem 0;
background: @underline;
padding: 0.3rem;
position: relative;
width: 100%;
&--image{
width: 100%;
border-radius: 100%;
user-select: none;
}
& .username{
margin: 0 0.5rem;
position: relative;
}
& .bot--tag{
order: 4;
font-size: 50%;
background: #7289da;
padding: 0.2rem;
border-radius: 0.1rem;
user-select: none;
cursor: default;
}
}
.user--status{
@size: 0.8rem;
height: @size;
width: @size;
border-radius: 100%;
position: absolute;
right: 0;
bottom: 0;
border: 1px solid #ddd;
}
.status--online{
background: #43b581
}
.status--idle{
background: #faa61a;
}
.status--dnd{
background: #f04747 ;
}
.image--wrap{
@size: 2.5rem;
background: pink;
position: relative;
border-radius: 100%;
height: @size;
width: @size;
}
.user--game{
order: 5;
flex-grow: 1;
display: flex;
justify-content: flex-end;
align-items: flex-end;
position: relative;
font-size: 75%;
color: rgba(255,255,255, 0.5);
}
ul, li{
margin: 0;
padding: 0;
list-style: none;
}
.connect-button {
padding: 10px 20px;
font-size: 20px;
background: #232323;
color: white;
text-decoration: none;
border-radius: 5px;
margin-top: -5px;
vertical-align: middle;
margin-left: 10px;
}
.connect-button:hover {
opacity: .6;
}
View Compiled
// Discord Status Widget using Vue.js + API + Axios
new Vue({
el: '#app',
data() {
return {
info: null,
loading: true,
errored: false,
};
},
computed: {
sortedChannels: function () {
function compare(a, b) {
return a.position - b.position;
}
return this.info.channels.sort(compare);
},
},
mounted() {
axios.get('https://discordapp.com/api/guilds/208019977717022721/widget.json')
.then(response => (this.info = response.data))
.catch(error => {
console.log(error);
this.errored = true;
})
.finally(() => this.loading = false);
},
});
This Pen doesn't use any external CSS resources.