Better lab card styles
This commit is contained in:
parent
69193db45a
commit
53fe4c429f
1 changed files with 65 additions and 9 deletions
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue