From 53fe4c429f416750b796635be21a115fba0e8e24 Mon Sep 17 00:00:00 2001 From: Justin Edmund Date: Mon, 2 Jun 2025 14:43:06 -0700 Subject: [PATCH] Better lab card styles --- src/lib/components/LabCard.svelte | 74 +++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 9 deletions(-) diff --git a/src/lib/components/LabCard.svelte b/src/lib/components/LabCard.svelte index 385e5ae..9acfe46 100644 --- a/src/lib/components/LabCard.svelte +++ b/src/lib/components/LabCard.svelte @@ -7,10 +7,48 @@ // Determine if the project is clickable (not list-only) const isClickable = $derived(project.status !== 'list-only') 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)' + } {#if isClickable} - +

{project.title}

@@ -69,7 +107,14 @@ {/if}
{:else} -
+

{project.title}

@@ -135,14 +180,25 @@ flex-direction: column; gap: $unit-3x; transition: - transform 0.2s ease, - box-shadow 0.2s ease; + transform 0.15s ease-out, + box-shadow 0.15s ease-out; text-decoration: none; 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 { - transform: translateY(-2px); - box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1); + box-shadow: + 0 10px 30px rgba(0, 0, 0, 0.12), + 0 2px 10px rgba(0, 0, 0, 0.08); + + .project-title { + color: $red-60; + } } &.clickable { @@ -179,7 +235,7 @@ .project-title { margin: 0; - font-size: 1.25rem; + font-size: 1.125rem; font-weight: 400; color: $grey-00; line-height: 1.3; @@ -190,7 +246,7 @@ } .project-year { - font-size: 1rem; + font-size: 0.875rem; color: $grey-40; font-weight: 400; white-space: nowrap; @@ -198,7 +254,7 @@ .project-description { margin: 0 0 $unit-3x 0; - font-size: 1rem; + font-size: 1.125rem; line-height: 1.5; color: $grey-20;