mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat: make task panels resizable (#18590)
**Demo:** https://github.com/user-attachments/assets/cc80b768-197e-42a0-9326-f30c9d9038e3
This commit is contained in:
@@ -102,6 +102,7 @@
|
||||
"react-helmet-async": "2.0.5",
|
||||
"react-markdown": "9.0.3",
|
||||
"react-query": "npm:@tanstack/react-query@5.77.0",
|
||||
"react-resizable-panels": "3.0.3",
|
||||
"react-router-dom": "6.26.2",
|
||||
"react-syntax-highlighter": "15.6.1",
|
||||
"react-textarea-autosize": "8.5.9",
|
||||
|
||||
Generated
+14
@@ -220,6 +220,9 @@ importers:
|
||||
react-query:
|
||||
specifier: npm:@tanstack/react-query@5.77.0
|
||||
version: '@tanstack/react-query@5.77.0(react@18.3.1)'
|
||||
react-resizable-panels:
|
||||
specifier: 3.0.3
|
||||
version: 3.0.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
react-router-dom:
|
||||
specifier: 6.26.2
|
||||
version: 6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||
@@ -5428,6 +5431,12 @@ packages:
|
||||
'@types/react':
|
||||
optional: true
|
||||
|
||||
react-resizable-panels@3.0.3:
|
||||
resolution: {integrity: sha512-7HA8THVBHTzhDK4ON0tvlGXyMAJN1zBeRpuyyremSikgYh2ku6ltD7tsGQOcXx4NKPrZtYCm/5CBr+dkruTGQw==, tarball: https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-3.0.3.tgz}
|
||||
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
|
||||
|
||||
react-router-dom@6.26.2:
|
||||
resolution: {integrity: sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==, tarball: https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.2.tgz}
|
||||
engines: {node: '>=14.0.0'}
|
||||
@@ -12284,6 +12293,11 @@ snapshots:
|
||||
optionalDependencies:
|
||||
'@types/react': 18.3.12
|
||||
|
||||
react-resizable-panels@3.0.3(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
react: 18.3.1
|
||||
react-dom: 18.3.1(react@18.3.1)
|
||||
|
||||
react-router-dom@6.26.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||
dependencies:
|
||||
'@remix-run/router': 1.19.2
|
||||
|
||||
@@ -57,7 +57,7 @@ export const TaskApps: FC<TaskAppsProps> = ({ task }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<main className="flex-1 flex flex-col">
|
||||
<main className="flex flex-col">
|
||||
<div className="w-full flex items-center border-0 border-b border-border border-solid">
|
||||
<div className="p-2 pb-0 flex gap-2 items-center">
|
||||
{embeddedApps.map((app) => (
|
||||
|
||||
@@ -11,6 +11,7 @@ import { AI_PROMPT_PARAMETER_NAME, type Task } from "modules/tasks/tasks";
|
||||
import type { ReactNode } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useQuery } from "react-query";
|
||||
import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { ellipsizeText } from "utils/ellipsizeText";
|
||||
@@ -178,11 +179,15 @@ const TaskPage = () => {
|
||||
<Helmet>
|
||||
<title>{pageTitle(ellipsizeText(task.prompt, 64) ?? "Task")}</title>
|
||||
</Helmet>
|
||||
|
||||
<div className="h-full flex justify-stretch">
|
||||
<TaskSidebar task={task} />
|
||||
{content}
|
||||
</div>
|
||||
<PanelGroup autoSaveId="task" direction="horizontal">
|
||||
<Panel defaultSize={25} minSize={20}>
|
||||
<TaskSidebar task={task} />
|
||||
</Panel>
|
||||
<PanelResizeHandle>
|
||||
<div className="w-1 bg-border h-full hover:bg-border-hover transition-all relative" />
|
||||
</PanelResizeHandle>
|
||||
<Panel className="[&>*]:h-full">{content}</Panel>
|
||||
</PanelGroup>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -17,7 +17,6 @@ import { ArrowLeftIcon, EllipsisVerticalIcon } from "lucide-react";
|
||||
import type { Task } from "modules/tasks/tasks";
|
||||
import type { FC } from "react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { cn } from "utils/cn";
|
||||
import { TaskAppIFrame } from "./TaskAppIframe";
|
||||
import { TaskStatusLink } from "./TaskStatusLink";
|
||||
|
||||
@@ -82,15 +81,7 @@ export const TaskSidebar: FC<TaskSidebarProps> = ({ task }) => {
|
||||
const [sidebarApp, sidebarAppStatus] = getSidebarApp(task);
|
||||
|
||||
return (
|
||||
<aside
|
||||
className={cn([
|
||||
[
|
||||
"flex flex-col h-full shrink-0",
|
||||
"border-0 border-r border-solid border-border",
|
||||
],
|
||||
"w-[520px]",
|
||||
])}
|
||||
>
|
||||
<aside className="flex flex-col h-full shrink-0 w-full">
|
||||
<header className="border-0 border-b border-solid border-border p-4 pt-0">
|
||||
<div className="flex items-center justify-between py-1">
|
||||
<TooltipProvider>
|
||||
|
||||
Reference in New Issue
Block a user