deer-flow/frontend/src/hooks/use-mobile.ts
Ryker_Feng 7a985f441c
Fix(frontend): Fix mobile workspace and accessibility blockers (#3740)
* fix(frontend): address mobile workspace polish blockers

* fix(frontend): prevent mobile landing overflow

* fix(frontend): keep landing sections within mobile viewport

Section titles used a fixed text-5xl with no word breaking, and the
<section> flex items had default min-width:auto, so wider Linux font
metrics in CI pushed content past the viewport (scrollWidth 345 > 320).
Make titles/subtitles responsive with break-words, constrain section
width with min-w-0, and add an overflow-x-clip guard on the page root.

* fix(frontend): address review feedback on mobile landing PR

- add hamburger Sheet nav below sm: so mobile users keep docs/blog access
- switch useIsMobile to useSyncExternalStore to avoid hydration swap flash
- memoize artifactContent so it isn't rebuilt on every streamed token
- use slot-based key in HeroWordRotate; drop flex-wrap so SuperAgent never orphans at 320px
- delete unused word-rotate.tsx dead code
- move section gutter to <main> for a uniform mobile padding contract
- harden e2e: per-viewport overflow tests, locale-stable artifact selector, focus-ring asserts light vs dark differ

---------

Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
2026-07-06 07:15:35 +08:00

23 lines
568 B
TypeScript

import * as React from "react";
const MOBILE_BREAKPOINT = 768;
const MOBILE_QUERY = `(max-width: ${MOBILE_BREAKPOINT - 1}px)`;
function subscribe(callback: () => void) {
const mql = window.matchMedia(MOBILE_QUERY);
mql.addEventListener("change", callback);
return () => mql.removeEventListener("change", callback);
}
function getSnapshot() {
return window.matchMedia(MOBILE_QUERY).matches;
}
function getServerSnapshot() {
return false;
}
export function useIsMobile() {
return React.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
}