kamilcraft.com/src/components/SelectedProjects.vue
2022-07-14 00:33:28 +02:00

260 lines
5.5 KiB
Vue

<template>
<div class="max-w-screen-xl mx-auto px-6 xl:px-2 py-11">
<slot />
<div class="grid items-start grid-cols-2 gap-x-6 gap-y-5">
<div
v-for="project in projects"
:key="project.title.slug"
class="grid grid-project relative bg-neutral-100"
>
<img
v-if="project.images.small"
class="project-image w-[12.5rem] h-[12.5rem] object-cover"
:src="project.images.small"
:alt="project.title"
>
<img
v-else-if="project.images.large"
class="project-image w-[12.5rem] h-[12.5rem] object-cover"
:src="project.images.large"
:alt="project.title"
>
<div class="p-3 h-[12.5rem] overflow-y-hidden after:absolute after:left-0 after:bottom-0 after:w-full after:h-full">
<header class="pb-2">
<h3 class="text-lg font-bold">
{{ project.title }}
</h3>
<p class="text-sm">
{{ project.project_version }}
</p>
</header>
<p
class="text-sm"
v-html="markdownToText(project)"
/>
</div>
<div class="more-button">
<BaseButton
has-icon
icon="eye"
is-reverse
class="btn"
@click="router.push({ name: 'Project', params: { id: project.id } })"
>
O projekcie
</BaseButton>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { defineProps, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useStore } from 'vuex'
import BaseButton from './buttons/BaseButton'
import { marked } from 'marked'
defineProps({
projects: {
type: Array,
default: () => []
}
})
const route = useRoute()
const router = useRouter()
const store = useStore()
onMounted(() => {
const header = {
title: route.meta.title,
description: [
'Witam Państwa na podstronie z moimi projektami!'
]
}
store.commit('setHeader', header)
})
function markdownToText (project) {
const projectText = marked.parse(project.description)
const nodeElement = document.createElement('div')
nodeElement.innerHTML = projectText
return nodeElement.querySelector('p').innerText.substr(0, 350)
}
</script>
<style lang="scss" scoped>
@import "scss/media";
.grid-project {
grid-template-areas: 'image content';
grid-template-columns: 200px 1fr;
animation: load-project 2s forwards;
.project-image , .project-content {
object-position: top center;
}
.project-image {
grid-area: image;
}
.project-content {
grid-area: content;
}
}
.projects {
padding-top: 45px;
padding-bottom: 45px;
.container {
display: grid;
align-items: flex-start;
grid-template-columns: 1fr 1fr;
grid-auto-rows: minmax(80px, auto);
column-gap: 25px;
row-gap: 20px;
.project {
display: grid;
position: relative;
grid-template-areas: 'image content';
grid-template-columns: 200px 1fr;
background-color: #fafafa;
border: 1px solid rgba(0, 0, 0, .025);
border-radius: 5px;
animation: load-project 2s forwards;
.project_image {
grid-area: image;
width: 200px;
height: 200px;
object-fit: cover;
object-position: top center;
}
.project_content {
grid-area: content;
padding: 10px 15px;
height: 200px;
overflow-y: hidden;
position: relative;
.project_title {
font-size: 1.3em;
font-weight: normal;
line-height: 1.5em;
}
.project_release {
font-size: .9em;
font-weight: bold;
padding: 5px 0;
}
&::after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
background: linear-gradient(to bottom, rgba(255, 255, 255, 0) 60%, #fafafa 100%);
}
}
p {
font-size: .9em;
}
}
@include media-tablet(true) {
.project {
.more-button {
display: flex;
justify-content: center;
align-items: center;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
.btn {
display: none;
}
&:hover {
background: rgba(0, 0, 0, .3);
border-radius: 5px;
.btn {
display: flex;
color: white;
border-style: none;
&:hover {
background-color: #385c8a;
}
}
}
}
}
}
@include media-small {
.project {
display: block;
.project_image {
width: 100%;
height: 250px;
}
.project_content {
height: 125px;
}
.more-button {
display: block;
position: unset;
margin-top: 8px;
height: auto;
left: unset;
top: unset;
.btn {
display: flex;
width: 100%;
border-radius: 0;
border-style: solid;
}
}
}
}
}
}
@keyframes load-project {
from {
transform: translateY(20px);
opacity: .1;
}
to {
transform: translateY(0);
opacity: 1;
}
}
@include media-tablet {
.projects .container {
grid-template-columns: 1fr;
padding: 25px;
column-gap: 0;
row-gap: 20px;
}
}
</style>