first pass at iOS improvements

Hunter
Friday, December 19th, 2025 at 3:01 PM

index.html+41-74

index.html
  2  <html lang="en">
  3  <head>
  4  	<meta charset="UTF-8">
    -	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  5 +	<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
  6  	<title>Web Workshop</title>
  7  	<link rel="icon" href="resources/rollerskate.png">
  8  	<link rel="manifest" href="manifest.json">

 31  			box-sizing: border-box;
 32  		}
 33  
 34 +		html, body {
 35 +			overscroll-behavior: none;
 36 +			background-color: var(--editor-bg);
 37 +		}
 38 +
 39 +		html {
 40 +			height: 100%;
 41 +		}
 42 +
 43  		body {
 44  			font-family: monospace;
 45  			background: var(--bg-color);
 46  			color: var(--text-color);
    -			height: 100vh;
 47 +			height: 100%;
 48  			display: flex;
 49  			overflow: hidden;
 50  		}
 51  
 52  		.editor-pane {
 53  			width: 50%;
    -			height: 100vh;
 54 +			height: 100%;
 55  			position: relative;
 56  		}
 57  
 58  		.preview-pane {
 59  			width: 50%;
    -			height: 100vh;
 60 +			height: 100%;
 61  			position: relative;
 62  		}
 63  

184  			body {
185  				flex-direction: column;
186  			}
    -			
187 +
188  			.editor-pane {
189  				width: 100%;
    -				height: 50vh;
190 +				height: 50%;
191  				order: 2;
192  			}
    -			
193 +
194  			.preview-pane {
195  				width: 100%;
    -				height: 50vh;
196 +				height: 50%;
197  				order: 1;
198 +				padding-top: env(safe-area-inset-top);
199  			}
200  		}
201  
    -		/* Mobile keyboard state - portrait mode (height > width) */
    -		@media (pointer: coarse) and (max-aspect-ratio: 1/1), (pointer: none) and (max-aspect-ratio: 1/1) {
202 +		/* Mobile: fullscreen editor when keyboard is open */
203 +		@media (pointer: coarse), (pointer: none) {
204  			body.mobile-keyboard-open .preview-pane {
205  				display: none;
206  			}
    -			
    -			body.mobile-keyboard-open .editor-pane {
    -				height: var(--visible-height, 100vh);
    -				order: 1;
    -				overflow: hidden;
    -			}
    -		}
207  
    -		/* Mobile keyboard state - landscape mode (width > height) */
    -		@media (pointer: coarse) and (min-aspect-ratio: 1/1), (pointer: none) and (min-aspect-ratio: 1/1) {
    -			body.mobile-keyboard-open .preview-pane {
    -				display: none;
    -			}
    -			
208  			body.mobile-keyboard-open .editor-pane {
209 +				position: fixed;
210 +				top: 0;
211 +				left: 0;
212  				width: 100%;
    -				height: var(--visible-height, 100vh);
213 +				height: 100%;
214  				order: 1;
    -				overflow: hidden;
215 +				overscroll-behavior: none;
216  			}
217  		}
218  

598  				parent: document.getElementById('editor')
599  			});
600  
    -			// Track editor focus for mobile keyboard behavior
    -			editorView.contentDOM.addEventListener('focus', function() {
    -				isEditorFocused = true;
    -				handleViewportChange(); // Check if keyboard is already open
    -			});
    -			
    -			editorView.contentDOM.addEventListener('blur', function() {
    -				isEditorFocused = false;
    -				handleViewportChange(); // Exit fullscreen mode if keyboard is open
    -			});
    -			
601  			// Initial render
602  			updatePreview();
    -			
603 +
604 +			// Track editor focus for mobile keyboard detection
605 +			editorView.contentDOM.addEventListener('focus', () => { isEditorFocused = true; });
606 +			editorView.contentDOM.addEventListener('blur', () => { isEditorFocused = false; });
607 +
608  			// Focus the editor
609  			editorView.focus();
610  			

618  		}
619  
620  		// Mobile keyboard detection
    -		let initialViewportHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight;
    -		let keyboardOpenThreshold = 150; // pixels
    -		let isEditorFocused = false;
    -		let wasKeyboardOpen = false;
    -		
621  		function isMobileDevice() {
622  			return window.matchMedia("(pointer: coarse), (pointer: none)").matches;
623  		}
    -		
624 +
625 +		let initialViewportHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight;
626 +		let isEditorFocused = false;
627 +
628  		function handleViewportChange() {
629  			if (!isMobileDevice()) return;
    -			
630 +
631  			const currentHeight = window.visualViewport ? window.visualViewport.height : window.innerHeight;
    -			
    -			// Detect potential orientation change: very large height difference when no keyboard activity
    -			// Use a higher threshold to avoid interfering with keyboard detection
    -			if (!wasKeyboardOpen && !isEditorFocused && Math.abs(initialViewportHeight - currentHeight) > 300) {
    -				initialViewportHeight = currentHeight;
    -			}
    -			
632  			const heightDifference = initialViewportHeight - currentHeight;
    -			const isKeyboardOpen = heightDifference > keyboardOpenThreshold;
    -			
    -			// Only activate fullscreen editor mode if the editor is focused
633 +			const isKeyboardOpen = heightDifference > 150;
634 +
635 +			const wasFullscreen = document.body.classList.contains('mobile-keyboard-open');
636 +
637  			if (isKeyboardOpen && isEditorFocused) {
638  				document.body.classList.add('mobile-keyboard-open');
    -				// Set CSS custom property for the visible height
    -				document.documentElement.style.setProperty('--visible-height', `${currentHeight}px`);
    -				// Match editor background color
    -				document.body.style.backgroundColor = 'var(--editor-bg)';
    -				wasKeyboardOpen = true;
    -			} else if (wasKeyboardOpen && !isKeyboardOpen) {
    -				// Only run this when transitioning from keyboard open to closed
639 +			} else if (!isKeyboardOpen) {
640  				document.body.classList.remove('mobile-keyboard-open');
    -				// Reset to full viewport height
    -				document.documentElement.style.setProperty('--visible-height', '100vh');
    -				// Reset background color
    -				document.body.style.backgroundColor = '';
    -				// Blur the editor only if it was focused to prevent keyboard from reopening
    -				if (isEditorFocused) {
    -					editorView.contentDOM.blur();
    -				}
    -				// Update preview when keyboard closes to show any changes made while typing
    -				updatePreview();
    -				wasKeyboardOpen = false;
641  			}
642  		}
    -		
    -		// Listen for viewport changes
643 +
644  		if (window.visualViewport) {
645  			window.visualViewport.addEventListener('resize', handleViewportChange);
646  		} else {