implement requested hover and blink behaviors

This commit is contained in:
vndangkhoa 2026-04-29 16:21:08 +07:00
parent 9a7323eb28
commit f556b7dcc0
2 changed files with 25 additions and 6 deletions

View file

@ -11,17 +11,30 @@ function getRandomColor(isDark) {
function TetrisPiece({ piece, isDark }) { function TetrisPiece({ piece, isDark }) {
const [color, setColor] = useState(null); const [color, setColor] = useState(null);
const [showText, setShowText] = useState(false); const [showText, setShowText] = useState(false);
const [isHovered, setIsHovered] = useState(false);
const [isMobile, setIsMobile] = useState(() => window.innerWidth <= 500);
const isCV = piece.label === 'cv'; const isCV = piece.label === 'cv';
const isFeatured = piece.featured; const isFeatured = piece.featured;
const alwaysShowText = true; const alwaysShowText = true;
// Update mobile state on resize
useEffect(() => {
const handleResize = () => {
setIsMobile(window.innerWidth <= 500);
};
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
const handleMouseEnter = () => { const handleMouseEnter = () => {
if (!isCV) setColor(piece.hoverColor); if (!isCV) setColor(piece.hoverColor);
setShowText(true); setShowText(true);
setIsHovered(true);
}; };
const handleMouseLeave = () => { const handleMouseLeave = () => {
if (!isCV) setColor(null); if (!isCV) setColor(null);
setShowText(false); setShowText(false);
setIsHovered(false);
}; };
const handleClick = (e) => { const handleClick = (e) => {
@ -31,8 +44,9 @@ function TetrisPiece({ piece, isDark }) {
} }
}; };
const bgColor = piece.label === 'cv' ? piece.color : (piece.blinkColor || piece.color); // Start with background color (will be overridden by animation for mobile)
const rowDelay = piece.startY * 4; const bgColor = piece.label === 'cv' ? piece.color : (isDark ? piece.colorDark : piece.color);
const rowDelay = piece.startY * 8;
const textColor = '#ffffff'; const textColor = '#ffffff';
const isStatic = piece.label === 'cv' || piece.featured; const isStatic = piece.label === 'cv' || piece.featured;
@ -47,10 +61,14 @@ function TetrisPiece({ piece, isDark }) {
animationFillMode: 'forwards', animationFillMode: 'forwards',
}; };
const bgStyle = { // For desktop: use hoverColor when hovering, otherwise gray
// For mobile: use blinkColor for animation (will start dim via animation)
const bgStyle = {
position: 'absolute', position: 'absolute',
inset: 0, inset: 0,
backgroundColor: color || bgColor, backgroundColor: isDark || isMobile
? (color || bgColor) // Use actual color for blink animation
: (isHovered ? (piece.hoverColor || color) : '#cccccc'), // Hover color or gray
transition: 'background-color 0.15s ease', transition: 'background-color 0.15s ease',
}; };

View file

@ -203,7 +203,8 @@ body {
opacity: 0.15; opacity: 0.15;
} }
} }
.tetris-board > div { /* Only apply duration override to elements that have both dropIn and blink animations */
.tetris-board > div:not([style*="dropIn 0.5s ease-out forwards"]) {
animation-duration: 0.5s, 8s !important; animation-duration: 0.5s, 8s !important;
} }
} }