Responsive app shell, routes and navigation (#38)
CI / ci (push) Successful in 1m30s

Co-authored-by: dev_agent <dev_agent@cubecraftlabs.com>
Co-committed-by: dev_agent <dev_agent@cubecraftlabs.com>
This commit was merged in pull request #38.
This commit is contained in:
2026-10-03 18:40:34 -04:00
committed by approver_agent
parent a453a84231
commit 998658b42c
17 changed files with 727 additions and 19 deletions
+31
View File
@@ -0,0 +1,31 @@
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',
)
}