From 852ab28e31d13e6b01295174b6882ffad449c785 Mon Sep 17 00:00:00 2001 From: trafficlunar Date: Wed, 12 Feb 2025 16:19:54 +0000 Subject: [PATCH] fix: sidebar layout on mobile --- src/components/sidebar/BlockSelector.tsx | 24 ++++++++++++--- src/components/sidebar/index.tsx | 39 ++++++++++++++++++------ src/pages/AppPage.tsx | 13 +++++++- 3 files changed, 60 insertions(+), 16 deletions(-) diff --git a/src/components/sidebar/BlockSelector.tsx b/src/components/sidebar/BlockSelector.tsx index 047beff..6b92044 100644 --- a/src/components/sidebar/BlockSelector.tsx +++ b/src/components/sidebar/BlockSelector.tsx @@ -8,6 +8,7 @@ import { ToolContext } from "@/context/Tool"; import { useBlockData } from "@/hooks/useBlockData"; import { useTextures } from "@/hooks/useTextures"; +import { Application } from "pixi.js"; interface Props { stageWidth: number; @@ -19,6 +20,8 @@ function BlockSelector({ stageWidth, searchInput }: Props) { const { isDark } = useContext(ThemeContext); const { selectedBlock, setSelectedBlock } = useContext(ToolContext); + const [app, setApp] = useState(); + const [hoverPosition, setHoverPosition] = useState(null); const [selectedBlockPosition, setSelectedBlockPosition] = useState({ x: 0, y: 0 }); @@ -44,6 +47,13 @@ function BlockSelector({ stageWidth, searchInput }: Props) { setSelectedBlockPosition(position); }, [searchInput, selectedBlock]); + useEffect(() => { + if (!app?.renderer?.view?.style) return; + + // Can't set it in props for some reason + app.renderer.view.style.touchAction = "auto"; + }, [app]); + if (filteredBlocks.length == 0) { return (
@@ -59,12 +69,18 @@ function BlockSelector({ stageWidth, searchInput }: Props) { height={Math.ceil(Object.keys(blockData).length / blocksPerColumn) * (32 + 2) + 8} options={{ backgroundAlpha: 0 }} onMouseLeave={() => setHoverPosition(null)} + onMount={setApp} > {filteredBlocks.map((block, index) => { const texture = textures[block]; const { x, y } = getBlockPosition(index); + const onClick = () => { + setSelectedBlock(block); + setSelectedBlockPosition({ x, y }); + }; + return ( setHoverPosition({ x, y })} - click={() => { - setSelectedBlock(block); - setSelectedBlockPosition({ x, y }); - }} + mouseover={() => setHoverPosition({ x, y })} + click={onClick} + tap={onClick} /> ); })} diff --git a/src/components/sidebar/index.tsx b/src/components/sidebar/index.tsx index 578e14e..d656fae 100644 --- a/src/components/sidebar/index.tsx +++ b/src/components/sidebar/index.tsx @@ -1,5 +1,6 @@ import { useContext, useEffect, useRef, useState } from "react"; -import { GripVerticalIcon } from "lucide-react"; +import { isMobile, useMobileOrientation } from "react-device-detect"; +import { GripHorizontalIcon, GripVerticalIcon } from "lucide-react"; import { SettingsContext } from "@/context/Settings"; @@ -17,6 +18,12 @@ import BlockSelector from "./BlockSelector"; function Sidebar() { const { settings } = useContext(SettingsContext); + const { isLandscape } = useMobileOrientation(); + const isMobileView = isMobile && !isLandscape; + + // For mobile + const [height, setHeight] = useState(300); + // For horizontal screens const [width, setWidth] = useState(300); const [resizing, setResizing] = useState(false); @@ -31,17 +38,22 @@ function Sidebar() { const onMouseDown = () => { setResizing(true); - document.body.style.cursor = "ew-resize"; + document.body.style.cursor = isMobileView ? "ns-resize" : "ew-resize"; + document.body.style.touchAction = "none"; + document.body.style.userSelect = "none"; }; const onMouseUp = () => { setResizing(false); document.body.style.cursor = "auto"; + document.body.style.touchAction = "auto"; + document.body.style.userSelect = "auto"; }; - const onMouseMove = (e: MouseEvent) => { + const onMouseMove = (e: PointerEvent) => { if (!resizing) return; - setWidth(() => Math.min(Math.max(window.innerWidth - e.clientX, 200), 1000)); + if (isMobileView) setHeight(() => Math.min(Math.max(window.innerHeight - e.clientY, 200), 500)); + setWidth(() => Math.min(Math.max(window.innerWidth - e.clientX, 200), 500)); }; useEffect(() => { @@ -83,14 +95,21 @@ function Sidebar() { <> {(settings.historyPanel || settings.colorPicker || settings.blockReplacer || settings.toolSettings || settings.blockSelector) && (
- + {isMobileView ? : }
{(settings.historyPanel || settings.colorPicker || settings.blockReplacer) && ( @@ -127,14 +146,14 @@ function Sidebar() { {settings.toolSettings && ( <> - + {settings.blockSelector && } )} {settings.blockSelector && ( <> setSearchInput(e.target.value)} /> - + diff --git a/src/pages/AppPage.tsx b/src/pages/AppPage.tsx index b6b091b..fd09c6c 100644 --- a/src/pages/AppPage.tsx +++ b/src/pages/AppPage.tsx @@ -1,3 +1,5 @@ +import { isMobile, useMobileOrientation } from "react-device-detect"; + import { CanvasProvider } from "@/context/Canvas"; import { HistoryProvider } from "@/context/History"; import { LoadingProvider } from "@/context/Loading"; @@ -13,6 +15,9 @@ import Canvas from "@/components/canvas/Canvas"; import Sidebar from "@/components/sidebar"; function AppPage() { + const { isLandscape } = useMobileOrientation(); + const isMobileView = isMobile && !isLandscape; + return ( @@ -23,7 +28,13 @@ function AppPage() { -
+