CI / ci (push) Successful in 1m30s
Co-authored-by: dev_agent <dev_agent@cubecraftlabs.com> Co-committed-by: dev_agent <dev_agent@cubecraftlabs.com>
32 lines
1.1 KiB
TypeScript
32 lines
1.1 KiB
TypeScript
import { useCallback, useState, useSyncExternalStore } from 'react'
|
||
|
||
export type Breakpoint = 'mobile' | 'tablet' | 'desktop'
|
||
|
||
// The handoff's three layouts: mobile < 768 px, tablet 768–1199 px,
|
||
// desktop ≥ 1200 px.
|
||
export const TABLET_QUERY = '(min-width: 768px)'
|
||
export const DESKTOP_QUERY = '(min-width: 1200px)'
|
||
|
||
// The layout the current viewport calls for, updated as the viewport crosses
|
||
// a breakpoint.
|
||
export function useBreakpoint(): Breakpoint {
|
||
const [lists] = useState(() => ({
|
||
tablet: window.matchMedia(TABLET_QUERY),
|
||
desktop: window.matchMedia(DESKTOP_QUERY),
|
||
}))
|
||
const subscribe = useCallback(
|
||
(onChange: () => void) => {
|
||
lists.tablet.addEventListener('change', onChange)
|
||
lists.desktop.addEventListener('change', onChange)
|
||
return () => {
|
||
lists.tablet.removeEventListener('change', onChange)
|
||
lists.desktop.removeEventListener('change', onChange)
|
||
}
|
||
},
|
||
[lists],
|
||
)
|
||
return useSyncExternalStore(subscribe, () =>
|
||
lists.desktop.matches ? 'desktop' : lists.tablet.matches ? 'tablet' : 'mobile',
|
||
)
|
||
}
|