diff --git a/apps/scandic-web/components/MyPages/DigitalTeamMemberCard/Content.tsx b/apps/scandic-web/components/MyPages/DigitalTeamMemberCard/Content.tsx index d182b91e4..dad772335 100644 --- a/apps/scandic-web/components/MyPages/DigitalTeamMemberCard/Content.tsx +++ b/apps/scandic-web/components/MyPages/DigitalTeamMemberCard/Content.tsx @@ -1,11 +1,6 @@ -import { - type CSSProperties, - type MouseEvent, - type TouchEvent, - useEffect, - useRef, - useState, -} from "react" +"use client" + +import { useEffect, useRef, useState } from "react" import { useIntl } from "react-intl" import { Typography } from "@scandic-hotels/design-system/Typography" @@ -27,6 +22,7 @@ export default function DigitalTeamMemberCardContent({ const cardRef = useRef(null) const [isHovering, setIsHovering] = useState(false) const [coords, setCoords] = useState({ x: 0, y: 0 }) + const shimmerRef = useRef(null) const [rect, setRect] = useState({ top: 0, left: 0, @@ -38,8 +34,6 @@ export default function DigitalTeamMemberCardContent({ y: 0, toJSON() {}, }) - let ticking = false - let animationFrame = 0 useEffect(() => { const observer = new ResizeObserver( @@ -56,82 +50,67 @@ export default function DigitalTeamMemberCardContent({ } }, []) - function requestTick( - evt: MouseEvent | TouchEvent - ) { - if (!ticking) { - animationFrame = requestAnimationFrame(update(evt)) + function onInteractionMove(e: React.MouseEvent | React.TouchEvent) { + let x, y + if ("touches" in e) { + x = e.touches[0].clientX - rect.left + y = e.touches[0].clientY - rect.top + } else { + x = e.clientX - rect.left + y = e.clientY - rect.top } - ticking = true - } - - function onInteractionMove( - evt: MouseEvent | TouchEvent - ) { - requestTick(evt) - } - - function update( - evt: MouseEvent | TouchEvent - ) { - return () => { - let x, y - if ("touches" in evt) { - x = evt.touches[0].clientX - rect.left - y = evt.touches[0].clientY - rect.top - } else { - x = evt.clientX - rect.left - y = evt.clientY - rect.top - } - setCoords({ x, y }) - } - } - - function getShimmerStyle(): CSSProperties { - const { x, y } = coords - const oppositeX = 100 - (x / rect.width) * 100 - const oppositeY = 100 - (y / rect.height) * 100 - return { - background: `radial-gradient(circle at ${oppositeX}% ${oppositeY}%, rgb(233 171 163 / 40%) 0%, rgb(255 255 255 / 0%) 50%)`, - opacity: isHovering ? 1 : 0, - } - } - - function getSkewStyle(): CSSProperties { - const { x, y } = coords const centerX = rect.width / 2 const centerY = rect.height / 2 - const rotateY = ((x - centerX) / centerX) * 5 // Max 5 degrees - const rotateX = ((centerY - y) / centerY) * 5 // Max 5 degrees - return { - transform: isHovering - ? `rotateX(${rotateX}deg) rotateY(${rotateY}deg)` - : "rotateX(0) rotateY(0)", + const rotateY = ((x - centerX) / centerX) * 8 + const rotateX = ((centerY - y) / centerY) * 8 + + // Update shimmer position to be in the opposite corner + if (shimmerRef.current) { + // Calculate opposite position (invert percentage within bounds) + const oppositeX = 100 - (x / rect.width) * 100 + const oppositeY = 100 - (y / rect.height) * 100 + + shimmerRef.current.style.background = `radial-gradient( + circle at ${oppositeX}% ${oppositeY}%, + rgba(233, 171, 163, 0.4) 0%, + rgba(255, 255, 255, 0) 50% + )` } + setCoords({ x: rotateX, y: rotateY }) } - function handleInteractionStart() { + function onInteractionStart() { setIsHovering(true) } - function handleInteractionEnd() { + function onInteractionEnd() { setIsHovering(false) - cancelAnimationFrame(animationFrame) + setCoords({ x: 0, y: 0 }) } return (
-
-
+
+
diff --git a/apps/scandic-web/components/MyPages/DigitalTeamMemberCard/digitalTeamMemberCard.module.css b/apps/scandic-web/components/MyPages/DigitalTeamMemberCard/digitalTeamMemberCard.module.css index 6fac9ed0d..b8ff1602e 100644 --- a/apps/scandic-web/components/MyPages/DigitalTeamMemberCard/digitalTeamMemberCard.module.css +++ b/apps/scandic-web/components/MyPages/DigitalTeamMemberCard/digitalTeamMemberCard.module.css @@ -28,6 +28,7 @@ .shimmer { position: absolute; inset: 0; + pointer-events: none; z-index: 3; opacity: 0; transition: opacity 0.3s ease; @@ -35,16 +36,18 @@ } .card { + touch-action: none; overflow: hidden; border-radius: var(--Corner-radius-lg); - box-shadow: 0 2px 1px rgb(255 255 255 / 11%) inset; padding: var(--Space-x2); height: 400px; width: 327px; max-width: 100%; color: var(--Text-Brand-OnPrimary-3-Accent); background-color: var(--Surface-Brand-Primary-1-OnSurface-Default); - box-shadow: 0 4px 44px rgb(0 0 0 / 25%); + box-shadow: + 0 2px 1px rgb(255 255 255 / 11%) inset, + 0 4px 44px rgb(0 0 0 / 25%); transition: transform 0.3s ease-out; will-change: transform; user-select: none;