feat(workbench): dock task and chart workspaces
Generic Container CI/CD / test-build-publish (push) Successful in 1m13s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 1m14s

This commit is contained in:
2026-11-12 11:42:25 +08:00
parent 33f0b90a7d
commit 7a304a91a8
27 changed files with 766 additions and 201 deletions
@@ -1,6 +1,7 @@
import { useEffect, useState } from "react";
import type { MobileWorkbenchSheetSnap } from "../components/mobile-workbench-sheet";
import { WORKBENCH_LAYOUT } from "../layout/workbench-layout";
import { CONDITION_PANE_MIN_WIDTH, type ArtifactRequestedView } from "../workspace/workspace-model";
const CONDITION_FEED_EXIT_MS = 170;
const CONDITION_FEED_EXPANDED_MIN_WIDTH = 1440;
@@ -33,6 +34,8 @@ export function useWorkbenchResponsiveLayout({
const [conditionFeedVisible, setConditionFeedVisible] = useState(false);
const [conditionFeedMounted, setConditionFeedMounted] = useState(false);
const [conditionFeedExpanded, setConditionFeedExpanded] = useState(false);
const [conditionFeedDocked, setConditionFeedDocked] = useState(false);
const [conditionView, setConditionView] = useState<ArtifactRequestedView>("map_split");
const [mobileSheet, setMobileSheet] = useState<WorkbenchMobileSheet>(null);
const [mobileSheetSnap, setMobileSheetSnap] = useState<MobileWorkbenchSheetSnap>("half");
const [agentCollapsedForCondition, setAgentCollapsedForCondition] = useState(false);
@@ -87,7 +90,11 @@ export function useWorkbenchResponsiveLayout({
function openAgentPanelForViewport() {
if (isLargeScreen) {
if (conditionFeedExpanded && viewportWidth < CONDITION_FEED_EXPANDED_MIN_WIDTH) {
if (conditionFeedDocked && viewportWidth - agentPanelWidth < CONDITION_PANE_MIN_WIDTH) {
setConditionFeedDocked(false);
setConditionFeedExpanded(false);
}
if (!conditionFeedDocked && conditionFeedExpanded && viewportWidth < CONDITION_FEED_EXPANDED_MIN_WIDTH) {
setConditionFeedExpanded(false);
setAgentCollapsedForCondition(false);
}
@@ -100,10 +107,11 @@ export function useWorkbenchResponsiveLayout({
}
function handleConditionExpandedChange(nextExpanded: boolean) {
if (nextExpanded && isLargeScreen && viewportWidth < CONDITION_FEED_EXPANDED_MIN_WIDTH) {
setAgentCollapsedForCondition(agentPanelOpen);
collapseAgentPanel();
} else if (!nextExpanded && agentCollapsedForCondition) {
if (isLargeScreen) {
setConditionFeedDocked(nextExpanded);
if (nextExpanded) setConditionView("map_split");
}
if (!nextExpanded && agentCollapsedForCondition) {
setAgentCollapsedForCondition(false);
expandAgentPanel();
}
@@ -111,22 +119,22 @@ export function useWorkbenchResponsiveLayout({
}
useEffect(() => {
if (!isLargeScreen || shouldShowConditionFeed || !conditionFeedExpanded) {
return;
if (isLargeScreen && conditionFeedDocked && shouldShowConditionFeed && agentPanelOpen
&& viewportWidth - agentPanelWidth < CONDITION_PANE_MIN_WIDTH) {
setAgentCollapsedForCondition(true);
collapseAgentPanel();
}
}, [agentPanelOpen, agentPanelWidth, collapseAgentPanel, conditionFeedDocked, isLargeScreen, shouldShowConditionFeed, viewportWidth]);
useEffect(() => {
if (!isLargeScreen || shouldShowConditionFeed || !conditionFeedExpanded) return;
setConditionFeedExpanded(false);
setConditionFeedDocked(false);
if (agentCollapsedForCondition) {
setAgentCollapsedForCondition(false);
expandAgentPanel();
}
}, [
agentCollapsedForCondition,
conditionFeedExpanded,
expandAgentPanel,
isLargeScreen,
shouldShowConditionFeed
]);
}, [agentCollapsedForCondition, conditionFeedExpanded, expandAgentPanel, isLargeScreen, shouldShowConditionFeed]);
function toggleConditionFeedForViewport() {
onClearActiveTool();
@@ -161,14 +169,16 @@ export function useWorkbenchResponsiveLayout({
}
const leftPanelOpen = isLargeScreen && agentPanelOpen;
const rightPanelOpen = isLargeScreen && (devPanelOpen || shouldShowConditionFeed);
const rightPanelOpen = isLargeScreen && (devPanelOpen || (shouldShowConditionFeed && !conditionFeedDocked));
const rightPanelExpanded =
isLargeScreen && shouldShowConditionFeed && conditionFeedExpanded && !devPanelOpen;
isLargeScreen && shouldShowConditionFeed && !conditionFeedDocked && conditionFeedExpanded && !devPanelOpen;
return {
agentPanelWidth,
closeMobileSheet,
conditionFeedExpanded,
conditionFeedDocked,
conditionView,
conditionFeedMounted,
handleConditionExpandedChange,
isLargeScreen,
@@ -181,6 +191,7 @@ export function useWorkbenchResponsiveLayout({
rightPanelExpanded,
rightPanelOpen,
setAgentPanelWidth,
setConditionView,
setMobileSheetSnap,
shouldShowConditionFeed,
toggleConditionFeedForViewport,