fixed controls buttons positioning in presentations

This commit is contained in:
Dmitri 2026-04-30 10:47:59 +02:00
parent 2bc7b64707
commit e1f032b123
2 changed files with 42 additions and 3 deletions

View File

@ -34,6 +34,10 @@ interface RuntimeControlsProps {
pages?: PreloadPage[];
isFullscreen: boolean;
toggleFullscreen: () => void;
/** Canvas width in pixels (for positioning relative to canvas) */
canvasWidth?: number;
/** Canvas height in pixels (for positioning relative to canvas) */
canvasHeight?: number;
}
/**
@ -381,12 +385,31 @@ function useCounterZoom() {
return scale;
}
/**
* Hook to get viewport dimensions
*/
function useViewportSize() {
const [size, setSize] = useState({ width: 0, height: 0 });
useEffect(() => {
const update = () => {
setSize({ width: window.innerWidth, height: window.innerHeight });
};
update();
window.addEventListener('resize', update);
return () => window.removeEventListener('resize', update);
}, []);
return size;
}
/**
* RuntimeControls - Main component for presentation controls
*
* Renders offline toggle and fullscreen button using fixed pixel values
* to maintain usable size regardless of canvas scaling.
* Uses visualViewport API to counter pinch-zoom scaling on mobile.
* Positions controls relative to the canvas area (not viewport edges).
*/
export default function RuntimeControls({
projectId,
@ -395,14 +418,28 @@ export default function RuntimeControls({
pages,
isFullscreen,
toggleFullscreen,
canvasWidth = 0,
canvasHeight = 0,
}: RuntimeControlsProps) {
// Counter-scale to resist pinch-zoom
const counterScale = useCounterZoom();
const viewport = useViewportSize();
// Calculate position relative to centered canvas
// Canvas is centered with: left: 50%, top: 50%, transform: translate(-50%, -50%)
// So we offset from viewport edge by (viewport - canvas) / 2 + padding
const padding = 16;
const rightOffset = canvasWidth > 0 && viewport.width > 0
? (viewport.width - canvasWidth) / 2 + padding
: padding;
const topOffset = canvasHeight > 0 && viewport.height > 0
? (viewport.height - canvasHeight) / 2 + padding
: padding;
const containerStyle: CSSProperties = {
position: 'fixed',
top: 16,
right: 16,
top: topOffset,
right: rightOffset,
display: 'flex',
alignItems: 'center',
gap: 8,

View File

@ -92,7 +92,7 @@ export default function RuntimePresentation({
// Canvas scale for responsive UI elements and letterbox mode
// Uses page's design dimensions (saved at constructor save time) for presentation isolation
const { cssVars, letterboxStyles, isPortrait, showRotatePrompt } =
const { cssVars, letterboxStyles, isPortrait, showRotatePrompt, canvasWidth, canvasHeight } =
useCanvasScale({
designWidth: currentPage?.design_width ?? undefined,
designHeight: currentPage?.design_height ?? undefined,
@ -774,6 +774,8 @@ export default function RuntimePresentation({
pages={pages}
isFullscreen={isFullscreen}
toggleFullscreen={toggleFullscreen}
canvasWidth={canvasWidth}
canvasHeight={canvasHeight}
/>
{/* Toast notifications for offline download status */}