authorgravatar for olivier.melcher@gmail.comOlivier Melcher <olivier.melcher@gmail.com> 2026-07-17 13:40:24-05:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-07-17 18:40:24+00:00
loga7f6d97b94d2e12b10081760063768f715f87e96
tree00951ca4ef1bccc03c3ec733da580981761ce9a4
parentf9a4f59930ab9931d8e92f6ebee69ee0cbc2cad2
signature Signed by PGP key B5690EEEBB952194

Allow preview panel to grow on wide displays (#4044)


2 files changed, 19 insertions(+), 4 deletions(-)

apps/web/src/components/preview/PreviewPanelShell.test.ts created+13
...@@ -0,0 +1,13 @@
1import { describe, expect, it } from "vite-plus/test";
2
3import { getPreviewPanelMaxWidth } from "./PreviewPanelShell";
4
5describe("getPreviewPanelMaxWidth", () => {
6 it("allows the panel to use 70% of an ultra-wide viewport without a pixel ceiling", () => {
7 expect(getPreviewPanelMaxWidth(6_000)).toBe(4_200);
8 });
9
10 it("rounds fractional CSS pixels down", () => {
11 expect(getPreviewPanelMaxWidth(2_001)).toBe(1_400);
12 });
13});
apps/web/src/components/preview/PreviewPanelShell.tsx+6-4
...@@ -10,12 +10,14 @@ export type PreviewPanelMode = "inline" | "sheet" | "sidebar" | "embedded";...@@ -10,12 +10,14 @@ export type PreviewPanelMode = "inline" | "sheet" | "sidebar" | "embedded";
1010
11const PREVIEW_PANEL_WIDTH_STORAGE_KEY = "t3code:preview-panel-width";11const PREVIEW_PANEL_WIDTH_STORAGE_KEY = "t3code:preview-panel-width";
12const PREVIEW_PANEL_MIN_WIDTH = 360;12const PREVIEW_PANEL_MIN_WIDTH = 360;
13/** Hard ceiling so a wide monitor can't yield a panel that swallows the chat. */13/** Fraction of the viewport allowed, preserving the remaining space for chat. */
14const PREVIEW_PANEL_MAX_WIDTH_PX = 1400;
15/** Fraction of the viewport allowed; the panel is min(this · vw, MAX_PX). */
16const PREVIEW_PANEL_MAX_WIDTH_FRACTION = 0.7;14const PREVIEW_PANEL_MAX_WIDTH_FRACTION = 0.7;
17const PREVIEW_PANEL_DEFAULT_WIDTH = 540;15const PREVIEW_PANEL_DEFAULT_WIDTH = 540;
1816
17export function getPreviewPanelMaxWidth(viewportWidth: number): number {
18 return Math.floor(viewportWidth * PREVIEW_PANEL_MAX_WIDTH_FRACTION);
19}
20
19/**21/**
20 * Shell for the preview panel. In inline mode the panel is user-resizable22 * Shell for the preview panel. In inline mode the panel is user-resizable
21 * via a drag handle on the left edge; width persists per browser. In23 * via a drag handle on the left edge; width persists per browser. In
...@@ -82,5 +84,5 @@ function useViewportClampedMaxWidth(): number {...@@ -82,5 +84,5 @@ function useViewportClampedMaxWidth(): number {
82 if (frame !== 0) window.cancelAnimationFrame(frame);84 if (frame !== 0) window.cancelAnimationFrame(frame);
83 };85 };
84 }, []);86 }, []);
85 return Math.min(PREVIEW_PANEL_MAX_WIDTH_PX, Math.floor(vw * PREVIEW_PANEL_MAX_WIDTH_FRACTION));87 return getPreviewPanelMaxWidth(vw);
86}88}