diff --git a/src/routes/Outlet.module.css b/src/routes/Outlet.module.css
index a49842cab0..10002c172d 100644
--- a/src/routes/Outlet.module.css
+++ b/src/routes/Outlet.module.css
@@ -16,7 +16,14 @@
/* If empty state or page is shown (not hidden), router outlet (first column) should have max width */
> div:not(:global(.ion-hide)) ~ ion-router-outlet {
- max-width: 520px;
+ flex: 0 0 var(--first-column-width);
+ max-width: calc(100% - 300px);
+ }
+
+ /* Column divider */
+ > .columnDivider {
+ order: 0;
+ flex: 0 0 auto;
}
/* First column (main content) */
@@ -42,3 +49,32 @@
}
}
}
+
+/* Resizable divider styles */
+.columnDivider {
+ width: 4px;
+ background: var(
+ --ion-toolbar-background,
+ var(--ion-color-step-50, var(--ion-background-color-step-50, #f7f7f7))
+ );
+ cursor: col-resize;
+ position: relative;
+ transition: background-color 0.2s ease;
+}
+
+.columnDivider:hover,
+.columnDivider:active {
+ background: var(--ion-color-light);
+}
+
+.columnDivider::before {
+ content: "";
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ width: 2px;
+ height: 20px;
+ background: var(--ion-color-light);
+ border-radius: 1px;
+}
diff --git a/src/routes/Outlet.tsx b/src/routes/Outlet.tsx
index 71260dcb25..cbfd0aab57 100644
--- a/src/routes/Outlet.tsx
+++ b/src/routes/Outlet.tsx
@@ -15,6 +15,7 @@ import buildPostsRoutes from "./tabs/posts";
import profile from "./tabs/profile";
import search from "./tabs/search";
import settings from "./tabs/settings";
+import ColumnDivider from "./twoColumn/ColumnDivider";
import SecondColumnContent from "./twoColumn/SecondColumnContent";
import styles from "./Outlet.module.css";
@@ -51,6 +52,7 @@ function AppRoutes() {
return (
+ {twoColumnLayoutEnabled &&
}
{twoColumnLayoutEnabled &&
}
{/* This is first (order = -1) in css. Why? See Outlet.module.css */}
diff --git a/src/routes/twoColumn/ColumnDivider.tsx b/src/routes/twoColumn/ColumnDivider.tsx
new file mode 100644
index 0000000000..d4f46c8454
--- /dev/null
+++ b/src/routes/twoColumn/ColumnDivider.tsx
@@ -0,0 +1,85 @@
+import { useEffect, useRef, useState } from "react";
+
+import { useColumnWidth } from "./useColumnWidth";
+
+import styles from "../Outlet.module.css";
+
+interface ColumnDividerProps {
+ onResize?: (width: number) => void;
+}
+
+export default function ColumnDivider({ onResize }: ColumnDividerProps) {
+ const dividerRef = useRef
(null);
+ const [isResizing, setIsResizing] = useState(false);
+ const [startX, setStartX] = useState(0);
+ const [startWidth, setStartWidth] = useState(0);
+ const { updateColumnWidth } = useColumnWidth();
+
+ useEffect(() => {
+ const handleMouseDown = (e: MouseEvent) => {
+ if (e.target === dividerRef.current) {
+ console.log("Mouse down on divider");
+ setIsResizing(true);
+ setStartX(e.clientX);
+
+ // Get current width with fallback to default
+ const currentWidthStr = getComputedStyle(
+ document.documentElement,
+ ).getPropertyValue("--first-column-width");
+ const currentWidth = parseInt(currentWidthStr) || 520; // fallback to 520px
+ console.log(
+ "Current width:",
+ currentWidth,
+ "raw value:",
+ currentWidthStr,
+ );
+ setStartWidth(currentWidth);
+
+ document.body.style.cursor = "col-resize";
+ document.body.style.userSelect = "none";
+ }
+ };
+
+ const handleMouseMove = (e: MouseEvent) => {
+ if (!isResizing) return;
+
+ const deltaX = e.clientX - startX;
+ const newWidth = Math.max(300, Math.min(800, startWidth + deltaX));
+
+ console.log("Resizing to:", newWidth, "delta:", deltaX);
+ updateColumnWidth(newWidth);
+ onResize?.(newWidth);
+ };
+
+ const handleMouseUp = () => {
+ console.log("Mouse up, stopping resize");
+ setIsResizing(false);
+ document.body.style.cursor = "";
+ document.body.style.userSelect = "";
+ };
+
+ const divider = dividerRef.current;
+ if (divider) {
+ divider.addEventListener("mousedown", handleMouseDown);
+ }
+
+ document.addEventListener("mousemove", handleMouseMove);
+ document.addEventListener("mouseup", handleMouseUp);
+
+ return () => {
+ if (divider) {
+ divider.removeEventListener("mousedown", handleMouseDown);
+ }
+ document.removeEventListener("mousemove", handleMouseMove);
+ document.removeEventListener("mouseup", handleMouseUp);
+ };
+ }, [isResizing, startX, startWidth, onResize, updateColumnWidth]);
+
+ return (
+
+ );
+}
diff --git a/src/routes/twoColumn/useColumnWidth.ts b/src/routes/twoColumn/useColumnWidth.ts
new file mode 100644
index 0000000000..50c1f1c69b
--- /dev/null
+++ b/src/routes/twoColumn/useColumnWidth.ts
@@ -0,0 +1,36 @@
+import { useEffect, useState } from "react";
+
+const DEFAULT_WIDTH = 520;
+const MIN_WIDTH = 300;
+const MAX_WIDTH = 800;
+
+export function useColumnWidth() {
+ const [columnWidth, setColumnWidth] = useState(DEFAULT_WIDTH);
+
+ // Initialize the CSS custom property when the component mounts
+ useEffect(() => {
+ document.documentElement.style.setProperty(
+ "--first-column-width",
+ `${DEFAULT_WIDTH}px`,
+ );
+ console.log("Initialized CSS property to:", DEFAULT_WIDTH);
+ }, []);
+
+ const updateColumnWidth = (width: number) => {
+ const clampedWidth = Math.max(MIN_WIDTH, Math.min(MAX_WIDTH, width));
+ console.log("Setting column width to:", clampedWidth);
+ setColumnWidth(clampedWidth);
+ document.documentElement.style.setProperty(
+ "--first-column-width",
+ `${clampedWidth}px`,
+ );
+ console.log(
+ "CSS property set, checking:",
+ getComputedStyle(document.documentElement).getPropertyValue(
+ "--first-column-width",
+ ),
+ );
+ };
+
+ return { columnWidth, updateColumnWidth };
+}