mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 05:26:47 +00:00
ab343b0a7b
The phone shell was chosen by width alone, and most phones are wider than 767px in landscape, so turning one swapped the whole route tree for the desktop planner and an open sheet, its input and the map position were lost. The phone query now also covers a touch screen under 500px tall, which no tablet is. It lives in one place: the shell, the planner and todo hooks, the warnings banner, dialog focus and the stylesheets read it, and six components that measured the window once on mount now follow it.
40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { useState, useEffect } from 'react'
|
|
|
|
/**
|
|
* The phone shell's viewport: narrower than the md breakpoint (768px), or a
|
|
* touch screen short enough to be a phone on its side.
|
|
*
|
|
* Width alone flipped a phone into the desktop planner the moment it was
|
|
* turned: most phones are wider than 767px in landscape. That swapped the
|
|
* whole route tree, so an open sheet, what was typed into it and the map's
|
|
* position were gone. A tablet stays where it was, since none is under 500px
|
|
* tall, and a desktop window keeps following its width, since its pointer is
|
|
* fine.
|
|
*
|
|
* The phone rules in `index.css` repeat this query; keep them in step.
|
|
*/
|
|
export const PHONE_QUERY = '(max-width: 767px), (pointer: coarse) and (max-height: 500px)'
|
|
|
|
/** Whether the phone shell applies right now, for code that is not a component. */
|
|
export function isPhoneViewport(): boolean {
|
|
return typeof window !== 'undefined' && typeof window.matchMedia === 'function' && window.matchMedia(PHONE_QUERY).matches
|
|
}
|
|
|
|
/**
|
|
* True while the phone shell applies (see {@link PHONE_QUERY}). Reactive:
|
|
* follows viewport resizes and orientation changes via matchMedia.
|
|
*/
|
|
export function useIsPhone(): boolean {
|
|
const [isPhone, setIsPhone] = useState(isPhoneViewport)
|
|
|
|
useEffect(() => {
|
|
const mq = window.matchMedia(PHONE_QUERY)
|
|
const handler = (e: MediaQueryListEvent) => setIsPhone(e.matches)
|
|
setIsPhone(mq.matches)
|
|
mq.addEventListener('change', handler)
|
|
return () => mq.removeEventListener('change', handler)
|
|
}, [])
|
|
|
|
return isPhone
|
|
}
|