feat: refine workbench visuals and map controls
Unify the Agent history extension with the header acrylic surface, preserve the full conversation body, and consolidate shared control and status styling. Restore map flow and SCADA controller behavior, remove obsolete rendering paths, and extend regression coverage. Button press coverage now releases outside the target so state assertions cannot accidentally toggle the control.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
clampAgentPanelWidth,
|
||||
getAgentPanelDefaultWidth,
|
||||
getAgentPanelMaxWidth,
|
||||
getWorkbenchBasemapTone,
|
||||
getWorkbenchCameraPadding,
|
||||
@@ -21,13 +22,13 @@ describe("workbench basemap surface tone", () => {
|
||||
describe("workbench floating panels", () => {
|
||||
it("uses bounded desktop and wide panel widths", () => {
|
||||
expect(getWorkbenchViewportLayout(1440)).toMatchObject({
|
||||
agentWidth: 460,
|
||||
agentWidth: 500,
|
||||
conditionWidth: 432,
|
||||
conditionExpandedWidth: 880,
|
||||
toolbarWidth: 48
|
||||
});
|
||||
expect(getWorkbenchViewportLayout(1536)).toMatchObject({
|
||||
agentWidth: 500,
|
||||
agentWidth: 540,
|
||||
conditionExpandedWidth: 960
|
||||
});
|
||||
});
|
||||
@@ -39,7 +40,7 @@ describe("workbench floating panels", () => {
|
||||
conditionOpen: true,
|
||||
conditionExpanded: false
|
||||
})
|
||||
).toEqual({ top: 72, right: 504, bottom: 32, left: 484 });
|
||||
).toEqual({ top: 72, right: 504, bottom: 32, left: 524 });
|
||||
|
||||
expect(
|
||||
getWorkbenchCameraPadding(1440, {
|
||||
@@ -47,7 +48,7 @@ describe("workbench floating panels", () => {
|
||||
conditionOpen: true,
|
||||
conditionExpanded: true
|
||||
})
|
||||
).toEqual({ top: 72, right: 952, bottom: 32, left: 484 });
|
||||
).toEqual({ top: 72, right: 952, bottom: 32, left: 476 });
|
||||
});
|
||||
|
||||
it("uses the committed Agent width without exceeding the hard limit", () => {
|
||||
@@ -65,12 +66,20 @@ describe("workbench floating panels", () => {
|
||||
agentWidth: 900,
|
||||
conditionOpen: false
|
||||
}).left
|
||||
).toBe(644);
|
||||
).toBe(744);
|
||||
});
|
||||
|
||||
it("reserves room for the compact condition panel on narrow desktops", () => {
|
||||
it("uses responsive defaults and preserves the map corridor at maximum width", () => {
|
||||
expect(getAgentPanelDefaultWidth(390)).toBe(500);
|
||||
expect(getAgentPanelDefaultWidth(1024)).toBe(484);
|
||||
expect(getAgentPanelDefaultWidth(1440)).toBe(500);
|
||||
expect(getAgentPanelDefaultWidth(1536)).toBe(540);
|
||||
expect(getAgentPanelMaxWidth(1024)).toBe(484);
|
||||
expect(clampAgentPanelWidth(620, 1024)).toBe(484);
|
||||
expect(getAgentPanelMaxWidth(1440)).toBe(620);
|
||||
expect(getAgentPanelMaxWidth(1280)).toBe(516);
|
||||
expect(getAgentPanelMaxWidth(1440)).toBe(676);
|
||||
expect(getAgentPanelMaxWidth(1536)).toBe(720);
|
||||
expect(getAgentPanelMaxWidth(1920)).toBe(720);
|
||||
expect(getAgentPanelMaxWidth(1920, true)).toBe(628);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,17 +4,20 @@ export const WORKBENCH_LAYOUT = {
|
||||
persistentConditionMinWidth: 1280,
|
||||
wideMinWidth: 1536,
|
||||
collapsedAgentWidth: 72,
|
||||
maxAgentWidth: 620,
|
||||
maxAgentWidth: 720,
|
||||
agentPanelLeftInset: 12,
|
||||
conditionPanelRightInset: 64,
|
||||
minimumAgentMapCorridor: 256,
|
||||
mapEdgeGap: 24,
|
||||
desktop: {
|
||||
agentWidth: 460,
|
||||
agentWidth: 500,
|
||||
conditionWidth: 432,
|
||||
conditionExpandedWidth: 880,
|
||||
toolbarWidth: 48,
|
||||
tickerWidth: 420
|
||||
},
|
||||
wide: {
|
||||
agentWidth: 500,
|
||||
agentWidth: 540,
|
||||
conditionWidth: 432,
|
||||
conditionExpandedWidth: 960,
|
||||
toolbarWidth: 48,
|
||||
@@ -26,28 +29,48 @@ export const WORKBENCH_LAYOUT = {
|
||||
}
|
||||
} as const;
|
||||
|
||||
export function clampAgentPanelWidth(width: number, viewportWidth: number) {
|
||||
const minWidth = getWorkbenchViewportLayout(viewportWidth).agentWidth;
|
||||
export function clampAgentPanelWidth(
|
||||
width: number,
|
||||
viewportWidth: number,
|
||||
conditionExpanded = false
|
||||
) {
|
||||
const minWidth = getAgentPanelDefaultWidth(viewportWidth, conditionExpanded);
|
||||
|
||||
return Math.round(
|
||||
Math.min(Math.max(width, minWidth), getAgentPanelMaxWidth(viewportWidth))
|
||||
Math.min(Math.max(width, minWidth), getAgentPanelMaxWidth(viewportWidth, conditionExpanded))
|
||||
);
|
||||
}
|
||||
|
||||
export function getAgentPanelMaxWidth(viewportWidth: number) {
|
||||
export function getAgentPanelDefaultWidth(viewportWidth: number, conditionExpanded = false) {
|
||||
const layout = getWorkbenchViewportLayout(viewportWidth);
|
||||
const widthWithCompactCondition =
|
||||
if (viewportWidth < WORKBENCH_LAYOUT.desktopMinWidth) {
|
||||
return layout.agentWidth;
|
||||
}
|
||||
|
||||
const conditionWidth = conditionExpanded ? layout.conditionExpandedWidth : layout.conditionWidth;
|
||||
const collisionSafeWidth =
|
||||
viewportWidth -
|
||||
12 -
|
||||
WORKBENCH_LAYOUT.agentPanelLeftInset -
|
||||
WORKBENCH_LAYOUT.mapEdgeGap -
|
||||
layout.conditionWidth -
|
||||
conditionWidth -
|
||||
WORKBENCH_LAYOUT.mapEdgeGap -
|
||||
layout.toolbarWidth;
|
||||
|
||||
return Math.max(
|
||||
layout.agentWidth,
|
||||
Math.min(WORKBENCH_LAYOUT.maxAgentWidth, widthWithCompactCondition)
|
||||
);
|
||||
return Math.min(layout.agentWidth, collisionSafeWidth);
|
||||
}
|
||||
|
||||
export function getAgentPanelMaxWidth(viewportWidth: number, conditionExpanded = false) {
|
||||
const layout = getWorkbenchViewportLayout(viewportWidth);
|
||||
const conditionWidth = conditionExpanded ? layout.conditionExpandedWidth : layout.conditionWidth;
|
||||
const defaultWidth = getAgentPanelDefaultWidth(viewportWidth, conditionExpanded);
|
||||
const widthWithMapCorridor =
|
||||
viewportWidth -
|
||||
WORKBENCH_LAYOUT.agentPanelLeftInset -
|
||||
WORKBENCH_LAYOUT.conditionPanelRightInset -
|
||||
conditionWidth -
|
||||
WORKBENCH_LAYOUT.minimumAgentMapCorridor;
|
||||
|
||||
return Math.max(defaultWidth, Math.min(WORKBENCH_LAYOUT.maxAgentWidth, widthWithMapCorridor));
|
||||
}
|
||||
|
||||
export type WorkbenchPanelState = {
|
||||
@@ -93,8 +116,15 @@ export function getWorkbenchCameraPadding(viewportWidth: number, panels: Workben
|
||||
const layout = getWorkbenchViewportLayout(viewportWidth);
|
||||
const agentWidth = panels.agentOpen
|
||||
? panels.agentWidth === undefined
|
||||
? layout.agentWidth
|
||||
: clampAgentPanelWidth(panels.agentWidth, viewportWidth)
|
||||
? getAgentPanelDefaultWidth(
|
||||
viewportWidth,
|
||||
panels.conditionOpen && Boolean(panels.conditionExpanded)
|
||||
)
|
||||
: clampAgentPanelWidth(
|
||||
panels.agentWidth,
|
||||
viewportWidth,
|
||||
panels.conditionOpen && Boolean(panels.conditionExpanded)
|
||||
)
|
||||
: WORKBENCH_LAYOUT.collapsedAgentWidth;
|
||||
const conditionWidth = panels.conditionOpen
|
||||
? panels.conditionExpanded
|
||||
|
||||
Reference in New Issue
Block a user