<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://discordapp.com/assets/4f004ac9be168ac6ee18fc442a52ab53.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;
}
// 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);
  },
});

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.min.js
  2. https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js