From 0d82cc7574a054aae0db34eb995fd0a96834028e Mon Sep 17 00:00:00 2001 From: Gregory Schier Date: Sat, 25 Mar 2023 18:33:01 -0700 Subject: [PATCH] Even better layouts --- src-web/components/RequestResponse.tsx | 45 ++++++++++++++++------- src-web/components/Workspace.tsx | 12 ++---- src-web/components/WorkspaceDropdown.tsx | 6 ++- src-web/components/WorkspaceHeader.tsx | 2 +- src-web/components/core/Editor/Editor.css | 2 +- src-web/components/core/Tabs/Tabs.tsx | 11 +++--- 6 files changed, 47 insertions(+), 31 deletions(-) diff --git a/src-web/components/RequestResponse.tsx b/src-web/components/RequestResponse.tsx index e0c4ad9b..f14d5ad6 100644 --- a/src-web/components/RequestResponse.tsx +++ b/src-web/components/RequestResponse.tsx @@ -2,16 +2,25 @@ import classnames from 'classnames'; import type { CSSProperties, MouseEvent as ReactMouseEvent } from 'react'; import React, { useCallback, useMemo, useRef, useState } from 'react'; import { useKeyValue } from '../hooks/useKeyValue'; +import { clamp } from '../lib/clamp'; import { RequestPane } from './RequestPane'; import { ResponsePane } from './ResponsePane'; import { ResizeBar } from './Workspace'; +interface Props { + style: CSSProperties; + vertical?: boolean; +} + const rqst = { gridArea: 'rqst' }; const resp = { gridArea: 'resp' }; const drag = { gridArea: 'drag' }; -export default function RequestResponse() { - const DEFAULT = 0.5; +const DEFAULT = 0.5; +const MIN_WIDTH_PX = 10; +const MIN_HEIGHT_PX = 100; + +export default function RequestResponse({ style, vertical }: Props) { const containerRef = useRef(null); const widthKv = useKeyValue({ key: 'body_width', defaultValue: DEFAULT }); const heightKv = useKeyValue({ key: 'body_height', defaultValue: DEFAULT }); @@ -22,14 +31,14 @@ export default function RequestResponse() { null, ); - const vertical = false; const styles = useMemo( () => ({ + ...style, gridTemplate: vertical ? ` - ' ${rqst.gridArea}' ${1 - height}fr + ' ${rqst.gridArea}' minmax(0,${1 - height}fr) ' ${drag.gridArea}' auto - ' ${resp.gridArea}' ${height}fr + ' ${resp.gridArea}' minmax(0,${height}fr) / 1fr ` : ` @@ -37,7 +46,7 @@ export default function RequestResponse() { / ${1 - width}fr auto ${width}fr `, }), - [vertical, width, height], + [vertical, width, height, style], ); const unsub = () => { @@ -68,13 +77,21 @@ export default function RequestResponse() { move: (e: MouseEvent) => { e.preventDefault(); // Prevent text selection and things if (vertical) { - const newHeightPx = startHeight - (e.clientY - mouseStartY); - const newHeight = newHeightPx / containerRect.height; - heightKv.set(newHeight); + const maxHeightPx = containerRect.height - MIN_HEIGHT_PX; + const newHeightPx = clamp( + startHeight - (e.clientY - mouseStartY), + MIN_HEIGHT_PX, + maxHeightPx, + ); + heightKv.set(newHeightPx / containerRect.height); } else { - const newWidthPx = startWidth - (e.clientX - mouseStartX); - const newWidth = newWidthPx / containerRect.width; - widthKv.set(newWidth); + const maxWidthPx = containerRect.width - MIN_WIDTH_PX; + const newWidthPx = clamp( + startWidth - (e.clientX - mouseStartX), + MIN_WIDTH_PX, + maxWidthPx, + ); + widthKv.set(newWidthPx / containerRect.width); } }, up: (e: MouseEvent) => { @@ -93,9 +110,9 @@ export default function RequestResponse() { return (
- +
-
+
( @@ -26,23 +28,17 @@ export default function Workspace() { return (
- + - - - +
); } -const BodyContainer = memo(function BodyContainer({ children }: { children: ReactNode }) { - return
{children}
; -}); - const HeaderContainer = memo(function HeaderContainer({ children }: { children: ReactNode }) { return (
- diff --git a/src-web/components/WorkspaceHeader.tsx b/src-web/components/WorkspaceHeader.tsx index 5670bff3..1b872424 100644 --- a/src-web/components/WorkspaceHeader.tsx +++ b/src-web/components/WorkspaceHeader.tsx @@ -25,7 +25,7 @@ export function WorkspaceHeader({ className }: Props) { /> -
+
{activeRequest?.name}
diff --git a/src-web/components/core/Editor/Editor.css b/src-web/components/core/Editor/Editor.css index a0428fdd..f501cfc9 100644 --- a/src-web/components/core/Editor/Editor.css +++ b/src-web/components/core/Editor/Editor.css @@ -17,7 +17,7 @@ } .cm-line { - @apply text-gray-900 pl-1 pr-1.5; + @apply text-gray-800 pl-1 pr-1.5; } .cm-placeholder { diff --git a/src-web/components/core/Tabs/Tabs.tsx b/src-web/components/core/Tabs/Tabs.tsx index c64d2cd5..25492820 100644 --- a/src-web/components/core/Tabs/Tabs.tsx +++ b/src-web/components/core/Tabs/Tabs.tsx @@ -69,6 +69,9 @@ export function Tabs({ {tabs.map((t) => { const isActive = t.value === value; + const btnClassName = classnames( + isActive ? 'bg-gray-100 text-gray-800' : 'text-gray-600 hover:text-gray-900', + ); if (t.options) { return ( ({ color="custom" size="sm" onClick={isActive ? undefined : () => handleTabChange(t.value)} - className={classnames( - isActive ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900', - )} + className={btnClassName} > {t.options.items.find((i) => i.value === t.options?.value)?.label ?? ''} @@ -97,9 +98,7 @@ export function Tabs({ color="custom" size="sm" onClick={() => handleTabChange(t.value)} - className={classnames( - isActive ? 'bg-gray-100 text-gray-900' : 'text-gray-600 hover:text-gray-900', - )} + className={btnClassName} > {t.label}