Change lint rules to AirBnB
This commit is contained in:
@@ -1,108 +1,108 @@
|
||||
<template>
|
||||
<div class="collapsable">
|
||||
<input :id="`collapsible-${uniqueKey}`" class="toggle" type="checkbox" checked>
|
||||
<label :for="`collapsible-${uniqueKey}`" class="lbl-toggle" tabindex="0">
|
||||
<h2>{{ title }}</h2>
|
||||
</label>
|
||||
<div class="collapsible-content">
|
||||
<div class="content-inner">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'CollapsableContainer',
|
||||
props: {
|
||||
uniqueKey: String,
|
||||
title: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
|
||||
.collapsable {
|
||||
width: 310px;
|
||||
padding: 5px;
|
||||
margin: 10px;
|
||||
border-radius: 10px;
|
||||
background: #1CA8DD;
|
||||
background: -webkit-linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
background: linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
box-shadow: 1px 1px 2px #130f23;
|
||||
|
||||
.wrap-collabsible {
|
||||
margin-bottom: 1.2rem 0;
|
||||
}
|
||||
|
||||
input[type='checkbox'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.lbl-toggle {
|
||||
display: block;
|
||||
padding: 1rem;
|
||||
cursor: pointer;
|
||||
border-radius: 7px;
|
||||
transition: all 0.25s ease-out;
|
||||
text-align: left;
|
||||
color: #2f323ae6;
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.lbl-toggle:hover {
|
||||
color: #2f323a;
|
||||
}
|
||||
|
||||
.lbl-toggle::before {
|
||||
content: ' ';
|
||||
display: inline-block;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-left: 5px solid currentColor;
|
||||
vertical-align: middle;
|
||||
margin-right: .7rem;
|
||||
transform: translateY(-2px);
|
||||
|
||||
transition: transform .2s ease-out;
|
||||
}
|
||||
|
||||
.toggle:checked + .lbl-toggle::before {
|
||||
transform: rotate(90deg) translateX(-3px);
|
||||
}
|
||||
|
||||
.collapsible-content {
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height .25s ease-in-out;
|
||||
background: #2f323ae6;
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
|
||||
.toggle:checked + .lbl-toggle + .collapsible-content {
|
||||
max-height: 1000px;
|
||||
}
|
||||
|
||||
.toggle:checked + .lbl-toggle {
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.collapsible-content .content-inner {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="collapsable">
|
||||
<input :id="`collapsible-${uniqueKey}`" class="toggle" type="checkbox" checked>
|
||||
<label :for="`collapsible-${uniqueKey}`" class="lbl-toggle" tabindex="0">
|
||||
<h2>{{ title }}</h2>
|
||||
</label>
|
||||
<div class="collapsible-content">
|
||||
<div class="content-inner">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'CollapsableContainer',
|
||||
props: {
|
||||
uniqueKey: String,
|
||||
title: String,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
|
||||
.collapsable {
|
||||
width: 310px;
|
||||
padding: 5px;
|
||||
margin: 10px;
|
||||
border-radius: 10px;
|
||||
background: #1CA8DD;
|
||||
background: -webkit-linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
background: linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
box-shadow: 1px 1px 2px #130f23;
|
||||
|
||||
.wrap-collabsible {
|
||||
margin-bottom: 1.2rem 0;
|
||||
}
|
||||
|
||||
input[type='checkbox'] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
label {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.lbl-toggle {
|
||||
display: block;
|
||||
padding: 1rem;
|
||||
cursor: pointer;
|
||||
border-radius: 7px;
|
||||
transition: all 0.25s ease-out;
|
||||
text-align: left;
|
||||
color: #2f323ae6;
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.lbl-toggle:hover {
|
||||
color: #2f323a;
|
||||
}
|
||||
|
||||
.lbl-toggle::before {
|
||||
content: ' ';
|
||||
display: inline-block;
|
||||
border-top: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-left: 5px solid currentColor;
|
||||
vertical-align: middle;
|
||||
margin-right: .7rem;
|
||||
transform: translateY(-2px);
|
||||
|
||||
transition: transform .2s ease-out;
|
||||
}
|
||||
|
||||
.toggle:checked + .lbl-toggle::before {
|
||||
transform: rotate(90deg) translateX(-3px);
|
||||
}
|
||||
|
||||
.collapsible-content {
|
||||
max-height: 0px;
|
||||
overflow: hidden;
|
||||
transition: max-height .25s ease-in-out;
|
||||
background: #2f323ae6;
|
||||
border-radius: 0 0 10px 10px;
|
||||
}
|
||||
|
||||
.toggle:checked + .lbl-toggle + .collapsible-content {
|
||||
max-height: 1000px;
|
||||
}
|
||||
|
||||
.toggle:checked + .lbl-toggle {
|
||||
border-bottom-right-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
}
|
||||
|
||||
.collapsible-content .content-inner {
|
||||
padding: 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,118 +1,119 @@
|
||||
<template>
|
||||
<section>
|
||||
<form>
|
||||
<label for="filter-tiles">Search</label>
|
||||
<input
|
||||
id="filter-tiles"
|
||||
v-model="input"
|
||||
ref="filter"
|
||||
placeholder="Start typing to filter tiles..."
|
||||
v-on:input="userIsTypingSomething"
|
||||
@keydown.esc="clearFilterInput" />
|
||||
<i v-if="input.length > 0"
|
||||
class="el-icon-circle-close clear-search"
|
||||
title="Clear search"
|
||||
@click="clearFilterInput"></i>
|
||||
</form>
|
||||
<div class="space-filler"></div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'FilterTile',
|
||||
data () {
|
||||
return {
|
||||
input: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
userIsTypingSomething () {
|
||||
this.$emit('user-is-searchin', this.input)
|
||||
},
|
||||
clearFilterInput () {
|
||||
this.input = ''
|
||||
this.userIsTypingSomething()
|
||||
document.activeElement.blur()
|
||||
},
|
||||
},
|
||||
mounted: function() {
|
||||
window.addEventListener('keyup', (event) => {
|
||||
const key = event.key
|
||||
if(/^[a-zA-Z]$/.test(key) && !document.activeElement.id) {
|
||||
this.input += key
|
||||
this.$refs.filter.focus()
|
||||
this.userIsTypingSomething()
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
background: linear-gradient(0deg, rgba(47,50,58,1) 0%, rgba(40,42,50,1) 100%);
|
||||
}
|
||||
form {
|
||||
border-radius: 0 0 20px 0;
|
||||
padding: 0 0.2rem 0.2rem 0;
|
||||
background: #282a32;
|
||||
label {
|
||||
display: inline;
|
||||
background: -webkit-gradient(linear, right bottom, left top, from(#9F86FF), color-stop(#1CA8DD), to(#007AE1));
|
||||
background: linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
margin: 0.5rem;
|
||||
display: inline;
|
||||
}
|
||||
input {
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
padding: 0.5rem;
|
||||
margin: 0.5rem;
|
||||
outline: none;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
background: #607d8b33;
|
||||
box-shadow: 1px 1px 2px #232323;
|
||||
color: #1CA8DD;
|
||||
font-family: 'Comfortaa', cursive;
|
||||
&:focus {
|
||||
background: #607d8b4a;
|
||||
}
|
||||
}
|
||||
.clear-search {
|
||||
position: absolute;
|
||||
margin: 1em 0 0 -2em;
|
||||
color: #1CA8DD;
|
||||
opacity: 0.5;
|
||||
border-radius: 50px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
background: #282a32;
|
||||
}
|
||||
}
|
||||
}
|
||||
.space-filler {
|
||||
flex: 1;
|
||||
border-radius: 20px 0 0;
|
||||
background: #2f323a;
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
form {
|
||||
flex: 1;
|
||||
border-radius: 0;
|
||||
text-align: center;
|
||||
padding: 0.25rem 0;
|
||||
}
|
||||
.space-filler {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<section>
|
||||
<form>
|
||||
<label for="filter-tiles">Search</label>
|
||||
<input
|
||||
id="filter-tiles"
|
||||
v-model="input"
|
||||
ref="filter"
|
||||
placeholder="Start typing to filter tiles..."
|
||||
v-on:input="userIsTypingSomething"
|
||||
@keydown.esc="clearFilterInput" />
|
||||
<i v-if="input.length > 0"
|
||||
class="el-icon-circle-close clear-search"
|
||||
title="Clear search"
|
||||
@click="clearFilterInput"></i>
|
||||
</form>
|
||||
<div class="space-filler"></div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'FilterTile',
|
||||
data() {
|
||||
return {
|
||||
input: '',
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
userIsTypingSomething() {
|
||||
this.$emit('user-is-searchin', this.input);
|
||||
},
|
||||
clearFilterInput() {
|
||||
this.input = '';
|
||||
this.userIsTypingSomething();
|
||||
document.activeElement.blur();
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('keyup', (event) => {
|
||||
const { key } = event;
|
||||
if (/^[a-zA-Z]$/.test(key) && !document.activeElement.id) {
|
||||
this.input += key;
|
||||
this.$refs.filter.focus();
|
||||
this.userIsTypingSomething();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
section {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
background: linear-gradient(0deg, rgba(47,50,58,1) 0%, rgba(40,42,50,1) 100%);
|
||||
}
|
||||
form {
|
||||
border-radius: 0 0 20px 0;
|
||||
padding: 0 0.2rem 0.2rem 0;
|
||||
background: #282a32;
|
||||
label {
|
||||
display: inline;
|
||||
background: -webkit-gradient(
|
||||
linear, right bottom, left top, from(#9F86FF), color-stop(#1CA8DD), to(#007AE1));
|
||||
background: linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
margin: 0.5rem;
|
||||
display: inline;
|
||||
}
|
||||
input {
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
padding: 0.5rem;
|
||||
margin: 0.5rem;
|
||||
outline: none;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
background: #607d8b33;
|
||||
box-shadow: 1px 1px 2px #232323;
|
||||
color: #1CA8DD;
|
||||
font-family: 'Comfortaa', cursive;
|
||||
&:focus {
|
||||
background: #607d8b4a;
|
||||
}
|
||||
}
|
||||
.clear-search {
|
||||
position: absolute;
|
||||
margin: 1em 0 0 -2em;
|
||||
color: #1CA8DD;
|
||||
opacity: 0.5;
|
||||
border-radius: 50px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
background: #282a32;
|
||||
}
|
||||
}
|
||||
}
|
||||
.space-filler {
|
||||
flex: 1;
|
||||
border-radius: 20px 0 0;
|
||||
background: #2f323a;
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
form {
|
||||
flex: 1;
|
||||
border-radius: 0;
|
||||
text-align: center;
|
||||
padding: 0.25rem 0;
|
||||
}
|
||||
.space-filler {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
<template>
|
||||
<footer>
|
||||
Developed by <a :href="authorUrl">{{authorName}}</a>.
|
||||
Licensed under <a :href="licenseUrl">{{license}}</a>
|
||||
{{ showCopyright? '©': '' }} {{date}}.
|
||||
Get the <a :href="repoUrl">Source Code</a>.
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Footer',
|
||||
props: {
|
||||
authorName: { type: String, default: 'Alicia Sykes' },
|
||||
authorUrl: { type: String, default: 'https://aliciasykes.com' },
|
||||
license: { type: String, default: 'MIT' },
|
||||
licenseUrl: { type: String, default: 'https://gist.github.com/Lissy93/143d2ee01ccc5c052a17' },
|
||||
date: { type: String, default: `${new Date().getFullYear()}` },
|
||||
showCopyright: { type: Boolean, default: true },
|
||||
repoUrl: { type: String, default: 'https://github.com/lissy93/panel' }
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
|
||||
footer {
|
||||
padding: 0.5rem;
|
||||
text-align: center;
|
||||
color: #5e6474;
|
||||
}
|
||||
|
||||
footer a{
|
||||
color: #5e6474;
|
||||
&:hover {
|
||||
color: #9F86FF;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
<template>
|
||||
<footer>
|
||||
Developed by <a :href="authorUrl">{{authorName}}</a>.
|
||||
Licensed under <a :href="licenseUrl">{{license}}</a>
|
||||
{{ showCopyright? '©': '' }} {{date}}.
|
||||
Get the <a :href="repoUrl">Source Code</a>.
|
||||
</footer>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Footer',
|
||||
props: {
|
||||
authorName: { type: String, default: 'Alicia Sykes' },
|
||||
authorUrl: { type: String, default: 'https://aliciasykes.com' },
|
||||
license: { type: String, default: 'MIT' },
|
||||
licenseUrl: { type: String, default: 'https://gist.github.com/Lissy93/143d2ee01ccc5c052a17' },
|
||||
date: { type: String, default: `${new Date().getFullYear()}` },
|
||||
showCopyright: { type: Boolean, default: true },
|
||||
repoUrl: { type: String, default: 'https://github.com/lissy93/panel' },
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
|
||||
footer {
|
||||
padding: 0.5rem;
|
||||
text-align: center;
|
||||
color: #5e6474;
|
||||
}
|
||||
|
||||
footer a{
|
||||
color: #5e6474;
|
||||
&:hover {
|
||||
color: #9F86FF;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,33 +1,34 @@
|
||||
<template>
|
||||
<header>
|
||||
<PageTitle />
|
||||
<Nav class="nav"/>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PageTitle from '@/components/PageTitle.vue'
|
||||
import Nav from '@/components/Nav.vue'
|
||||
export default {
|
||||
name: 'Header',
|
||||
components: {
|
||||
PageTitle,
|
||||
Nav
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
header {
|
||||
margin: 0;
|
||||
padding: 0.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background: #282a32;
|
||||
align-items: center;
|
||||
align-content: flex-start;
|
||||
@media screen and (max-width: 600px) {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<header>
|
||||
<PageTitle />
|
||||
<Nav class="nav"/>
|
||||
</header>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PageTitle from '@/components/PageTitle.vue';
|
||||
import Nav from '@/components/Nav.vue';
|
||||
|
||||
export default {
|
||||
name: 'Header',
|
||||
components: {
|
||||
PageTitle,
|
||||
Nav,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
header {
|
||||
margin: 0;
|
||||
padding: 0.5rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
background: #282a32;
|
||||
align-items: center;
|
||||
align-content: flex-start;
|
||||
@media screen and (max-width: 600px) {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
}
|
||||
msg: String,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
|
||||
@@ -1,136 +1,134 @@
|
||||
<template>
|
||||
<el-tooltip placement="bottom" effect="dark" :content="description" :disabled="!description">
|
||||
<div class="item" tabindex="0">
|
||||
<div class="tile-title" :id="`tile-${id}`">
|
||||
<span class="text">{{ title }}</span>
|
||||
<div class="overflow-dots">...</div>
|
||||
</div>
|
||||
<img
|
||||
v-if="icon"
|
||||
:src="`/img/tile-icons/${icon}.png`"
|
||||
class="tile-icon"
|
||||
/>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'Item',
|
||||
props: {
|
||||
id: String, // The unique ID of a tile (e.g. 001)
|
||||
title: String, // The main text of tile, required
|
||||
subtitle: String, // Optional sub-text
|
||||
description: String, // Optional tooltip hover text
|
||||
icon: String, // Optional path to icon, within public/img/tile-icons
|
||||
color: String, // Optional background color, specified in hex code
|
||||
url: String, // URL to the resource, optional but recommended
|
||||
openingMethod: { // Where resource will open, either 'newtab', 'sametab' or 'iframe'
|
||||
type: String,
|
||||
default: 'newtab',
|
||||
validator: (value) =>
|
||||
['newtab', 'sametab', 'iframe'].indexOf(value) !== -1
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return { getId: this.id }
|
||||
},
|
||||
mounted () {
|
||||
// Detects overflowing text, and allows is to marguee on hover
|
||||
// The below code is horifically bad, it is embarassing that I wrote it...
|
||||
const tileElem = document.getElementById(`tile-${this.getId}`)
|
||||
if (tileElem) {
|
||||
const isOverflowing =
|
||||
tileElem.scrollHeight > tileElem.clientHeight ||
|
||||
tileElem.scrollWidth > tileElem.clientWidth
|
||||
if (isOverflowing) {
|
||||
tileElem.className += ' is-overflowing'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
|
||||
.item {
|
||||
width: 120px;
|
||||
height: 100px;
|
||||
color: #1CA8DD;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: 8px;
|
||||
background: #607d8b33;
|
||||
text-align: center;
|
||||
padding: 2px;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 10px;
|
||||
box-shadow: 1px 1px 2px #373737;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
box-shadow: 1px 2px 4px #373737;
|
||||
background: #607d8b4d;
|
||||
}
|
||||
&:focus {
|
||||
border: 2px solid #1CA8DD;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
.tile-title {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 120px;
|
||||
height: 30px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
|
||||
span.text {
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
transition: 1s;
|
||||
float: left;
|
||||
left: 0;
|
||||
}
|
||||
&:not(.is-overflowing) span.text{
|
||||
width: 100%;
|
||||
}
|
||||
.overflow-dots {
|
||||
// display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.tile-title.is-overflowing {
|
||||
span.text {
|
||||
overflow: hidden;
|
||||
}
|
||||
.overflow-dots {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
background: #354857;
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
right: 0;
|
||||
transition: opacity 0.1s ease-in;
|
||||
}
|
||||
}
|
||||
|
||||
.item:hover .tile-title{
|
||||
.overflow-dots {
|
||||
// display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
span.text {
|
||||
transform: translateX(calc(120px - 100%));
|
||||
}
|
||||
}
|
||||
|
||||
.tile-icon {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
</style>
|
||||
<template>
|
||||
<el-tooltip placement="bottom" effect="dark" :content="description" :disabled="!description">
|
||||
<div class="item" tabindex="0">
|
||||
<div class="tile-title" :id="`tile-${id}`">
|
||||
<span class="text">{{ title }}</span>
|
||||
<div class="overflow-dots">...</div>
|
||||
</div>
|
||||
<img
|
||||
v-if="icon"
|
||||
:src="`/img/tile-icons/${icon}.png`"
|
||||
class="tile-icon"
|
||||
/>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'Item',
|
||||
props: {
|
||||
id: String, // The unique ID of a tile (e.g. 001)
|
||||
title: String, // The main text of tile, required
|
||||
subtitle: String, // Optional sub-text
|
||||
description: String, // Optional tooltip hover text
|
||||
icon: String, // Optional path to icon, within public/img/tile-icons
|
||||
color: String, // Optional background color, specified in hex code
|
||||
url: String, // URL to the resource, optional but recommended
|
||||
openingMethod: { // Where resource will open, either 'newtab', 'sametab' or 'iframe'
|
||||
type: String,
|
||||
default: 'newtab',
|
||||
validator: (value) => ['newtab', 'sametab', 'iframe'].indexOf(value) !== -1,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return { getId: this.id };
|
||||
},
|
||||
mounted() {
|
||||
// Detects overflowing text, and allows is to marguee on hover
|
||||
// The below code is horifically bad, it is embarassing that I wrote it...
|
||||
const tileElem = document.getElementById(`tile-${this.getId}`);
|
||||
if (tileElem) {
|
||||
const isOverflowing = tileElem.scrollHeight > tileElem.clientHeight
|
||||
|| tileElem.scrollWidth > tileElem.clientWidth;
|
||||
if (isOverflowing) {
|
||||
tileElem.className += ' is-overflowing';
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
|
||||
.item {
|
||||
width: 120px;
|
||||
height: 100px;
|
||||
color: #1CA8DD;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin: 8px;
|
||||
background: #607d8b33;
|
||||
text-align: center;
|
||||
padding: 2px;
|
||||
border: 2px solid transparent;
|
||||
border-radius: 10px;
|
||||
box-shadow: 1px 1px 2px #373737;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
box-shadow: 1px 2px 4px #373737;
|
||||
background: #607d8b4d;
|
||||
}
|
||||
&:focus {
|
||||
border: 2px solid #1CA8DD;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
.tile-title {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
width: 120px;
|
||||
height: 30px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
padding: 0;
|
||||
|
||||
span.text {
|
||||
position: absolute;
|
||||
white-space: nowrap;
|
||||
transition: 1s;
|
||||
float: left;
|
||||
left: 0;
|
||||
}
|
||||
&:not(.is-overflowing) span.text{
|
||||
width: 100%;
|
||||
}
|
||||
.overflow-dots {
|
||||
// display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.tile-title.is-overflowing {
|
||||
span.text {
|
||||
overflow: hidden;
|
||||
}
|
||||
.overflow-dots {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
background: #354857;
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
right: 0;
|
||||
transition: opacity 0.1s ease-in;
|
||||
}
|
||||
}
|
||||
|
||||
.item:hover .tile-title{
|
||||
.overflow-dots {
|
||||
// display: none;
|
||||
opacity: 0;
|
||||
}
|
||||
span.text {
|
||||
transform: translateX(calc(120px - 100%));
|
||||
}
|
||||
}
|
||||
|
||||
.tile-icon {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,55 +1,55 @@
|
||||
<template>
|
||||
<Collapsable :title="title" :uniqueKey="groupId">
|
||||
<div v-if="!items || items.length < 1" class="no-items">
|
||||
No Items to Show Yet
|
||||
</div>
|
||||
<div v-else class="there-are-items">
|
||||
<Item
|
||||
v-for="item in items"
|
||||
:key="`${groupId}-${item.id}`"
|
||||
:id="`${groupId}-${item.id}`"
|
||||
:title="item.title"
|
||||
:description="item.description"
|
||||
:icon="item.icon"
|
||||
/>
|
||||
</div>
|
||||
</Collapsable>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Item from '@/components/Item.vue'
|
||||
import Collapsable from '@/components/Collapsable.vue'
|
||||
|
||||
export default {
|
||||
name: 'ItemGroup',
|
||||
props: {
|
||||
groupId: String,
|
||||
title: String,
|
||||
items: Array
|
||||
},
|
||||
components: {
|
||||
Collapsable,
|
||||
Item
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.no-items {
|
||||
width: 100px;
|
||||
margin: 0 auto;
|
||||
padding: 0.8rem;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
border-radius: 10px;
|
||||
background: #607d8b33;
|
||||
color: #1CA8DD;
|
||||
box-shadow: 1px 1px 2px #373737;
|
||||
}
|
||||
|
||||
.there-are-items {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
</style>
|
||||
<template>
|
||||
<Collapsable :title="title" :uniqueKey="groupId">
|
||||
<div v-if="!items || items.length < 1" class="no-items">
|
||||
No Items to Show Yet
|
||||
</div>
|
||||
<div v-else class="there-are-items">
|
||||
<Item
|
||||
v-for="item in items"
|
||||
:key="`${groupId}-${item.id}`"
|
||||
:id="`${groupId}-${item.id}`"
|
||||
:title="item.title"
|
||||
:description="item.description"
|
||||
:icon="item.icon"
|
||||
/>
|
||||
</div>
|
||||
</Collapsable>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Item from '@/components/Item.vue';
|
||||
import Collapsable from '@/components/Collapsable.vue';
|
||||
|
||||
export default {
|
||||
name: 'ItemGroup',
|
||||
props: {
|
||||
groupId: String,
|
||||
title: String,
|
||||
items: Array,
|
||||
},
|
||||
components: {
|
||||
Collapsable,
|
||||
Item,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.no-items {
|
||||
width: 100px;
|
||||
margin: 0 auto;
|
||||
padding: 0.8rem;
|
||||
text-align: center;
|
||||
cursor: default;
|
||||
border-radius: 10px;
|
||||
background: #607d8b33;
|
||||
color: #1CA8DD;
|
||||
box-shadow: 1px 1px 2px #373737;
|
||||
}
|
||||
|
||||
.there-are-items {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,41 +1,41 @@
|
||||
<template>
|
||||
<nav id="nav">
|
||||
<router-link to="/" class="nav-item">Home</router-link>
|
||||
<router-link to="/about" class="nav-item">About</router-link>
|
||||
</nav>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Nav'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.nav-item {
|
||||
display: inline-block;
|
||||
padding: 0.75rem 0.5rem;
|
||||
margin: 0.5rem;
|
||||
outline: none;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
background: #607d8b33;
|
||||
-webkit-box-shadow: 1px 1px 2px #232323;
|
||||
box-shadow: 1px 1px 2px #232323;
|
||||
color: #1CA8DD;
|
||||
font-family: "Comfortaa", cursive;
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
background: #607d8b1c;
|
||||
box-shadow: 1px 4px 3px #232323;
|
||||
}
|
||||
}
|
||||
.router-link-active {
|
||||
border: 1px solid #1CA8DD;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<nav id="nav">
|
||||
<router-link to="/" class="nav-item">Home</router-link>
|
||||
<router-link to="/about" class="nav-item">About</router-link>
|
||||
</nav>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Nav',
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.nav-item {
|
||||
display: inline-block;
|
||||
padding: 0.75rem 0.5rem;
|
||||
margin: 0.5rem;
|
||||
outline: none;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
background: #607d8b33;
|
||||
-webkit-box-shadow: 1px 1px 2px #232323;
|
||||
box-shadow: 1px 1px 2px #232323;
|
||||
color: #1CA8DD;
|
||||
font-family: "Comfortaa", cursive;
|
||||
text-decoration: none;
|
||||
&:hover {
|
||||
background: #607d8b1c;
|
||||
box-shadow: 1px 4px 3px #232323;
|
||||
}
|
||||
}
|
||||
.router-link-active {
|
||||
border: 1px solid #1CA8DD;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
<template>
|
||||
<div class="page-titles">
|
||||
<h1>Pannel</h1>
|
||||
<span class="subtitle">Awesome subtitle</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PageTitle'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-titles {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
h1 {
|
||||
background: -webkit-linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
background: linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
font-size: 3rem;
|
||||
margin: 0;
|
||||
}
|
||||
span.subtitle {
|
||||
color: #9F86FF;
|
||||
font-style: italic;
|
||||
text-shadow: 1px 1px 2px #130f23;
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
text-align: center;
|
||||
padding: 0.25rem 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="page-titles">
|
||||
<h1>Pannel</h1>
|
||||
<span class="subtitle">Awesome subtitle</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'PageTitle',
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.page-titles {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
h1 {
|
||||
background: -webkit-linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
background: linear-gradient(to left top, #9F86FF, #1CA8DD, #007AE1);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
font-size: 3rem;
|
||||
margin: 0;
|
||||
}
|
||||
span.subtitle {
|
||||
color: #9F86FF;
|
||||
font-style: italic;
|
||||
text-shadow: 1px 1px 2px #130f23;
|
||||
}
|
||||
@media screen and (max-width: 600px) {
|
||||
text-align: center;
|
||||
padding: 0.25rem 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user