diff --git a/frontend/src/components/Constructor/CanvasElement.tsx b/frontend/src/components/Constructor/CanvasElement.tsx index f72695b..2cd6173 100644 --- a/frontend/src/components/Constructor/CanvasElement.tsx +++ b/frontend/src/components/Constructor/CanvasElement.tsx @@ -21,6 +21,7 @@ import type { CanvasElement as CanvasElementType } from '../../types/constructor import type { ResolvedTransitionSettings } from '../../types/transition'; import type { PreloadCacheProvider } from '../../hooks/video'; import { isInfoPanelElementType } from '../../lib/elementDefaults'; +import { normalizeZIndexValue } from '../../lib/elementStyles'; interface CanvasElementProps { element: CanvasElementType; @@ -136,6 +137,10 @@ const CanvasElement: React.FC = ({ top: `${yClamped}%`, transform: 'translate(-50%, -50%)', }; + const zIndex = normalizeZIndexValue(element.zIndex); + if (zIndex !== undefined) { + positionStyle.zIndex = zIndex; + } // Add appear animation to outer div (ALWAYS - for WYSIWYG) // Animation is applied to outer div to keep positioning hack working diff --git a/frontend/src/components/RuntimeElement.tsx b/frontend/src/components/RuntimeElement.tsx index 893e3cd..fa87a0f 100644 --- a/frontend/src/components/RuntimeElement.tsx +++ b/frontend/src/components/RuntimeElement.tsx @@ -20,6 +20,7 @@ import type { CanvasElement } from '../types/constructor'; import type { ResolvedTransitionSettings } from '../types/transition'; import type { PreloadCacheProvider } from '../hooks/video'; import { isInfoPanelElementType } from '../lib/elementDefaults'; +import { normalizeZIndexValue } from '../lib/elementStyles'; interface RuntimeElementProps { element: CanvasElement; @@ -115,6 +116,10 @@ const RuntimeElement: React.FC = ({ transform: `translate(-50%, -50%)${rotation ? ` rotate(${rotation}deg)` : ''}`, pointerEvents: 'auto', }; + const zIndex = normalizeZIndexValue(element.zIndex); + if (zIndex !== undefined) { + positionStyle.zIndex = zIndex; + } // Add appear animation to outer div // Animation stays on outer div to keep positioning hack working diff --git a/frontend/src/lib/elementStyles.ts b/frontend/src/lib/elementStyles.ts index 629d862..1d18ee0 100644 --- a/frontend/src/lib/elementStyles.ts +++ b/frontend/src/lib/elementStyles.ts @@ -267,6 +267,16 @@ const getTrimmedValue = (value: unknown): string => { return String(value).trim(); }; +export const normalizeZIndexValue = ( + value: unknown, +): CSSProperties['zIndex'] | undefined => { + const zIndexValue = getTrimmedValue(value); + if (!zIndexValue) return undefined; + + const parsed = Number(zIndexValue); + return Number.isFinite(parsed) ? parsed : undefined; +}; + /** * Build React CSSProperties from element style properties. * Handles type coercion for special properties like opacity and zIndex. @@ -326,13 +336,8 @@ export function buildElementStyle( } // Handle zIndex (needs numeric conversion, already in style from loop but override with number) - const zIndexValue = getTrimmedValue(source.zIndex); - if (zIndexValue) { - const parsed = Number(zIndexValue); - if (Number.isFinite(parsed)) { - style.zIndex = parsed; - } - } + const zIndex = normalizeZIndexValue(source.zIndex); + if (zIndex !== undefined) style.zIndex = zIndex; return style; }