Better lab card styles

This commit is contained in:
Justin Edmund 2025-06-02 14:43:06 -07:00
parent 69193db45a
commit 53fe4c429f

View file

@ -7,10 +7,48 @@
// Determine if the project is clickable (not list-only) // Determine if the project is clickable (not list-only)
const isClickable = $derived(project.status !== 'list-only') const isClickable = $derived(project.status !== 'list-only')
const projectUrl = $derived(`/labs/${project.slug}`) const projectUrl = $derived(`/labs/${project.slug}`)
// Tilt card functionality
let cardElement: HTMLElement
let isHovering = $state(false)
let transform = $state('')
function handleMouseMove(e: MouseEvent) {
if (!cardElement || !isHovering) return
const rect = cardElement.getBoundingClientRect()
const x = e.clientX - rect.left
const y = e.clientY - rect.top
const centerX = rect.width / 2
const centerY = rect.height / 2
const rotateX = ((y - centerY) / centerY) * -3 // Subtle tilt
const rotateY = ((x - centerX) / centerX) * 3
transform = `perspective(1000px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) scale3d(1.02, 1.02, 1.02)`
}
function handleMouseEnter() {
isHovering = true
}
function handleMouseLeave() {
isHovering = false
transform = 'perspective(1000px) rotateX(0) rotateY(0) scale3d(1, 1, 1)'
}
</script> </script>
{#if isClickable} {#if isClickable}
<a href={projectUrl} class="lab-card clickable"> <a
href={projectUrl}
class="lab-card clickable"
bind:this={cardElement}
onmousemove={handleMouseMove}
onmouseenter={handleMouseEnter}
onmouseleave={handleMouseLeave}
style:transform
>
<div class="card-header"> <div class="card-header">
<div class="project-title-container"> <div class="project-title-container">
<h3 class="project-title">{project.title}</h3> <h3 class="project-title">{project.title}</h3>
@ -69,7 +107,14 @@
{/if} {/if}
</a> </a>
{:else} {:else}
<article class="lab-card"> <article
class="lab-card"
bind:this={cardElement}
onmousemove={handleMouseMove}
onmouseenter={handleMouseEnter}
onmouseleave={handleMouseLeave}
style:transform
>
<div class="card-header"> <div class="card-header">
<div class="project-title-container"> <div class="project-title-container">
<h3 class="project-title">{project.title}</h3> <h3 class="project-title">{project.title}</h3>
@ -135,14 +180,25 @@
flex-direction: column; flex-direction: column;
gap: $unit-3x; gap: $unit-3x;
transition: transition:
transform 0.2s ease, transform 0.15s ease-out,
box-shadow 0.2s ease; box-shadow 0.15s ease-out;
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
transform-style: preserve-3d;
will-change: transform;
// Prevent overflow issues with 3D transforms
-webkit-mask-image: -webkit-radial-gradient(white, black);
mask-image: radial-gradient(white, black);
&:hover { &:hover {
transform: translateY(-2px); box-shadow:
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); 0 10px 30px rgba(0, 0, 0, 0.12),
0 2px 10px rgba(0, 0, 0, 0.08);
.project-title {
color: $red-60;
}
} }
&.clickable { &.clickable {
@ -179,7 +235,7 @@
.project-title { .project-title {
margin: 0; margin: 0;
font-size: 1.25rem; font-size: 1.125rem;
font-weight: 400; font-weight: 400;
color: $grey-00; color: $grey-00;
line-height: 1.3; line-height: 1.3;
@ -190,7 +246,7 @@
} }
.project-year { .project-year {
font-size: 1rem; font-size: 0.875rem;
color: $grey-40; color: $grey-40;
font-weight: 400; font-weight: 400;
white-space: nowrap; white-space: nowrap;
@ -198,7 +254,7 @@
.project-description { .project-description {
margin: 0 0 $unit-3x 0; margin: 0 0 $unit-3x 0;
font-size: 1rem; font-size: 1.125rem;
line-height: 1.5; line-height: 1.5;
color: $grey-20; color: $grey-20;