forked from DebaucheryLibrarian/traxxx
137 lines
2.3 KiB
Vue
Executable File
137 lines
2.3 KiB
Vue
Executable File
<template>
|
|
<div
|
|
class="tags-container"
|
|
:class="{ overflowing }"
|
|
>
|
|
<ul
|
|
ref="tags"
|
|
class="tags nolist"
|
|
:class="{ expanded }"
|
|
>
|
|
<li
|
|
v-for="tag in tags"
|
|
:key="`tag-${tag.slug}`"
|
|
class="tag"
|
|
>
|
|
<a
|
|
:href="`/tag/${tag.slug}`"
|
|
class="link"
|
|
>{{ tag.name }}</a>
|
|
</li>
|
|
</ul>
|
|
|
|
<button
|
|
v-if="overflowing && !expanded"
|
|
class="tags-more"
|
|
@click="expanded = true"
|
|
>more tags</button>
|
|
|
|
<button
|
|
v-if="expanded"
|
|
class="tags-more"
|
|
@click="expanded = false"
|
|
>fewer tags</button>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { nextTick } from 'vue';
|
|
|
|
function updateOverflowing() {
|
|
nextTick(() => {
|
|
const containerBoundaries = this.$refs.tags.getBoundingClientRect();
|
|
const containerBottom = containerBoundaries.top + containerBoundaries.height;
|
|
|
|
this.overflowing = Array.from(this.$refs.tags.querySelectorAll('.tag')).some((tag) => {
|
|
const tagBoundaries = tag.getBoundingClientRect();
|
|
|
|
return tagBoundaries.top > containerBottom;
|
|
});
|
|
});
|
|
}
|
|
|
|
function mounted() {
|
|
window.addEventListener('resize', this.updateOverflowing);
|
|
this.updateOverflowing();
|
|
}
|
|
|
|
function beforeUnmount() {
|
|
window.removeEventListener('resize', this.updateOverflowing);
|
|
}
|
|
|
|
export default {
|
|
props: {
|
|
tags: {
|
|
type: Array,
|
|
default: () => [],
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
overflowing: false,
|
|
expanded: false,
|
|
};
|
|
},
|
|
watch: {
|
|
expanded: updateOverflowing,
|
|
},
|
|
mounted,
|
|
beforeUnmount,
|
|
methods: {
|
|
updateOverflowing,
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.tags-container {
|
|
margin: 0 0 1.5rem 0;
|
|
|
|
&.overflowing {
|
|
margin: 0 0 .5rem 0;
|
|
}
|
|
}
|
|
|
|
.tags {
|
|
max-height: 4.7rem;
|
|
padding: 2px 1rem 0 1rem;
|
|
text-align: left;
|
|
overflow: hidden;
|
|
|
|
&.expanded {
|
|
max-height: unset;
|
|
}
|
|
}
|
|
|
|
.tag .link {
|
|
color: var(--link);
|
|
background: var(--background);
|
|
display: inline-block;
|
|
padding: .5rem;
|
|
margin: 0 .25rem .25rem 0;
|
|
box-shadow: 0 0 2px var(--shadow-weak);
|
|
text-decoration: none;
|
|
text-transform: capitalize;
|
|
|
|
&:hover {
|
|
color: var(--primary);
|
|
}
|
|
}
|
|
|
|
.tags-more {
|
|
background: var(--shadow-touch);
|
|
padding: .5rem 1rem;
|
|
border: none;
|
|
margin: .25rem 0 .5rem 1rem;
|
|
color: var(--shadow);
|
|
font-size: .8rem;
|
|
font-weight: bold;
|
|
|
|
&:hover {
|
|
background: var(--shadow-hint);
|
|
color: var(--shadow-strong);
|
|
cursor: pointer;
|
|
}
|
|
}
|
|
</style>
|