From cf40870d86ae5dc74fe6e1f9fa3fbaf86804a093 Mon Sep 17 00:00:00 2001 From: thsparks Date: Thu, 22 Feb 2024 16:44:37 -0800 Subject: [PATCH 01/16] Resize mostly working using flexBasis, just odd on window resize. --- teachertool/src/components/MainPanel.tsx | 2 +- teachertool/src/components/SplitPane.tsx | 48 +++++++++++++++++-- .../components/styling/SplitPane.module.scss | 6 ++- 3 files changed, 50 insertions(+), 6 deletions(-) diff --git a/teachertool/src/components/MainPanel.tsx b/teachertool/src/components/MainPanel.tsx index 2438a71ae78d..2a91f96d1cc1 100644 --- a/teachertool/src/components/MainPanel.tsx +++ b/teachertool/src/components/MainPanel.tsx @@ -11,7 +11,7 @@ export const MainPanel: React.FC = () => {
} right={} diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index 034e707b1d36..6666db54ebfb 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -11,11 +11,53 @@ interface IProps { right: React.ReactNode; } -export const SplitPane: React.FC = ({ className, split, left, right }) => { +export const SplitPane: React.FC = ({ className, split, defaultSize, left, right }) => { + const [size, setSize] = React.useState(defaultSize); + const leftRef = React.useRef(null); + + function handleResizeMouse(event: MouseEvent) { + handleResize(event.clientX, event.clientY); + } + + function handleResizeTouch(event: TouchEvent) { + if (event.touches.length >= 1) { + handleResize(event.touches[0].clientX, event.touches[0].clientY); + } + } + + function handleResize(clientX: number, clientY: number) { + const paneRect = leftRef.current?.getBoundingClientRect(); + if (paneRect) { + const newSize = split === "vertical" ? clientX - paneRect.left : clientY - paneRect.top; + setSize(newSize); + } + } + + function addResizeListeners(event: React.MouseEvent | React.TouchEvent) { + event.preventDefault(); + document.addEventListener("mousemove", handleResizeMouse); + document.addEventListener("mouseup", removeResizeListeners); + document.addEventListener("touchmove", handleResizeTouch); + document.addEventListener("touchend", removeResizeListeners); + } + + function removeResizeListeners() { + document.removeEventListener("mousemove", handleResizeMouse); + document.removeEventListener("mouseup", removeResizeListeners); + document.removeEventListener("touchmove", handleResizeTouch); + document.removeEventListener("touchend", removeResizeListeners); + } + return (
-
{left}
-
+
+ {left} +
+
{right}
diff --git a/teachertool/src/components/styling/SplitPane.module.scss b/teachertool/src/components/styling/SplitPane.module.scss index 92ac6878c384..a1f3c960fbb8 100644 --- a/teachertool/src/components/styling/SplitPane.module.scss +++ b/teachertool/src/components/styling/SplitPane.module.scss @@ -9,12 +9,14 @@ } .left-vertical { - flex: 1; + flex-grow: 0; + flex-shrink: 0; overflow: auto; } .right-vertical { - flex: 1; + flex-grow: 1; + flex-shrink: 1; overflow: auto; } From 1de9ef782ee930759254978e9df0dafe6a327c46 Mon Sep 17 00:00:00 2001 From: thsparks Date: Thu, 22 Feb 2024 16:53:24 -0800 Subject: [PATCH 02/16] Use percentage rather than absolute pixels --- teachertool/src/components/SplitPane.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index 6666db54ebfb..7b7a8173865e 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -13,7 +13,7 @@ interface IProps { export const SplitPane: React.FC = ({ className, split, defaultSize, left, right }) => { const [size, setSize] = React.useState(defaultSize); - const leftRef = React.useRef(null); + const containerRef = React.useRef(null); function handleResizeMouse(event: MouseEvent) { handleResize(event.clientX, event.clientY); @@ -26,9 +26,12 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, lef } function handleResize(clientX: number, clientY: number) { - const paneRect = leftRef.current?.getBoundingClientRect(); - if (paneRect) { - const newSize = split === "vertical" ? clientX - paneRect.left : clientY - paneRect.top; + const containerRect = containerRef.current?.getBoundingClientRect(); + if (containerRect) { + const newSize = + split === "vertical" + ? `${(clientX / containerRect.width) * 100}%` + : `${(clientY / containerRect.height) * 100}%`; setSize(newSize); } } @@ -49,8 +52,8 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, lef } return ( -
-
+
+
{left}
Date: Thu, 22 Feb 2024 17:14:08 -0800 Subject: [PATCH 03/16] Save split pane position --- teachertool/src/components/MainPanel.tsx | 12 +++++++++++- teachertool/src/components/SplitPane.tsx | 4 +++- teachertool/src/services/storageService.ts | 18 ++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/teachertool/src/components/MainPanel.tsx b/teachertool/src/components/MainPanel.tsx index 2a91f96d1cc1..a34b51e5ef17 100644 --- a/teachertool/src/components/MainPanel.tsx +++ b/teachertool/src/components/MainPanel.tsx @@ -3,18 +3,28 @@ import css from "./styling/MainPanel.module.scss"; import { SplitPane } from "./SplitPane"; import { RubricWorkspace } from "./RubricWorkspace"; import { ProjectWorkspace } from "./ProjectWorkspace"; +import { getSplitPosition as getLastSplitPosition, setSplitPosition as setLastSplitPosition } from "../services/storageService"; interface IProps {} export const MainPanel: React.FC = () => { + function handleResize(size: number | string) { + setLastSplitPosition(size.toString()); + } + + const lastSavedSplitPosition = getLastSplitPosition() ?? "50%"; + + // TODO still - fix arrow mouse display, figure out why it isn't working with the iframe loaded. Maybe test local storage more (does it redraw a bunch because of this changing after the change in SplitPane?)... + return (
} right={} + onResize={handleResize} />
); diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index 7b7a8173865e..50030b752f2e 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -9,9 +9,10 @@ interface IProps { primary: "left" | "right"; left: React.ReactNode; right: React.ReactNode; + onResize?: (size: number | string) => void; } -export const SplitPane: React.FC = ({ className, split, defaultSize, left, right }) => { +export const SplitPane: React.FC = ({ className, split, defaultSize, left, right, onResize }) => { const [size, setSize] = React.useState(defaultSize); const containerRef = React.useRef(null); @@ -33,6 +34,7 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, lef ? `${(clientX / containerRect.width) * 100}%` : `${(clientY / containerRect.height) * 100}%`; setSize(newSize); + onResize?.(newSize); } } diff --git a/teachertool/src/services/storageService.ts b/teachertool/src/services/storageService.ts index 459d6e02c9f6..7743b0abbeb7 100644 --- a/teachertool/src/services/storageService.ts +++ b/teachertool/src/services/storageService.ts @@ -10,6 +10,7 @@ import { Rubric } from "../types/rubric"; const KEY_PREFIX = "teachertool"; const AUTORUN_KEY = [KEY_PREFIX, "autorun"].join("/"); const LAST_ACTIVE_RUBRIC_KEY = [KEY_PREFIX, "lastActiveRubric"].join("/"); +const SPLIT_POSITION_KEY = [KEY_PREFIX, "splitPosition"].join("/"); function getValue(key: string, defaultValue?: string): string | undefined { return localStorage.getItem(key) || defaultValue; @@ -148,6 +149,23 @@ export function setLastActiveRubricName(name: string) { } } +export function getSplitPosition(): string { + try { + return getValue(SPLIT_POSITION_KEY) ?? ""; + } catch (e) { + logError(ErrorCode.localStorageReadError, e); + return ""; + } +} + +export function setSplitPosition(position: string) { + try { + setValue(SPLIT_POSITION_KEY, position); + } catch (e) { + logError(ErrorCode.localStorageWriteError, e); + } +} + export async function getRubric(name: string): Promise { const db = await getDb; From 85a0b33929130b147930df75184bd2a68a2f6410 Mon Sep 17 00:00:00 2001 From: thsparks Date: Fri, 23 Feb 2024 09:55:15 -0800 Subject: [PATCH 04/16] Only store new size on end of resizing. --- teachertool/src/components/MainPanel.tsx | 8 +++--- teachertool/src/components/SplitPane.tsx | 34 ++++++++++++++++-------- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/teachertool/src/components/MainPanel.tsx b/teachertool/src/components/MainPanel.tsx index a34b51e5ef17..283b15851892 100644 --- a/teachertool/src/components/MainPanel.tsx +++ b/teachertool/src/components/MainPanel.tsx @@ -8,13 +8,15 @@ import { getSplitPosition as getLastSplitPosition, setSplitPosition as setLastSp interface IProps {} export const MainPanel: React.FC = () => { - function handleResize(size: number | string) { + function handleResizeEnd(size: number | string) { setLastSplitPosition(size.toString()); } const lastSavedSplitPosition = getLastSplitPosition() ?? "50%"; - // TODO still - fix arrow mouse display, figure out why it isn't working with the iframe loaded. Maybe test local storage more (does it redraw a bunch because of this changing after the change in SplitPane?)... + // TODO still: + // figure out why it isn't working with the iframe loaded. + // Double click to restore defaults. return (
@@ -24,7 +26,7 @@ export const MainPanel: React.FC = () => { primary={"left"} left={} right={} - onResize={handleResize} + onResizeEnd={handleResizeEnd} />
); diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index 50030b752f2e..c33949cc8575 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -9,13 +9,20 @@ interface IProps { primary: "left" | "right"; left: React.ReactNode; right: React.ReactNode; - onResize?: (size: number | string) => void; + onResizeEnd?: (size: number | string) => void; } -export const SplitPane: React.FC = ({ className, split, defaultSize, left, right, onResize }) => { +export const SplitPane: React.FC = ({ className, split, defaultSize, left, right, onResizeEnd }) => { const [size, setSize] = React.useState(defaultSize); + const [isResizing, setIsResizing] = React.useState(false); const containerRef = React.useRef(null); + React.useEffect(() => { + if (!isResizing) { + onResizeEnd?.(size); + } + }, [isResizing]); + function handleResizeMouse(event: MouseEvent) { handleResize(event.clientX, event.clientY); } @@ -33,24 +40,29 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, lef split === "vertical" ? `${(clientX / containerRect.width) * 100}%` : `${(clientY / containerRect.height) * 100}%`; + + console.log("newSize", newSize); setSize(newSize); - onResize?.(newSize); } } - function addResizeListeners(event: React.MouseEvent | React.TouchEvent) { + function startResizing(event: React.MouseEvent | React.TouchEvent) { event.preventDefault(); document.addEventListener("mousemove", handleResizeMouse); - document.addEventListener("mouseup", removeResizeListeners); + document.addEventListener("mouseup", endResizing); document.addEventListener("touchmove", handleResizeTouch); - document.addEventListener("touchend", removeResizeListeners); + document.addEventListener("touchend", endResizing); + + setIsResizing(true); } - function removeResizeListeners() { + function endResizing() { document.removeEventListener("mousemove", handleResizeMouse); - document.removeEventListener("mouseup", removeResizeListeners); + document.removeEventListener("mouseup", endResizing); document.removeEventListener("touchmove", handleResizeTouch); - document.removeEventListener("touchend", removeResizeListeners); + document.removeEventListener("touchend", endResizing); + + setIsResizing(false); } return ( @@ -60,8 +72,8 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, lef
From e09fd1923dfd70efe57f26174fb8acee3a6ea037 Mon Sep 17 00:00:00 2001 From: thsparks Date: Fri, 23 Feb 2024 10:12:06 -0800 Subject: [PATCH 05/16] Prevent other areas of the page from consuming mouse events --- teachertool/src/components/MainPanel.tsx | 1 - teachertool/src/components/SplitPane.tsx | 13 ++++++++----- .../src/components/styling/SplitPane.module.scss | 5 +++++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/teachertool/src/components/MainPanel.tsx b/teachertool/src/components/MainPanel.tsx index 283b15851892..bb2d15508107 100644 --- a/teachertool/src/components/MainPanel.tsx +++ b/teachertool/src/components/MainPanel.tsx @@ -15,7 +15,6 @@ export const MainPanel: React.FC = () => { const lastSavedSplitPosition = getLastSplitPosition() ?? "50%"; // TODO still: - // figure out why it isn't working with the iframe loaded. // Double click to restore defaults. return ( diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index c33949cc8575..674cd55835a5 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -16,6 +16,7 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, lef const [size, setSize] = React.useState(defaultSize); const [isResizing, setIsResizing] = React.useState(false); const containerRef = React.useRef(null); + const overlayRef = React.useRef(null); React.useEffect(() => { if (!isResizing) { @@ -70,14 +71,16 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, lef
{left}
-
+
{right}
+ + {/* + This overlay hack is necessary to prevent any other parts of the page (particularly iframes) + from intercepting the mouse events while resizing. We simply add a transparent div over everything. + */} +
); }; diff --git a/teachertool/src/components/styling/SplitPane.module.scss b/teachertool/src/components/styling/SplitPane.module.scss index a1f3c960fbb8..56c35877fff4 100644 --- a/teachertool/src/components/styling/SplitPane.module.scss +++ b/teachertool/src/components/styling/SplitPane.module.scss @@ -66,3 +66,8 @@ height: 5px; cursor: ns-resize; } + +.resizing-overlay { + position: 'absolute'; + inset: 0; +} From c1e69434d9f23d0de5f68108add50541ad732dd5 Mon Sep 17 00:00:00 2001 From: thsparks Date: Fri, 23 Feb 2024 10:18:09 -0800 Subject: [PATCH 06/16] Add reset to default functionality on double click --- teachertool/src/components/MainPanel.tsx | 9 ++++++--- teachertool/src/components/SplitPane.tsx | 14 ++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/teachertool/src/components/MainPanel.tsx b/teachertool/src/components/MainPanel.tsx index bb2d15508107..ebaf0ed55d31 100644 --- a/teachertool/src/components/MainPanel.tsx +++ b/teachertool/src/components/MainPanel.tsx @@ -8,20 +8,23 @@ import { getSplitPosition as getLastSplitPosition, setSplitPosition as setLastSp interface IProps {} export const MainPanel: React.FC = () => { + const defaultSize = "50%"; + function handleResizeEnd(size: number | string) { setLastSplitPosition(size.toString()); } - const lastSavedSplitPosition = getLastSplitPosition() ?? "50%"; + const lastSavedSplitPosition = getLastSplitPosition() ?? defaultSize; // TODO still: - // Double click to restore defaults. + // Min and Max sizes. return (
} right={} diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index 674cd55835a5..53ca605c04b3 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -5,15 +5,16 @@ import { classList } from "react-common/components/util"; interface IProps { className?: string; split: "horizontal" | "vertical"; - defaultSize: number | string; + defaultSize: number | string; // The size to reset to when double clicking the splitter. + startingSize?: number | string; // The size to use initially when creating the splitter. Defaults to `defaultSize`. primary: "left" | "right"; left: React.ReactNode; right: React.ReactNode; onResizeEnd?: (size: number | string) => void; } -export const SplitPane: React.FC = ({ className, split, defaultSize, left, right, onResizeEnd }) => { - const [size, setSize] = React.useState(defaultSize); +export const SplitPane: React.FC = ({ className, split, defaultSize, startingSize, left, right, onResizeEnd }) => { + const [size, setSize] = React.useState(startingSize ?? defaultSize); const [isResizing, setIsResizing] = React.useState(false); const containerRef = React.useRef(null); const overlayRef = React.useRef(null); @@ -66,12 +67,17 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, lef setIsResizing(false); } + function setToDefaultSize() { + setSize(defaultSize); + onResizeEnd?.(defaultSize); + } + return (
{left}
-
+
{right}
From 232a9be093af44cda81030019d619af40073bc5e Mon Sep 17 00:00:00 2001 From: thsparks Date: Fri, 23 Feb 2024 10:35:16 -0800 Subject: [PATCH 07/16] Min and max sizes --- teachertool/src/components/MainPanel.tsx | 5 +++-- teachertool/src/components/SplitPane.tsx | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/teachertool/src/components/MainPanel.tsx b/teachertool/src/components/MainPanel.tsx index ebaf0ed55d31..54dcd15bee4c 100644 --- a/teachertool/src/components/MainPanel.tsx +++ b/teachertool/src/components/MainPanel.tsx @@ -16,8 +16,7 @@ export const MainPanel: React.FC = () => { const lastSavedSplitPosition = getLastSplitPosition() ?? defaultSize; - // TODO still: - // Min and Max sizes. + // TODO : fix horizontal (offset within the view?) return (
@@ -28,6 +27,8 @@ export const MainPanel: React.FC = () => { primary={"left"} left={} right={} + leftMinSize="5rem" + rightMinSize="5rem" onResizeEnd={handleResizeEnd} />
diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index 53ca605c04b3..8570991cd13d 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -10,10 +10,12 @@ interface IProps { primary: "left" | "right"; left: React.ReactNode; right: React.ReactNode; + leftMinSize?: number | string; + rightMinSize?: number | string; onResizeEnd?: (size: number | string) => void; } -export const SplitPane: React.FC = ({ className, split, defaultSize, startingSize, left, right, onResizeEnd }) => { +export const SplitPane: React.FC = ({ className, split, defaultSize, startingSize, left, right, leftMinSize, rightMinSize, onResizeEnd }) => { const [size, setSize] = React.useState(startingSize ?? defaultSize); const [isResizing, setIsResizing] = React.useState(false); const containerRef = React.useRef(null); @@ -72,9 +74,21 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta onResizeEnd?.(defaultSize); } + const leftStyle: React.CSSProperties = { flexBasis: size }; + if (split === "vertical") { + leftStyle.minWidth = leftMinSize; + + // Setting right's minWidth doesn't work because left is still allowed + // to expand beyond it. Instead, set left's maxWidth. + leftStyle.maxWidth = `calc(100% - ${rightMinSize})`; + } else { + leftStyle.minHeight = leftMinSize; + leftStyle.maxHeight = `calc(100% - ${rightMinSize})`; + } + return (
-
+
{left}
From 99b0c4923aed84fdea533a37dd0614a792bbf029 Mon Sep 17 00:00:00 2001 From: thsparks Date: Fri, 23 Feb 2024 11:11:44 -0800 Subject: [PATCH 08/16] Fix horizontal view --- teachertool/src/components/SplitPane.tsx | 6 +++--- teachertool/src/components/styling/SplitPane.module.scss | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index 8570991cd13d..b6e89670cd7e 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -42,8 +42,8 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta if (containerRect) { const newSize = split === "vertical" - ? `${(clientX / containerRect.width) * 100}%` - : `${(clientY / containerRect.height) * 100}%`; + ? `${((clientX - containerRect.left) / containerRect.width) * 100}%` + : `${((clientY - containerRect.top) / containerRect.height) * 100}%`; console.log("newSize", newSize); setSize(newSize); @@ -100,7 +100,7 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta This overlay hack is necessary to prevent any other parts of the page (particularly iframes) from intercepting the mouse events while resizing. We simply add a transparent div over everything. */} -
+
); }; diff --git a/teachertool/src/components/styling/SplitPane.module.scss b/teachertool/src/components/styling/SplitPane.module.scss index 56c35877fff4..bb4f623ff924 100644 --- a/teachertool/src/components/styling/SplitPane.module.scss +++ b/teachertool/src/components/styling/SplitPane.module.scss @@ -51,12 +51,14 @@ } .left-horizontal { - flex: 1; + flex-grow: 0; + flex-shrink: 0; overflow: auto; } .right-horizontal { - flex: 1; + flex-grow: 1; + flex-shrink: 1; overflow: auto; } From fff61e44bd7ef922c59c1d5459608f244a61da14 Mon Sep 17 00:00:00 2001 From: thsparks Date: Fri, 23 Feb 2024 11:11:56 -0800 Subject: [PATCH 09/16] Remove comment --- teachertool/src/components/MainPanel.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/teachertool/src/components/MainPanel.tsx b/teachertool/src/components/MainPanel.tsx index 54dcd15bee4c..37e9177466c7 100644 --- a/teachertool/src/components/MainPanel.tsx +++ b/teachertool/src/components/MainPanel.tsx @@ -16,8 +16,6 @@ export const MainPanel: React.FC = () => { const lastSavedSplitPosition = getLastSplitPosition() ?? defaultSize; - // TODO : fix horizontal (offset within the view?) - return (
Date: Fri, 23 Feb 2024 11:40:03 -0800 Subject: [PATCH 10/16] scss-ify --- teachertool/src/components/SplitPane.tsx | 10 +- .../components/styling/SplitPane.module.scss | 125 ++++++++---------- 2 files changed, 59 insertions(+), 76 deletions(-) diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index b6e89670cd7e..667341d118c3 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -87,14 +87,14 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta } return ( -
-
+
+
{left}
-
-
+
+
-
{right}
+
{right}
{/* This overlay hack is necessary to prevent any other parts of the page (particularly iframes) diff --git a/teachertool/src/components/styling/SplitPane.module.scss b/teachertool/src/components/styling/SplitPane.module.scss index bb4f623ff924..631b1d961e21 100644 --- a/teachertool/src/components/styling/SplitPane.module.scss +++ b/teachertool/src/components/styling/SplitPane.module.scss @@ -1,75 +1,58 @@ - -// TODO make this scssy - -.split-pane-vertical { - display: flex; - flex-direction: row; - height: 100%; - width: 100%; -} - -.left-vertical { - flex-grow: 0; - flex-shrink: 0; - overflow: auto; -} - -.right-vertical { - flex-grow: 1; - flex-shrink: 1; - overflow: auto; -} - -.splitter-vertical { - background-color: var(--pxt-content-accent); - width: 1px; -} - -.splitter-vertical-inner { - position: relative; - background-color: transparent; - transition: background-color 0.2s ease; - left: -2.5px; - width: 5px; - height: 100%; - cursor: ew-resize; -} - -.splitter-vertical-inner:hover { - background-color: var(--pxt-content-foreground); - transition: background-color 0.2s ease; - transition-delay: 0.2s; -} - -/* Horizontal split pane */ - -.split-pane-horizontal { - display: flex; - flex-direction: column; - height: 100%; - width: 100%; -} - -.left-horizontal { - flex-grow: 0; - flex-shrink: 0; - overflow: auto; -} - -.right-horizontal { - flex-grow: 1; - flex-shrink: 1; - overflow: auto; -} - -.splitter-horizontal { - flex: 0 0 1px; - background-color: var(--pxt-headerbar-background); - height: 5px; - cursor: ns-resize; +.split-pane { + display: flex; + height: 100%; + width: 100%; + + .left { + flex-grow: 0; + flex-shrink: 0; + overflow: auto; + } + + .right { + flex-grow: 1; + flex-shrink: 1; + overflow: auto; + } +} + +.split-vertical { + flex-direction: row; + + .splitter { + background-color: var(--pxt-content-accent); + width: 1px; + + .splitter-inner { + position: relative; + background-color: transparent; + transition: background-color 0.2s ease; + left: -2.5px; + width: 5px; + height: 100%; + cursor: ew-resize; + + &:hover { + background-color: var(--pxt-content-foreground); + transition: background-color 0.2s ease; + transition-delay: 0.2s; + } + } + } +} + +.split-horizontal { + flex-direction: column; + + .splitter { + flex: 0 0 1px; + background-color: var(--pxt-headerbar-background); + height: 5px; + cursor: ns-resize; + } } .resizing-overlay { - position: 'absolute'; - inset: 0; + position: absolute; + inset: 0; } From 5861ba0f2415883ad79d338b7ff24742e59e4c19 Mon Sep 17 00:00:00 2001 From: thsparks Date: Fri, 23 Feb 2024 12:31:10 -0800 Subject: [PATCH 11/16] Fix double clicking --- teachertool/src/components/SplitPane.tsx | 20 ++++++++++--------- .../components/styling/SplitPane.module.scss | 6 ++++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index 667341d118c3..6496ef445849 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -19,7 +19,6 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta const [size, setSize] = React.useState(startingSize ?? defaultSize); const [isResizing, setIsResizing] = React.useState(false); const containerRef = React.useRef(null); - const overlayRef = React.useRef(null); React.useEffect(() => { if (!isResizing) { @@ -45,7 +44,6 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta ? `${((clientX - containerRect.left) / containerRect.width) * 100}%` : `${((clientY - containerRect.top) / containerRect.height) * 100}%`; - console.log("newSize", newSize); setSize(newSize); } } @@ -90,17 +88,21 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta
{left} + + {/* + This overlay is necessary to prevent any other parts of the page (particularly iframes) + from intercepting the mouse events while resizing. We simply add a transparent div over the + left and right sections. + */} +
-
{right}
- - {/* - This overlay hack is necessary to prevent any other parts of the page (particularly iframes) - from intercepting the mouse events while resizing. We simply add a transparent div over everything. - */} -
+
+ {right} +
+
); }; diff --git a/teachertool/src/components/styling/SplitPane.module.scss b/teachertool/src/components/styling/SplitPane.module.scss index 631b1d961e21..156353618aee 100644 --- a/teachertool/src/components/styling/SplitPane.module.scss +++ b/teachertool/src/components/styling/SplitPane.module.scss @@ -4,12 +4,14 @@ width: 100%; .left { + position: relative; flex-grow: 0; flex-shrink: 0; overflow: auto; } .right { + position: relative; flex-grow: 1; flex-shrink: 1; overflow: auto; @@ -27,8 +29,8 @@ position: relative; background-color: transparent; transition: background-color 0.2s ease; - left: -2.5px; - width: 5px; + left: -3px; + width: 6px; height: 100%; cursor: ew-resize; From 17a76f06bfb57ec67050c4ad6ee2b475e5ac1e98 Mon Sep 17 00:00:00 2001 From: thsparks Date: Fri, 23 Feb 2024 14:23:02 -0800 Subject: [PATCH 12/16] Fix double clicking on the splitter without messing up hover detection on the splitter --- teachertool/src/components/SplitPane.tsx | 41 ++++++++++++------- .../components/styling/SplitPane.module.scss | 15 +++---- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index 6496ef445849..e74d3157b8be 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -15,7 +15,17 @@ interface IProps { onResizeEnd?: (size: number | string) => void; } -export const SplitPane: React.FC = ({ className, split, defaultSize, startingSize, left, right, leftMinSize, rightMinSize, onResizeEnd }) => { +export const SplitPane: React.FC = ({ + className, + split, + defaultSize, + startingSize, + left, + right, + leftMinSize, + rightMinSize, + onResizeEnd, +}) => { const [size, setSize] = React.useState(startingSize ?? defaultSize); const [isResizing, setIsResizing] = React.useState(false); const containerRef = React.useRef(null); @@ -44,6 +54,7 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta ? `${((clientX - containerRect.left) / containerRect.width) * 100}%` : `${((clientY - containerRect.top) / containerRect.height) * 100}%`; + setIsResizing(true); // Do this here rather than inside startResizing to prevent interference with double click detection. setSize(newSize); } } @@ -54,8 +65,6 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta document.addEventListener("mouseup", endResizing); document.addEventListener("touchmove", handleResizeTouch); document.addEventListener("touchend", endResizing); - - setIsResizing(true); } function endResizing() { @@ -88,21 +97,23 @@ export const SplitPane: React.FC = ({ className, split, defaultSize, sta
{left} - - {/* - This overlay is necessary to prevent any other parts of the page (particularly iframes) - from intercepting the mouse events while resizing. We simply add a transparent div over the - left and right sections. - */} -
-
+
-
- {right} -
-
+
{right}
+ + {/* + This overlay is necessary to prevent any other parts of the page (particularly iframes) + from intercepting the mouse events while resizing. We simply add a transparent div over the + left and right sections. + */} +
); }; diff --git a/teachertool/src/components/styling/SplitPane.module.scss b/teachertool/src/components/styling/SplitPane.module.scss index 156353618aee..a5b3fbb4c80c 100644 --- a/teachertool/src/components/styling/SplitPane.module.scss +++ b/teachertool/src/components/styling/SplitPane.module.scss @@ -4,18 +4,24 @@ width: 100%; .left { - position: relative; flex-grow: 0; flex-shrink: 0; overflow: auto; } .right { - position: relative; flex-grow: 1; flex-shrink: 1; overflow: auto; } + + .resizing-overlay { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + } } .split-vertical { @@ -53,8 +59,3 @@ cursor: ns-resize; } } - -.resizing-overlay { - position: absolute; - inset: 0; -} From bbc0130c058536d91623f4d146aa543a16367d16 Mon Sep 17 00:00:00 2001 From: thsparks Date: Fri, 23 Feb 2024 14:25:19 -0800 Subject: [PATCH 13/16] Refactoring + Prettier --- teachertool/src/components/MainPanel.tsx | 2 +- teachertool/src/services/storageService.ts | 4 ++-- teachertool/src/state/helpers.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/teachertool/src/components/MainPanel.tsx b/teachertool/src/components/MainPanel.tsx index 37e9177466c7..dcc08ba7c643 100644 --- a/teachertool/src/components/MainPanel.tsx +++ b/teachertool/src/components/MainPanel.tsx @@ -3,7 +3,7 @@ import css from "./styling/MainPanel.module.scss"; import { SplitPane } from "./SplitPane"; import { RubricWorkspace } from "./RubricWorkspace"; import { ProjectWorkspace } from "./ProjectWorkspace"; -import { getSplitPosition as getLastSplitPosition, setSplitPosition as setLastSplitPosition } from "../services/storageService"; +import { getLastSplitPosition, setLastSplitPosition } from "../services/storageService"; interface IProps {} diff --git a/teachertool/src/services/storageService.ts b/teachertool/src/services/storageService.ts index 7743b0abbeb7..33162c2fbf10 100644 --- a/teachertool/src/services/storageService.ts +++ b/teachertool/src/services/storageService.ts @@ -149,7 +149,7 @@ export function setLastActiveRubricName(name: string) { } } -export function getSplitPosition(): string { +export function getLastSplitPosition(): string { try { return getValue(SPLIT_POSITION_KEY) ?? ""; } catch (e) { @@ -158,7 +158,7 @@ export function getSplitPosition(): string { } } -export function setSplitPosition(position: string) { +export function setLastSplitPosition(position: string) { try { setValue(SPLIT_POSITION_KEY, position); } catch (e) { diff --git a/teachertool/src/state/helpers.ts b/teachertool/src/state/helpers.ts index 93b9d5aead91..c836e6b2d2ce 100644 --- a/teachertool/src/state/helpers.ts +++ b/teachertool/src/state/helpers.ts @@ -71,7 +71,7 @@ export function getSelectableCatalogCriteria(state: AppState): CatalogCriteria[] state.catalog?.filter( catalogCriteria => ((catalogCriteria.parameters && catalogCriteria.parameters.length > 0) || - !usedCatalogCriteria.includes(catalogCriteria.id)) && + !usedCatalogCriteria.includes(catalogCriteria.id)) && !catalogCriteria.hideInCatalog ) ?? [] ); From 7230ad541ed0bbbf9e140ac81c085957ff827132 Mon Sep 17 00:00:00 2001 From: thsparks Date: Mon, 26 Feb 2024 13:52:44 -0800 Subject: [PATCH 14/16] Make min sizes non-optional --- teachertool/src/components/SplitPane.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index e74d3157b8be..c553d2bd31a1 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -10,8 +10,8 @@ interface IProps { primary: "left" | "right"; left: React.ReactNode; right: React.ReactNode; - leftMinSize?: number | string; - rightMinSize?: number | string; + leftMinSize: number | string; + rightMinSize: number | string; onResizeEnd?: (size: number | string) => void; } From 2dc8a7adc998c446e07c1754911c904e82f47b88 Mon Sep 17 00:00:00 2001 From: thsparks Date: Mon, 26 Feb 2024 13:53:34 -0800 Subject: [PATCH 15/16] Remove default value when lastSavedPosition is null. --- teachertool/src/components/MainPanel.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/teachertool/src/components/MainPanel.tsx b/teachertool/src/components/MainPanel.tsx index dcc08ba7c643..aef72e4d91d4 100644 --- a/teachertool/src/components/MainPanel.tsx +++ b/teachertool/src/components/MainPanel.tsx @@ -14,8 +14,7 @@ export const MainPanel: React.FC = () => { setLastSplitPosition(size.toString()); } - const lastSavedSplitPosition = getLastSplitPosition() ?? defaultSize; - + const lastSavedSplitPosition = getLastSplitPosition(); return (
Date: Mon, 26 Feb 2024 15:13:08 -0800 Subject: [PATCH 16/16] Move setResizing up --- teachertool/src/components/SplitPane.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/teachertool/src/components/SplitPane.tsx b/teachertool/src/components/SplitPane.tsx index c553d2bd31a1..3ee7b3ae932f 100644 --- a/teachertool/src/components/SplitPane.tsx +++ b/teachertool/src/components/SplitPane.tsx @@ -49,12 +49,11 @@ export const SplitPane: React.FC = ({ function handleResize(clientX: number, clientY: number) { const containerRect = containerRef.current?.getBoundingClientRect(); if (containerRect) { + setIsResizing(true); // Do this here rather than inside startResizing to prevent interference with double click detection. const newSize = split === "vertical" ? `${((clientX - containerRect.left) / containerRect.width) * 100}%` : `${((clientY - containerRect.top) / containerRect.height) * 100}%`; - - setIsResizing(true); // Do this here rather than inside startResizing to prevent interference with double click detection. setSize(newSize); } }