traxxx/assets/components/album/album.vue

230 lines
3.8 KiB
Vue
Raw Normal View History

<template>
<teleport to="body">
<div class="album">
<div class="album-header">
<h3 class="album-title">{{ title }}</h3>
<Icon
icon="cross2"
class="close"
@click.native="$emit('close')"
/>
</div>
<div
class="album-items"
:class="{ portrait }"
>
<div
v-for="item in albumItems"
:key="item.id"
class="item-container"
>
<a
:href="`${path}/${item.path}`"
class="item-link"
target="_blank"
>
<img
:src="`${path}/${item.thumbnail}`"
:title="item.title"
loading="lazy"
class="item image"
>
<span
v-if="comments && item.title"
class="item-comment"
>{{ item.title }}</span>
</a>
</div>
</div>
</div>
</teleport>
</template>
<script>
function albumItems() {
return this.items.map(item => ({
...item,
title: item.comment || (item.credit && `© ${item.credit}`) || (item.entity && `© ${item.entity.name}`),
}));
}
export default {
props: {
items: {
type: Array,
default: () => [],
},
title: {
type: String,
default: null,
},
path: {
type: String,
default: '/media',
},
portrait: {
type: Boolean,
default: false,
},
comments: {
type: Boolean,
default: true,
},
},
computed: {
albumItems,
},
emits: ['close'],
};
</script>
<style lang="scss" scoped>
@import 'breakpoints';
.album {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
position: fixed;
top: 0;
left: 0;
background: var(--darken-extreme);
z-index: 10;
}
.album-header {
display: flex;
justify-content: space-between;
flex-shrink: 0;
}
.album-title {
2021-01-23 22:50:15 +00:00
display: block;
flex-grow: 1;
align-items: center;
2021-01-23 22:50:15 +00:00
padding: 1rem;
margin: 0;
color: var(--text-light);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
2021-01-23 22:50:15 +00:00
text-align: center;
text-transform: capitalize;
}
.close {
width: 1.5rem;
height: 1.5rem;
padding: 1rem;
fill: var(--lighten);
&:hover {
cursor: pointer;
fill: var(--text-light);
}
}
.album-items {
display: grid;
align-items: center;
justify-content: center;
2021-01-29 14:36:54 +00:00
grid-template-columns: repeat(auto-fit, minmax(25rem, 1fr));
grid-gap: 0 1rem;
padding: 1rem;
2021-01-23 22:09:05 +00:00
margin: auto 0;
overflow-y: auto;
&.portrait {
grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}
}
.item-container {
display: flex;
align-items: center;
justify-content: center;
}
.item-link {
position: relative;
2021-02-05 01:00:18 +00:00
margin: 0 0 .5rem 0;
overflow: hidden;
&:hover .item-comment {
transform: translateY(0);
}
}
.item {
2021-02-04 22:09:52 +00:00
max-width: 100%;
max-height: 100%;
}
.item-comment {
width: 100%;
position: absolute;
bottom: 0;
left: 0;
box-sizing: border-box;
padding: .5rem;
color: var(--text-light);
background: var(--shadow);
font-size: .9rem;
text-shadow: 0 0 3px var(--shadow);
white-space: normal;
line-height: 1.25;
transform: translateY(100%);
transition: transform .25s ease;
}
@media(max-width: $breakpoint-giga) {
2021-02-05 01:00:18 +00:00
.album-items {
grid-template-columns: repeat(auto-fill, minmax(22.5rem, 1fr));
.portrait {
grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
}
}
}
@media(max-width: $breakpoint-mega) {
.album-items.portrait {
grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
}
}
2021-01-29 14:36:54 +00:00
@media(max-width: $breakpoint-kilo) {
.album-items {
grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
2021-02-05 01:00:18 +00:00
grid-gap: 0 .5rem;
padding: .5rem;
}
.item-link {
margin: 0 0 .25rem 0;
2021-01-29 14:36:54 +00:00
}
}
@media(max-width: $breakpoint) {
.album-items {
2021-02-05 01:00:18 +00:00
grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
}
}
@media(max-width: $breakpoint-micro) {
.album-items {
2021-02-05 01:00:18 +00:00
grid-template-columns: repeat(auto-fill, minmax(11rem, 1fr));
}
}
@media(max-width: $breakpoint-pico) {
.album-items {
grid-template-columns: repeat(auto-fill, minmax(7rem, 1fr));
}
}
</style>