diff --git a/frontend/src/css/main.css b/frontend/src/css/main.css index 829708e..2f6302a 100644 --- a/frontend/src/css/main.css +++ b/frontend/src/css/main.css @@ -274,14 +274,16 @@ ============================================================= */ /* Element appear animation keyframes - Safari optimized */ -/* Note: element-fade-in must NOT include transform as it conflicts with - element positioning (translate(-50%, -50%)) causing position shift */ @-webkit-keyframes element-fade-in { from { opacity: 0; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } to { opacity: 1; + -webkit-transform: translate3d(0, 0, 0); + transform: translate3d(0, 0, 0); } } diff --git a/frontend/src/hooks/useElementEffects.ts b/frontend/src/hooks/useElementEffects.ts index a3fd828..7c2b0f1 100644 --- a/frontend/src/hooks/useElementEffects.ts +++ b/frontend/src/hooks/useElementEffects.ts @@ -6,7 +6,7 @@ * handles state-based style application via JavaScript events. */ -import { useCallback, useState, useEffect, useRef } from 'react'; +import { useCallback, useState, useEffect } from 'react'; import type { CSSProperties } from 'react'; import { buildHoverStyle, @@ -83,20 +83,13 @@ export function useElementEffects( isClickPersisted: false, }); - // Track previous resetKey to avoid running on initial mount - const prevResetKeyRef = useRef(resetKey); - // Reset reveal state and click-persisted state when resetKey changes (e.g., page navigation) - // Only run when resetKey actually CHANGES, not on initial mount (to avoid re-render during animation) useEffect(() => { - if (prevResetKeyRef.current !== resetKey) { - setState((prev) => ({ - ...prev, - isRevealed: false, - isClickPersisted: false, - })); - prevResetKeyRef.current = resetKey; - } + setState((prev) => ({ + ...prev, + isRevealed: false, + isClickPersisted: false, + })); }, [resetKey]); const onMouseEnter = useCallback(() => { diff --git a/frontend/src/lib/elementEffects.ts b/frontend/src/lib/elementEffects.ts index ea13b77..a22262d 100644 --- a/frontend/src/lib/elementEffects.ts +++ b/frontend/src/lib/elementEffects.ts @@ -113,58 +113,13 @@ export type EffectPropName = (typeof EFFECT_PROPS)[number]; /** * Build base transition style for smooth state changes. - * Uses specific properties instead of 'all' to avoid affecting positioning transforms. */ export function buildTransitionStyle( effects: Partial, ): CSSProperties { const duration = normalizeDuration(effects.hoverTransitionDuration) || '0.2s'; - - // Build list of properties to transition based on what's configured - const transitionProps: string[] = []; - - // Always include opacity if any effect might change it - if ( - effects.hoverOpacity || - effects.focusOpacity || - effects.activeOpacity || - effects.hoverReveal - ) { - transitionProps.push('opacity'); - } - - // Include transform only for scale effects (not positioning) - if (effects.hoverScale || effects.focusScale || effects.activeScale) { - transitionProps.push('transform'); - } - - // Background color - if (effects.hoverBackgroundColor || effects.activeBackgroundColor) { - transitionProps.push('background-color'); - } - - // Text color - if (effects.hoverColor) { - transitionProps.push('color'); - } - - // Box shadow - if (effects.hoverBoxShadow || effects.focusBoxShadow) { - transitionProps.push('box-shadow'); - } - - // Outline - if (effects.focusOutline) { - transitionProps.push('outline'); - } - - // If no specific properties, return empty (no transition needed) - if (transitionProps.length === 0) { - return {}; - } - return { - transition: transitionProps.map((p) => `${p} ${duration} ease`).join(', '), + transition: `all ${duration} ease`, }; }