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) <noreply@anthropic.com>
This commit is contained in:
Jose Luis
2026-03-21 16:15:29 +01:00
parent f0e7f7f37a
commit 8b193126f7
2 changed files with 8 additions and 4 deletions

View File

@@ -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
</div>
</div>
{fullscreen && (
<FullscreenDrumPad moduleId={moduleId} onClose={onCloseFullscreen} />
{fullscreen && createPortal(
<FullscreenDrumPad moduleId={moduleId} onClose={onCloseFullscreen} />,
document.body
)}
</>
);

View File

@@ -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
</div>
</div>
{fullscreen && (
{fullscreen && createPortal(
<FullscreenPiano
moduleId={moduleId}
initialOctave={octave}
onClose={onCloseFullscreen}
/>
/>,
document.body
)}
</>
);