hide fullscreen controls on iOS/devices without Fullscreen API

iOS Safari doesn't support requestFullscreen. Detect support and:
- Intro page: show single START button instead of FULLSCREEN/WINDOWED
- AppLayout: hide the global fullscreen button entirely

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
main
name 2026-04-12 01:55:57 -07:00
parent 3190891d6e
commit e5552e72f7
3 changed files with 44 additions and 22 deletions

View File

@ -1,15 +1,18 @@
import { useCallback, useEffect, useState } from 'react'
import { Outlet } from 'react-router-dom'
import { supportsFullscreen } from '../lib/platform'
import styles from './AppLayout.module.css'
export function AppLayout() {
const canFullscreen = supportsFullscreen()
const [isFullscreen, setIsFullscreen] = useState(!!document.fullscreenElement)
useEffect(() => {
if (!canFullscreen) return
const onChange = () => setIsFullscreen(!!document.fullscreenElement)
document.addEventListener('fullscreenchange', onChange)
return () => document.removeEventListener('fullscreenchange', onChange)
}, [])
}, [canFullscreen])
const goFullscreen = useCallback(() => {
document.documentElement.requestFullscreen().catch(() => {})
@ -20,7 +23,7 @@ export function AppLayout() {
<main className={styles.main}>
<Outlet />
</main>
{!isFullscreen && (
{canFullscreen && !isFullscreen && (
<button
type="button"
className={styles.fullscreenBtn}

View File

@ -0,0 +1,3 @@
export function supportsFullscreen(): boolean {
return !!document.documentElement.requestFullscreen
}

View File

@ -2,6 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import { ROUTE_PATHS } from '../app/route-paths'
import { playSound, SFX_BUTTON_DEFAULT } from '../lib/sounds'
import { supportsFullscreen } from '../lib/platform'
import styles from './IntroPage.module.css'
const SPONSORS = [
@ -121,26 +122,41 @@ export function IntroPage() {
{cameraReady && (
<div className={styles.actionsRow}>
<button
type="button"
className={`${styles.btn} ${styles.btnPrimary} font-title`}
onClick={() => {
playSound(SFX_BUTTON_DEFAULT)
goFullscreen()
}}
>
FULLSCREEN
</button>
<button
type="button"
className={`${styles.btn} ${styles.btnSecondary} font-title`}
onClick={() => {
playSound(SFX_BUTTON_DEFAULT)
goWindowed()
}}
>
WINDOWED
</button>
{supportsFullscreen() ? (
<>
<button
type="button"
className={`${styles.btn} ${styles.btnPrimary} font-title`}
onClick={() => {
playSound(SFX_BUTTON_DEFAULT)
goFullscreen()
}}
>
FULLSCREEN
</button>
<button
type="button"
className={`${styles.btn} ${styles.btnSecondary} font-title`}
onClick={() => {
playSound(SFX_BUTTON_DEFAULT)
goWindowed()
}}
>
WINDOWED
</button>
</>
) : (
<button
type="button"
className={`${styles.btn} ${styles.btnPrimary} font-title`}
onClick={() => {
playSound(SFX_BUTTON_DEFAULT)
goWindowed()
}}
>
START
</button>
)}
</div>
)}