feat: add project entry component
- update css - update some styles
This commit is contained in:
@@ -33,10 +33,10 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
|
|
||||||
margin-top: 5rem;
|
margin-top: 5rem;
|
||||||
padding: 2rem;
|
padding: 2rem;
|
||||||
|
|
||||||
background-color: var(--color-footer-background);
|
background-color: var(--color-footer-background);
|
||||||
}
|
}
|
||||||
@@ -64,19 +64,23 @@
|
|||||||
padding: 0.5rem;
|
padding: 0.5rem;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
&:visited {
|
&:hover {
|
||||||
color: inherit;
|
color: var(--color-header-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:visited:not(:hover){
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
width: 1em;
|
width: 1em;
|
||||||
height: 1em;
|
height: 1em;
|
||||||
}
|
}
|
||||||
|
|
||||||
div {
|
div {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
color: var(--color-text-tertiary);
|
color: var(--color-text-tertiary);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -80,7 +80,7 @@
|
|||||||
transition: ease-in-out 0.2s;
|
transition: ease-in-out 0.2s;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: var(--color-accent-primary);
|
color: var(--color-header-hover);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
var(--color-body-background) 0%,
|
var(--color-body-background) 0%,
|
||||||
var(--color-intro-background-secondary) 100%
|
var(--color-profile-background-secondary) 100%
|
||||||
);
|
);
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
@@ -49,8 +49,8 @@
|
|||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
background-image: linear-gradient(
|
background-image: linear-gradient(
|
||||||
to right,
|
to right,
|
||||||
var(--color-intro-image-background-primary) 0%,
|
var(--color-profile-image-background-primary) 0%,
|
||||||
var(--color-intro-image-background-secondary) 100%
|
var(--color-profile-image-background-secondary) 100%
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
|
|
||||||
margin: unset;
|
margin: unset;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
color: var(--color-intro-title-text);
|
color: var(--color-profile-title-text);
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
@@ -87,7 +87,7 @@
|
|||||||
|
|
||||||
.text {
|
.text {
|
||||||
margin: unset;
|
margin: unset;
|
||||||
color: var(--color-intro-text);
|
color: var(--color-profile-text);
|
||||||
font-size: 1.125rem;
|
font-size: 1.125rem;
|
||||||
line-height: 1.625;
|
line-height: 1.625;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { ProjectEntry } from '$lib/types/data';
|
import type { ProjectEntry } from '$lib/types/data';
|
||||||
|
import { MousePointerClick } from '@lucide/svelte';
|
||||||
|
|
||||||
let {
|
let {
|
||||||
title,
|
title,
|
||||||
@@ -9,12 +10,227 @@
|
|||||||
toolsHeadline,
|
toolsHeadline,
|
||||||
tools
|
tools
|
||||||
}: ProjectEntry = $props();
|
}: ProjectEntry = $props();
|
||||||
|
|
||||||
|
function inViewOnce(node: HTMLElement) {
|
||||||
|
const observer = new IntersectionObserver((entries) => {
|
||||||
|
entries.forEach(entry => {
|
||||||
|
if (entry.isIntersecting) {
|
||||||
|
node.classList.add('in-view');
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, { threshold: 1.0 });
|
||||||
|
|
||||||
|
observer.observe(node);
|
||||||
|
|
||||||
|
return {
|
||||||
|
destroy() {
|
||||||
|
observer.disconnect();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<article>
|
<article use:inViewOnce>
|
||||||
|
<div class="content">
|
||||||
|
<div class="front">
|
||||||
|
<span class="icon">
|
||||||
|
<MousePointerClick class="icon" />
|
||||||
|
</span>
|
||||||
|
<span class="title">{title}</span>
|
||||||
|
<span class="description">{description}</span>
|
||||||
|
</div>
|
||||||
|
<div class="back">
|
||||||
|
<div class="tasks">
|
||||||
|
<span class="task-headline">{taskHeadline}</span>
|
||||||
|
<span class="task-description">{tasks}</span>
|
||||||
|
</div>
|
||||||
|
<div class="tools">
|
||||||
|
<span class="tools-headline">{toolsHeadline}</span>
|
||||||
|
<ul class="tools-tags">
|
||||||
|
{#each tools as tool, i (i)}
|
||||||
|
<li class="tools-tags-tag">{tool}</li>
|
||||||
|
{/each}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
article {
|
||||||
|
display: block;
|
||||||
|
border-radius: 1rem;
|
||||||
|
transition: box-shadow ease-in-out 0.1s, transform ease-in-out 0.3s 0s;
|
||||||
|
will-change: rotate;
|
||||||
|
|
||||||
|
perspective: 1000px;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transition: box-shadow ease-in-out 0.1s, transform ease-in-out 0.3s 0.5s;
|
||||||
|
|
||||||
|
transform: translateY(-0.5rem);
|
||||||
|
box-shadow: var(--color-project-card-box-shadow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(article.in-view) {
|
||||||
|
animation: shake 0.4s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
0%, 100% {
|
||||||
|
rotate: 0;
|
||||||
|
}
|
||||||
|
30%, 70% {
|
||||||
|
rotate: 2deg;
|
||||||
|
}
|
||||||
|
40%, 80% {
|
||||||
|
rotate: -2deg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.content {
|
||||||
|
display: grid;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
transition: transform 0.5s;
|
||||||
|
transform-style: preserve-3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
article:hover .content {
|
||||||
|
transform: rotateY(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.front, .back {
|
||||||
|
grid-column: 1;
|
||||||
|
grid-row: 1;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
padding: 1.5rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
|
||||||
|
backface-visibility: hidden;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.front {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to right bottom,
|
||||||
|
var(--color-project-card-front-background-primary) 0%,
|
||||||
|
var(--color-project-card-front-background-secondary) 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
position: absolute;
|
||||||
|
top: 1rem;
|
||||||
|
right: 1rem;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
color: var(--color-profile-title-text);
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.4;
|
||||||
|
font-weight: bold;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.description {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.back {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-content: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 2rem;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
background-image: linear-gradient(
|
||||||
|
to right bottom,
|
||||||
|
var(--color-project-card-back-background-primary) 0%,
|
||||||
|
var(--color-project-card-back-background-secondary) 100%
|
||||||
|
);
|
||||||
|
transform: rotateY(180deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.tasks {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-headline {
|
||||||
|
font-size: 1.25rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.task-description {
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools-headline {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools-tags {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
|
||||||
|
margin: unset;
|
||||||
|
padding: unset;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tools-tags-tag {
|
||||||
|
padding: 0.25rem 0.75rem;
|
||||||
|
border-radius: 1rem;
|
||||||
|
background-color: var(--color-header-border);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -60,4 +60,20 @@
|
|||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-auto-rows: auto;
|
||||||
|
gap: 2rem;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 25rem));
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px) {
|
||||||
|
grid-template-columns: repeat(3, minmax(0, 25rem));
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -5,20 +5,6 @@
|
|||||||
--color-text-secondary: oklch(0.707 0.022 261.325);
|
--color-text-secondary: oklch(0.707 0.022 261.325);
|
||||||
--color-text-tertiary: oklch(0.551 0.027 264.364);
|
--color-text-tertiary: oklch(0.551 0.027 264.364);
|
||||||
|
|
||||||
|
|
||||||
--color-header-border: oklab(0.623 -0.0378409 -0.210628 / 0.3);
|
|
||||||
--color-header-background: oklab(0.21 -0.00316128 -0.0338527 / 0.95);
|
|
||||||
--color-header-hover: oklch(70.7% 0.165 254.624);
|
|
||||||
|
|
||||||
--color-footer-background: oklch(0.13 0.028 261.692);
|
|
||||||
|
|
||||||
--color-intro-background-primary: oklab(0.379 -0.0113992 -0.145554 / 0.2);
|
|
||||||
--color-intro-background-secondary: oklab(0.379 -0.0113992 -0.145554 / 0.2);
|
|
||||||
--color-intro-image-background-primary: oklch(0.623 0.214 259.815);
|
|
||||||
--color-intro-image-background-secondary: oklch(0.511 0.262 276.966);
|
|
||||||
--color-intro-text: oklch(0.967 0.003 264.542);
|
|
||||||
--color-intro-title-text: oklch(0.809 0.105 251.813);
|
|
||||||
|
|
||||||
--color-headline-primary: oklch(0.707 0.165 254.624);
|
--color-headline-primary: oklch(0.707 0.165 254.624);
|
||||||
--color-headline-secondary: oklch(0.673 0.182 276.935);
|
--color-headline-secondary: oklch(0.673 0.182 276.935);
|
||||||
--color-headline-tertiary: oklch(0.714 0.203 305.504);
|
--color-headline-tertiary: oklch(0.714 0.203 305.504);
|
||||||
@@ -28,6 +14,25 @@
|
|||||||
var(--color-headline-secondary) 60%,
|
var(--color-headline-secondary) 60%,
|
||||||
var(--color-headline-tertiary) 100%);
|
var(--color-headline-tertiary) 100%);
|
||||||
|
|
||||||
|
--color-header-border: oklab(0.623 -0.0378409 -0.210628 / 0.3);
|
||||||
|
--color-header-background: oklab(0.21 -0.00316128 -0.0338527 / 0.95);
|
||||||
|
--color-header-hover: oklch(70.7% 0.165 254.624);
|
||||||
|
|
||||||
|
--color-footer-background: oklch(0.13 0.028 261.692);
|
||||||
|
|
||||||
|
--color-profile-background-primary: oklab(0.379 -0.0113992 -0.145554 / 0.2);
|
||||||
|
--color-profile-background-secondary: oklab(0.379 -0.0113992 -0.145554 / 0.2);
|
||||||
|
--color-profile-image-background-primary: oklch(0.623 0.214 259.815);
|
||||||
|
--color-profile-image-background-secondary: oklch(0.511 0.262 276.966);
|
||||||
|
--color-profile-text: oklch(0.967 0.003 264.542);
|
||||||
|
--color-profile-title-text: oklch(0.809 0.105 251.813);
|
||||||
|
|
||||||
|
--color-project-card-front-background-primary: oklch(0.278 0.033 256.848);
|
||||||
|
--color-project-card-front-background-secondary: oklch(0.373 0.034 259.733);
|
||||||
|
--color-project-card-back-background-primary: oklch(0.379 0.146 265.522);
|
||||||
|
--color-project-card-back-background-secondary: oklch(0.359 0.144 278.697);
|
||||||
|
--color-project-card-box-shadow: 0 0 0 0 rgba(0,0,0,0), oklab(0.623 -0.0378409 -0.210628 / 0.5) 0 25px 50px -12px;
|
||||||
|
|
||||||
--z-index-header: 50;
|
--z-index-header: 50;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,3 +52,8 @@ html, body {
|
|||||||
font-family: 'AdwaitaSans', 'AdwaitaMono', sans-serif;
|
font-family: 'AdwaitaSans', 'AdwaitaMono', sans-serif;
|
||||||
scroll-behavior: smooth;
|
scroll-behavior: smooth;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
width: 1em;
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user