Refocus responsive layouts on compact desktop use
All checks were successful
Deploy Sokko G / deploy (push) Successful in 19s

This commit is contained in:
Shinuwa 2026-10-05 15:47:46 +02:00
parent 96d058293d
commit 0ac1a0974e
27 changed files with 610 additions and 190 deletions

View file

@ -19,6 +19,7 @@ import { useHashRoute } from "./router/hashRouter.js";
import { normalizeCalendarData, normalizeTimerData } from "./features/toolboxes/storage/toolboxStorage.js";
import { useAutoBackup } from "./features/toolboxes/storage/useAutoBackup.js";
import { GlobalMemosTicker } from "./features/toolboxes/GlobalMemosTicker.jsx";
import { useMediaQuery } from "./hooks/useMediaQuery.js";
const assetRecoveryUrl = new URL(window.location.href);
if (assetRecoveryUrl.searchParams.has("_asset-recovery")) {
@ -43,6 +44,8 @@ function getNotificationDuration(message, options = {}) {
function App() {
const route = useHashRoute();
const compactGameLayout = useMediaQuery("(max-width: 1439px)");
const reducedSidebar = useMediaQuery("(max-width: 1024px)");
const { siteContent, siteContentError, games, gamesError, mhwilds, diablo4, aniimo } = useAppData(route);
const [filters, setFilters] = useGameFilters();
const [confirmModal, setConfirmModal] = useState(null);
@ -50,7 +53,8 @@ function App() {
const [autoBackupModalOpen, setAutoBackupModalOpen] = useState(false);
const [linkModalGameId, setLinkModalGameId] = useState("");
const [drawerGameId, setDrawerGameId] = useState("");
const [drawerRoute, setDrawerRoute] = useState(route);
const [drawerVisible, setDrawerVisible] = useState(false);
const [drawerContext, setDrawerContext] = useState({ route, compactGameLayout });
const [image, setImage] = useState(null);
const [pendingTutorialToolboxId, setPendingTutorialToolboxId] = useState("");
const [notifications, setNotifications] = useState([]);
@ -61,11 +65,33 @@ function App() {
const autoBackup = useAutoBackup(store);
const { backupNeeded, requestPermission: requestBackupPermission } = autoBackup;
const guideChecklistStorage = useGuideChecklistStorage(store);
const guideScrollRef = useRef(0);
if (drawerRoute !== route) {
setDrawerRoute(route);
const setGameToolbox = useCallback((gameId) => {
if (gameId) {
if (compactGameLayout && !drawerVisible) guideScrollRef.current = window.scrollY;
setDrawerGameId(gameId);
setDrawerVisible(true);
if (compactGameLayout) window.requestAnimationFrame(() => window.scrollTo({ top: 0, behavior: "auto" }));
return;
}
setDrawerVisible(false);
if (compactGameLayout) {
window.requestAnimationFrame(() => window.scrollTo({ top: guideScrollRef.current, behavior: "auto" }));
} else {
setDrawerGameId("");
}
}, [compactGameLayout, drawerVisible]);
if (drawerContext.route !== route || drawerContext.compactGameLayout !== compactGameLayout) {
setDrawerContext({ route, compactGameLayout });
const activeGameId = route.match(/^\/games\/([^/]+)/)?.[1] || "";
if (activeGameId !== drawerGameId) setDrawerGameId("");
if (activeGameId !== drawerGameId) {
setDrawerGameId("");
setDrawerVisible(false);
} else if (!compactGameLayout && !drawerVisible && drawerGameId) {
setDrawerGameId("");
}
}
const notify = useCallback((message, options = {}) => {
@ -126,7 +152,7 @@ function App() {
setCreateModal,
setConfirmModal,
setLinkModalGameId,
setDrawerGameId,
setDrawerGameId: setGameToolbox,
setImage
});
@ -135,7 +161,7 @@ function App() {
moduleData: store.moduleData,
links: store.links,
route,
drawerGameId,
drawerGameId: drawerVisible ? drawerGameId : "",
normalizeTimerData,
normalizeCalendarData,
textContent: siteContent?.toolboxes?.modules,
@ -173,9 +199,19 @@ function App() {
return (
<GuideChecklistContext.Provider value={{ route, aniimo, mhwilds, diablo4, siteContent, toolboxes: store.toolboxes, links: store.links, moduleData: store.moduleData, guideChecklistStorage, actions }}>
<Shell route={route} content={siteContent} games={games} toolboxes={store.toolboxes} links={store.links} drawerGameId={drawerGameId} actions={actions}>
<AppErrorBoundary route={route}>
<RouteContent
<Shell
route={route}
content={siteContent}
games={games}
drawerGameId={drawerGameId}
drawerVisible={drawerVisible}
compactGameLayout={compactGameLayout}
reducedSidebar={reducedSidebar}
actions={actions}
>
<div className="route-content-view" aria-hidden={compactGameLayout && drawerVisible || undefined} inert={compactGameLayout && drawerVisible || undefined}>
<AppErrorBoundary route={route}>
<RouteContent
route={route}
siteContent={siteContent}
games={games}
@ -202,8 +238,9 @@ function App() {
addImageFiles={actions.addImageFiles}
pendingTutorialToolboxId={pendingTutorialToolboxId}
setPendingTutorialToolboxId={setPendingTutorialToolboxId}
/>
</AppErrorBoundary>
/>
</AppErrorBoundary>
</div>
{drawerGameId && (
<Suspense fallback={null}>
<ToolboxDrawer
@ -219,6 +256,8 @@ function App() {
updateToolbox={actions.updateToolbox}
updateModuleData={store.updateModuleData}
addImageFiles={actions.addImageFiles}
visible={drawerVisible}
compact={compactGameLayout}
/>
</Suspense>
)}
@ -238,7 +277,7 @@ function App() {
setCreateModal={setCreateModal}
linkModalGameId={linkModalGameId}
setLinkModalGameId={setLinkModalGameId}
setDrawerGameId={setDrawerGameId}
setDrawerGameId={setGameToolbox}
storageError={storageError}
setStorageError={setStorageError}
image={image}