Polish live workbench shell layout
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-06-17 23:16:23 +02:00
parent 6d43de4b5c
commit ae7e4bf5a3
7 changed files with 115 additions and 28 deletions
+11
View File
@@ -614,3 +614,14 @@ Added:
- Shortened displayed export paths while preserving the full path in the element title. - Shortened displayed export paths while preserving the full path in the element title.
- Added regression coverage for populated-state Data layout, export limiting and export preview empty state. - Added regression coverage for populated-state Data layout, export limiting and export preview empty state.
- No API contracts, migrations, product capabilities, live provider fetching or AI/model dependency changes were introduced. - No API contracts, migrations, product capabilities, live provider fetching or AI/model dependency changes were introduced.
## Sprint 55 live visual shell polish (2026-06-17)
- Audited the live workbench visually in Browser on `http://192.168.10.150:1202`.
- Compacted the top context bar and primary navigation so the workbench has more usable canvas space.
- Moved the inspector below the workspace on standard desktop widths instead of forcing a cramped three-column layout.
- Preserved the side inspector behavior for wider screens.
- Improved Map workspace control wrapping so the map/status controls do not clip at 1280px.
- Reset page scroll on workspace changes so workspaces open from their heading instead of inheriting stale scroll positions.
- Added regression coverage for the standard-desktop layout and workspace scroll reset.
- No API contracts, migrations, product capabilities, live provider fetching or AI/model dependency changes were introduced.
@@ -35,9 +35,10 @@ def test_app_entrypoint_has_clean_encoding_and_react_imports() -> None:
app = app_path.read_text(encoding="utf-8") app = app_path.read_text(encoding="utf-8")
assert not app_bytes.startswith(b"\xef\xbb\xbf") assert not app_bytes.startswith(b"\xef\xbb\xbf")
assert "import { useMemo, useState } from 'react'" in app assert "import { useEffect, useMemo, useState } from 'react'" in app
assert "FormEvent" not in app assert "FormEvent" not in app
assert "useEffect" not in app assert app.count("useEffect(") == 1
assert "window.scrollTo({ top: 0, left: 0 })" in app
assert "const [activeWorkspace, setActiveWorkspace] = useState<WorkspaceKey>('overview')" in app assert "const [activeWorkspace, setActiveWorkspace] = useState<WorkspaceKey>('overview')" in app
@@ -27,6 +27,18 @@ def test_data_workspace_keeps_catalog_wide_enough_for_populated_state() -> None:
assert ".dataset-card .button-row" in css assert ".dataset-card .button-row" in css
def test_shell_preserves_workspace_width_on_standard_desktop_viewports() -> None:
css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8")
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8")
assert "grid-template-columns: 12.5rem minmax(0, 1fr) 21rem" in css
assert "@media (max-width: 1360px)" in css
assert ".workbench-inspector {\n grid-column: 1 / -1;" in css
assert "height: auto;" in css
assert "window.scrollTo({ top: 0, left: 0 })" in app
assert "}, [activeWorkspace])" in app
def test_app_wires_dataset_quick_actions_to_existing_workspaces() -> None: def test_app_wires_dataset_quick_actions_to_existing_workspaces() -> None:
app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8") app = (ROOT / "frontend" / "src" / "App.tsx").read_text(encoding="utf-8")
+28
View File
@@ -2207,3 +2207,31 @@ Limitations:
Next recommended pass: Next recommended pass:
- Add export history filtering or retention controls if artifact history continues to grow during demo runs. - Add export history filtering or retention controls if artifact history continues to grow during demo runs.
## Sprint 55 live visual shell polish (2026-06-17)
Changed:
- Performed a Browser-based visual audit of the live Tower workbench at `http://192.168.10.150:1202`.
- Confirmed the main visual defect was the cramped three-column desktop shell: left navigation, central workspace and inspector competed for width at 1280px.
- Compacted the sticky top context bar and left navigation.
- Changed the standard desktop breakpoint so the inspector moves below the workspace up to 1360px, while remaining a side panel on wider displays.
- Made the Map toolbar wrap responsively instead of forcing four controls into a narrow row.
- Added a workspace-change scroll reset so switching pages starts at the workspace heading instead of inheriting stale scroll position.
- Added regression coverage for the standard desktop shell width and scroll-reset behavior.
Tested:
- Local Browser visual audit against `http://127.0.0.1:5177` using the live Tower API proxy.
- Verified Overview, Data, Map and Exports workspaces visually after the shell changes.
- Browser console error/warning check returned no entries.
- `cd frontend && npm run typecheck`
- `cd backend && python -m pytest tests/test_sprint53_selection_ergonomics.py tests/test_sprint50_workspace_usability_polish.py -q`
- `cd frontend && npm run build`
Open:
- Run full readiness, deploy Tower and verify the live visual shell on `http://192.168.10.150:1202`.
Limitations:
- This pass remains UI shell polish only. It does not add features, change API contracts, alter migrations, fetch live providers or enable new AI models.
Next recommended pass:
- Continue with export history filtering or retention controls if repeated demo runs keep growing artifact history.
+1
View File
@@ -324,4 +324,5 @@ This file now starts with the current implementation status. Older preparation/b
- [x] Add selected-object inspector detail tabs for project, AOI, dataset, QA check, export and AI run context. - [x] Add selected-object inspector detail tabs for project, AOI, dataset, QA check, export and AI run context.
- [x] Improve map/dataset selection ergonomics from the workbench canvas and inspector. - [x] Improve map/dataset selection ergonomics from the workbench canvas and inspector.
- [x] Improve populated Data/Exports readability after a demo workflow run. - [x] Improve populated Data/Exports readability after a demo workflow run.
- [x] Improve live visual shell width, scroll behavior and Map workspace layout at 1280px.
- [ ] Add export history filtering or retention controls for long-running demo environments. - [ ] Add export history filtering or retention controls for long-running demo environments.
+5 -1
View File
@@ -1,4 +1,4 @@
import { useMemo, useState } from 'react' import { useEffect, useMemo, useState } from 'react'
import './styles/app.css' import './styles/app.css'
import { ChangeDetectionPanel } from './components/analysis/ChangeDetectionPanel' import { ChangeDetectionPanel } from './components/analysis/ChangeDetectionPanel'
import { DatasetPanel } from './components/datasets/DatasetPanel' import { DatasetPanel } from './components/datasets/DatasetPanel'
@@ -44,6 +44,10 @@ const workspaceNavItems: Array<{ key: WorkspaceKey; label: string; description:
function App(): JSX.Element { function App(): JSX.Element {
const [activeWorkspace, setActiveWorkspace] = useState<WorkspaceKey>('overview') const [activeWorkspace, setActiveWorkspace] = useState<WorkspaceKey>('overview')
useEffect(() => {
window.scrollTo({ top: 0, left: 0 })
}, [activeWorkspace])
const { const {
projects, projects,
selectedProject, selectedProject,
+55 -25
View File
@@ -519,38 +519,43 @@ section li strong + div {
top: 0; top: 0;
z-index: 20; z-index: 20;
display: grid; display: grid;
grid-template-columns: minmax(16rem, 26rem) minmax(0, 1fr); grid-template-columns: minmax(12rem, 18rem) minmax(0, 1fr);
gap: 1rem; gap: 0.75rem;
align-items: center; align-items: center;
border-bottom: 1px solid var(--line); border-bottom: 1px solid var(--line);
padding: 0.85rem 1rem; padding: 0.55rem 0.85rem;
background: rgba(248, 251, 249, 0.96); background: rgba(248, 251, 249, 0.96);
backdrop-filter: blur(12px); backdrop-filter: blur(12px);
} }
.brand-block h1 { .brand-block h1 {
font-size: 1.45rem; font-size: 1.18rem;
line-height: 1.1; line-height: 1.1;
} }
.brand-block .eyebrow {
margin-bottom: 0.12rem;
font-size: 0.66rem;
}
.context-bar { .context-bar {
display: grid; display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr)); grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.65rem; gap: 0.5rem;
} }
.context-bar > div { .context-bar > div {
min-height: 4.2rem; min-height: 3.2rem;
border: 1px solid var(--line); border: 1px solid var(--line);
border-radius: 8px; border-radius: 8px;
padding: 0.62rem 0.72rem; padding: 0.44rem 0.58rem;
background: #ffffff; background: #ffffff;
} }
.context-bar span { .context-bar span {
display: block; display: block;
color: var(--muted); color: var(--muted);
font-size: 0.72rem; font-size: 0.66rem;
font-weight: 800; font-weight: 800;
letter-spacing: 0.05em; letter-spacing: 0.05em;
text-transform: uppercase; text-transform: uppercase;
@@ -558,16 +563,16 @@ section li strong + div {
.context-bar strong { .context-bar strong {
display: block; display: block;
margin-top: 0.3rem; margin-top: 0.18rem;
font-size: 0.92rem; font-size: 0.84rem;
line-height: 1.25; line-height: 1.25;
} }
.workbench-layout { .workbench-layout {
display: grid; display: grid;
grid-template-columns: 14rem minmax(0, 1fr) 24rem; grid-template-columns: 12.5rem minmax(0, 1fr) 21rem;
gap: 0; gap: 0;
height: calc(100vh - 5.95rem); height: calc(100vh - 4.35rem);
min-height: 42rem; min-height: 42rem;
} }
@@ -581,7 +586,7 @@ section li strong + div {
.workbench-sidebar { .workbench-sidebar {
border-right: 1px solid var(--line); border-right: 1px solid var(--line);
padding: 0.85rem; padding: 0.72rem;
} }
.workbench-sidebar nav { .workbench-sidebar nav {
@@ -592,9 +597,9 @@ section li strong + div {
.nav-item { .nav-item {
display: block; display: block;
width: 100%; width: 100%;
min-height: 4.2rem; min-height: 3.7rem;
border-color: transparent; border-color: transparent;
padding: 0.66rem 0.72rem; padding: 0.58rem 0.62rem;
background: transparent; background: transparent;
box-shadow: none; box-shadow: none;
text-align: left; text-align: left;
@@ -610,7 +615,7 @@ section li strong + div {
} }
.nav-item span { .nav-item span {
font-size: 0.96rem; font-size: 0.9rem;
} }
.nav-item small { .nav-item small {
@@ -631,12 +636,12 @@ section li strong + div {
min-width: 0; min-width: 0;
min-height: 0; min-height: 0;
overflow: auto; overflow: auto;
padding: 1rem; padding: 0.85rem 1rem 1rem;
} }
.workbench-inspector { .workbench-inspector {
border-left: 1px solid var(--line); border-left: 1px solid var(--line);
padding: 1rem; padding: 0.85rem;
} }
.workbench-inspector > section { .workbench-inspector > section {
@@ -651,10 +656,10 @@ section li strong + div {
gap: 1rem; gap: 1rem;
align-items: end; align-items: end;
justify-content: space-between; justify-content: space-between;
margin-bottom: 1rem; margin-bottom: 0.85rem;
border: 1px solid var(--line); border: 1px solid var(--line);
border-radius: 8px; border-radius: 8px;
padding: 0.85rem 1rem; padding: 0.72rem 0.85rem;
background: #ffffff; background: #ffffff;
} }
@@ -1119,7 +1124,7 @@ button.entity-card {
.map-toolbar { .map-toolbar {
display: grid; display: grid;
grid-template-columns: minmax(12rem, 1fr) minmax(10rem, 0.8fr) minmax(10rem, 0.8fr) minmax(14rem, 1fr); grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr));
gap: 0.75rem; gap: 0.75rem;
align-items: end; align-items: end;
margin-bottom: 0.85rem; margin-bottom: 0.85rem;
@@ -1165,7 +1170,7 @@ button.entity-card {
.workbench-inspector-panel { .workbench-inspector-panel {
display: grid; display: grid;
gap: 0.8rem; gap: 0.68rem;
} }
.inspector-header { .inspector-header {
@@ -1230,10 +1235,10 @@ button.entity-card {
.inspector-card { .inspector-card {
display: grid; display: grid;
gap: 0.55rem; gap: 0.48rem;
border: 1px solid var(--line); border: 1px solid var(--line);
border-radius: 8px; border-radius: 8px;
padding: 0.8rem; padding: 0.7rem;
background: #ffffff; background: #ffffff;
} }
@@ -1282,9 +1287,15 @@ button.entity-card {
gap: 0.55rem; gap: 0.55rem;
} }
@media (max-width: 1120px) { @media (max-width: 1360px) {
.workbench-layout { .workbench-layout {
grid-template-columns: 12rem minmax(0, 1fr); grid-template-columns: 12rem minmax(0, 1fr);
height: auto;
min-height: 0;
}
.workbench-main {
overflow: visible;
} }
.workbench-inspector { .workbench-inspector {
@@ -1292,6 +1303,25 @@ button.entity-card {
border-top: 1px solid var(--line); border-top: 1px solid var(--line);
border-left: 0; border-left: 0;
} }
.workbench-inspector-panel {
max-width: none;
}
.inspector-tab-panel {
grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr));
}
.workbench-inspector-panel .dataset-detail-panel,
.inspector-action-bar {
grid-column: 1 / -1;
}
.inspector-header h2,
.inspector-tabs,
.inspector-action-bar {
position: static;
}
} }
@media (max-width: 980px) { @media (max-width: 980px) {