From 55d46841af64450adffdf5d9045b9d13a949ce7c Mon Sep 17 00:00:00 2001 From: openhands Date: Mon, 30 Dec 2024 16:04:20 +0000 Subject: [PATCH] Add draggable and collapsible panels to the UI layout --- frontend/package-lock.json | 11 +++ frontend/package.json | 1 + frontend/src/routes/_oh.app/panels.module.css | 23 +++++ frontend/src/routes/_oh.app/route.tsx | 84 +++++++++++-------- 4 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 frontend/src/routes/_oh.app/panels.module.css diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 138620acc36a..2af9a3885293 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -36,6 +36,7 @@ "react-icons": "^5.4.0", "react-markdown": "^9.0.1", "react-redux": "^9.2.0", + "react-resizable-panels": "^2.1.7", "react-router": "^7.1.1", "react-syntax-highlighter": "^15.6.1", "react-textarea-autosize": "^8.5.4", @@ -14215,6 +14216,16 @@ "node": ">=0.10.0" } }, + "node_modules/react-resizable-panels": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.1.7.tgz", + "integrity": "sha512-JtT6gI+nURzhMYQYsx8DKkx6bSoOGFp7A3CwMrOb8y5jFHFyqwo9m68UhmXRw57fRVJksFn1TSlm3ywEQ9vMgA==", + "license": "MIT", + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/react-router": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.1.tgz", diff --git a/frontend/package.json b/frontend/package.json index 735aa2930d7f..704c81d99add 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -35,6 +35,7 @@ "react-icons": "^5.4.0", "react-markdown": "^9.0.1", "react-redux": "^9.2.0", + "react-resizable-panels": "^2.1.7", "react-router": "^7.1.1", "react-syntax-highlighter": "^15.6.1", "react-textarea-autosize": "^8.5.4", diff --git a/frontend/src/routes/_oh.app/panels.module.css b/frontend/src/routes/_oh.app/panels.module.css new file mode 100644 index 000000000000..353f3fa2a6b5 --- /dev/null +++ b/frontend/src/routes/_oh.app/panels.module.css @@ -0,0 +1,23 @@ +.resizeHandle { + width: 8px; + background-color: var(--nextui-default-100); + transition: background-color 0.2s; + margin: 0 -2px; + cursor: col-resize; +} + +.resizeHandle:hover { + background-color: var(--nextui-default-200); +} + +.resizeHandle[data-resize-handle-active] { + background-color: var(--nextui-default-300); +} + +.resizeHandleBar { + height: 100%; + width: 2px; + margin: 0 auto; + background-color: var(--nextui-default-300); + border-radius: 2px; +} \ No newline at end of file diff --git a/frontend/src/routes/_oh.app/route.tsx b/frontend/src/routes/_oh.app/route.tsx index f9f437776d82..82a57424c34c 100644 --- a/frontend/src/routes/_oh.app/route.tsx +++ b/frontend/src/routes/_oh.app/route.tsx @@ -2,6 +2,7 @@ import { useDisclosure } from "@nextui-org/react"; import React from "react"; import { Outlet } from "react-router"; import { useDispatch, useSelector } from "react-redux"; +import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels"; import { ConversationProvider, useConversation, @@ -27,6 +28,7 @@ import { Container } from "#/components/layout/container"; import Security from "#/components/shared/modals/security/security"; import { CountBadge } from "#/components/layout/count-badge"; import { TerminalStatusLabel } from "#/components/features/terminal/terminal-status-label"; +import styles from "./panels.module.css"; function AppContent() { const { gitHubToken } = useAuth(); @@ -62,43 +64,53 @@ function AppContent() {
-
- - - +
+ + + + + + -
- , - to: "", - icon: , - }, - { label: "Workspace", to: "workspace", icon: }, - { label: "Jupyter", to: "jupyter", icon: }, - { - label: ( -
- Browser - {updateCount > 0 && } -
- ), - to: "browser", - icon: , - }, - ]} - > - - {/* Terminal uses some API that is not compatible in a server-environment. For this reason, we lazy load it to ensure - * that it loads only in the client-side. */} - }> - - - -
-
+ +
+ + + + , + to: "", + icon: , + }, + { label: "Workspace", to: "workspace", icon: }, + { label: "Jupyter", to: "jupyter", icon: }, + { + label: ( +
+ Browser + {updateCount > 0 && ( + + )} +
+ ), + to: "browser", + icon: , + }, + ]} + > + + {/* Terminal uses some API that is not compatible in a server-environment. For this reason, we lazy load it to ensure + * that it loads only in the client-side. */} + }> + + + +
+
+