From 8b193126f75e8da751a306ebb32b95abf06ba1b9 Mon Sep 17 00:00:00 2001 From: Jose Luis Date: Sat, 21 Mar 2026 16:15:29 +0100 Subject: [PATCH] fix: render fullscreen overlays via React Portal to document.body The fullscreen piano/drumpad was rendering inside ModuleNode which has CSS transform: scale(zoom). This breaks position: fixed (fixed elements inside a transformed parent position relative to the transform, not the viewport). Using createPortal to document.body fixes this. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/DrumPadWidget.jsx | 6 ++++-- src/components/KeyboardWidget.jsx | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/components/DrumPadWidget.jsx b/src/components/DrumPadWidget.jsx index ed54575..70be250 100644 --- a/src/components/DrumPadWidget.jsx +++ b/src/components/DrumPadWidget.jsx @@ -1,4 +1,5 @@ import React, { useCallback, useState } from 'react'; +import { createPortal } from 'react-dom'; import { triggerKeyboard } from '../engine/audioEngine.js'; // 4x4 pad layout — each pad maps to a MIDI note @@ -99,8 +100,9 @@ export default function DrumPadWidget({ moduleId, fullscreen, onCloseFullscreen - {fullscreen && ( - + {fullscreen && createPortal( + , + document.body )} ); diff --git a/src/components/KeyboardWidget.jsx b/src/components/KeyboardWidget.jsx index 8329fd4..63cc5f2 100644 --- a/src/components/KeyboardWidget.jsx +++ b/src/components/KeyboardWidget.jsx @@ -1,4 +1,5 @@ import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { createPortal } from 'react-dom'; import { triggerKeyboard } from '../engine/audioEngine.js'; import { state } from '../engine/state.js'; @@ -167,12 +168,13 @@ export default function KeyboardWidget({ moduleId, fullscreen, onCloseFullscreen - {fullscreen && ( + {fullscreen && createPortal( + />, + document.body )} );