Calm workbench layout density
GeoIntel CI / docs-smoke (push) Has been cancelled
GeoIntel CI / contract-smoke (push) Has been cancelled

This commit is contained in:
Codex
2026-07-04 23:08:58 +02:00
parent d7e577b6a2
commit 0355a3dfbf
6 changed files with 410 additions and 7 deletions
+8
View File
@@ -7,6 +7,14 @@
# Changelog
## Sprint 113 Calm workbench layout pass (2026-07-04)
- Reduced visual density in the workbench shell without changing API contracts or workflows.
- Softened the base palette, borders and shadows so panels read as a work surface instead of stacked cards.
- Made the top context bar, sidebar navigation, workspace heading, status tiles and inspector more compact.
- Hid the duplicated workspace command bar because the persistent sidebar already provides primary navigation.
- Added static regression coverage for the calmer shell density and mobile-safe navigation rules.
## Sprint 112 QA evidence map overlay (2026-06-25)
- Added a read-only QA/QC evidence GeoJSON endpoint for persisted quality checks.
@@ -0,0 +1,24 @@
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[2]
def test_calm_workbench_layout_reduces_duplicate_navigation_density() -> None:
css = (REPO_ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8")
assert "Sprint 113 calm workbench UX pass" in css
assert ".workspace-command-bar" in css
assert "display: none;" in css
assert ".workbench-layout" in css
assert "grid-template-columns: 10.25rem minmax(0, 1fr) 18.5rem" in css
def test_calm_workbench_layout_keeps_mobile_safe_navigation() -> None:
css = (REPO_ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8")
assert "@media (max-width: 620px)" in css
assert ".workbench-sidebar .nav-item" in css
assert "min-width: 7.75rem" in css
assert ".status-strip-grid" in css
assert "grid-template-columns: repeat(2, minmax(0, 1fr))" in css
+26
View File
@@ -1,3 +1,29 @@
## Sprint 113 calm workbench layout pass (2026-07-04)
Changed:
- Added a calm-density layer to the frontend shell CSS to reduce visual pressure without changing workflows.
- Softened the base palette, borders and shadows.
- Made the top context bar, left workspace navigation, main heading, readiness tiles and inspector surfaces more compact.
- Hid the duplicated workspace command bar because the sidebar remains the primary persistent navigation.
- Updated `CHANGELOG.md`, `docs/TODO.md` and `frontend/README.md`.
- Added regression coverage in `backend/tests/test_sprint113_calm_workbench_layout.py`.
Validation:
- `cd frontend && npm run typecheck` passed.
- `python -m pytest backend\tests\test_sprint49_workbench_shell_refactor.py backend\tests\test_sprint62_frontend_visual_polish.py backend\tests\test_sprint82_shell_density_polish.py backend\tests\test_sprint83_workspace_panel_hierarchy.py -q` passed: 10 tests.
- `cd frontend && npm run build` passed.
- `python -m pytest backend\tests\test_sprint113_calm_workbench_layout.py -q` passed: 2 tests.
- `python -m compileall backend/app` passed.
- `cd backend && python -m pytest -q` passed: 358 tests.
- `bash scripts/run_readiness_check.sh` passed: 358 backend tests plus frontend typecheck/build.
Limitations:
- This pass improves visual density and hierarchy only; no API, persistence, workflow or map behavior changed.
- Live Tower redeploy still needs to be run after commit/push before the user sees the new layout at `http://192.168.10.150:1202`.
Next recommended pass:
- Do a live visual audit after redeploy and then tune individual workspaces, starting with Data and Map, based on actual screenshots.
## Sprint 112 QA evidence map overlay (2026-06-25)
Changed:
+1
View File
@@ -78,6 +78,7 @@ This file now starts with the current implementation status. Older preparation/b
- [x] Add selected map feature extraction with highlight, property table, copy and GeoJSON download.
- [x] Add QA/QC workspace result hierarchy and filter density polish.
- [x] Add Change Detection panel hierarchy and analysis workspace density polish.
- [x] Add calm workbench layout pass to reduce duplicate navigation, heavy card styling and shell density.
- [x] Add AI Labs Detection/Segmentation hierarchy and result density polish.
- [x] Add Export/System handoff hierarchy and provider registry density polish.
+2
View File
@@ -4,6 +4,8 @@ React + TypeScript + MapLibre foundation for project/area/dataset workflow.
The workbench now uses a task-based shell instead of a single long panel stack. `App.tsx` still owns shared orchestration state, but the UI is organized into Overview, Data, Map, QA/QC, AI Labs, Exports and System workspaces with a persistent top context bar and right-side dataset inspector.
The shell has a calmer V1 workbench density pass: the duplicated workspace command bar is hidden, the sidebar is more compact, the top context bar is quieter, readiness tiles are smaller and panels use softer borders/shadows. This keeps the same workflows and API calls while reducing visual noise on desktop and mobile.
When project data loads and no dataset is selected yet, the workbench auto-opens the first ready vector dataset. This gives Data, Map and Exports an immediately usable default context while preserving explicit user selection once the user picks another dataset.
Data and Map workspaces include mobile-density CSS for file inputs, dataset action buttons, map toolbar controls, range sliders and empty-map quick actions so narrow screens avoid accidental viewport overflow.
+349 -7
View File
@@ -1,15 +1,15 @@
@import 'maplibre-gl/dist/maplibre-gl.css';
:root {
--bg: #eef4f1;
--bg: #f4f7f5;
--panel: #ffffff;
--panel-soft: #f8fbf9;
--panel-soft: #fafcfb;
--surface-raised: #ffffff;
--surface-sunken: #f3f8f5;
--surface-sunken: #f7faf8;
--text: #132018;
--muted: #5f6f67;
--line: #cbd8d0;
--line-strong: #9fb2a7;
--line: #dbe4de;
--line-strong: #b8c8bf;
--accent: #0f766e;
--accent-strong: #115e59;
--accent-soft: #e3f4ef;
@@ -17,8 +17,8 @@
--focus-ring-soft: rgba(15, 118, 110, 0.2);
--warning: #b45309;
--danger: #991b1b;
--shadow: 0 12px 32px rgba(33, 48, 41, 0.08);
--shadow-soft: 0 8px 24px rgba(33, 48, 41, 0.06);
--shadow: 0 10px 26px rgba(33, 48, 41, 0.06);
--shadow-soft: 0 6px 18px rgba(33, 48, 41, 0.045);
color-scheme: light;
}
@@ -3780,3 +3780,345 @@ button.entity-card {
height: 22rem;
}
}
/* Sprint 113 calm workbench UX pass: reduce repeated navigation and visual density without changing workflows. */
body {
background: var(--bg);
}
button {
background: #ffffff;
box-shadow: none;
}
button:hover:not(:disabled) {
box-shadow: 0 0 0 3px rgba(15, 118, 110, 0.08);
}
section {
border-color: var(--line);
background: rgba(255, 255, 255, 0.98);
box-shadow: none;
}
.workbench-shell {
background: var(--bg);
}
.workbench-topbar {
grid-template-columns: minmax(10rem, 14rem) minmax(0, 1fr);
min-height: 3.65rem;
padding: 0.45rem 0.9rem;
background: rgba(255, 255, 255, 0.96);
box-shadow: 0 1px 0 rgba(19, 32, 24, 0.04);
}
.brand-block h1 {
font-size: 1.05rem;
}
.context-bar {
display: flex;
justify-content: flex-end;
gap: 0.45rem;
min-width: 0;
}
.context-bar > div {
min-height: 2.38rem;
min-width: 0;
max-width: 13rem;
border-color: transparent;
border-radius: 6px;
padding: 0.28rem 0.52rem;
background: #f8fbf9;
}
.context-bar span {
font-size: 0.58rem;
letter-spacing: 0.06em;
}
.context-bar strong {
overflow: hidden;
margin-top: 0.1rem;
font-size: 0.75rem;
line-height: 1.2;
text-overflow: ellipsis;
white-space: nowrap;
}
.workbench-layout {
grid-template-columns: 10.25rem minmax(0, 1fr) 18.5rem;
height: calc(100vh - 3.65rem);
}
.workbench-sidebar,
.workbench-inspector {
background: #f8faf8;
}
.workbench-sidebar {
padding: 0.58rem;
}
.workbench-sidebar nav {
gap: 0.28rem;
}
.nav-item {
min-height: 2.55rem;
border-radius: 6px;
padding: 0.42rem 0.52rem;
}
.nav-item span {
font-size: 0.82rem;
}
.nav-item small {
display: none;
}
.nav-item-active {
border-color: rgba(15, 118, 110, 0.22);
box-shadow: inset 3px 0 0 var(--accent);
}
.nav-item-active small {
display: block;
font-size: 0.68rem;
line-height: 1.2;
}
.workbench-main {
padding: 0.82rem 0.95rem 1.05rem;
}
.workbench-inspector {
padding: 0.7rem;
}
.workspace-heading {
margin-bottom: 0.65rem;
border: 0;
border-bottom: 1px solid var(--line);
border-radius: 0;
padding: 0.2rem 0 0.65rem;
background: transparent;
box-shadow: none;
}
.workspace-heading .eyebrow {
margin-bottom: 0.12rem;
}
.workspace-heading h2 {
font-size: 1.18rem;
}
.workspace-heading p:last-child {
max-width: 25rem;
font-size: 0.84rem;
}
.workspace-command-bar {
display: none;
}
.workspace-stack,
.workspace-grid {
gap: 0.75rem;
}
.workspace-panel,
.workflow-guidance-panel,
.overview-actions,
.workbench-status-strip,
.quality-summary-surface,
.quality-evidence-surface,
.quality-control-surface,
.quality-history-surface,
.change-detection-input-surface,
.change-detection-result-surface,
.change-detection-warning-surface,
.map-control-surface,
.map-frame-surface,
.map-inspection-surface,
.inspector-card,
.lab-block,
.result-summary-card,
.handoff-action-card,
.system-provider-card {
border-radius: 6px;
box-shadow: none;
}
.workbench-status-strip {
padding: 0.82rem;
}
.status-strip-header {
gap: 0.65rem;
margin-bottom: 0.7rem;
}
.status-strip-header h2,
.workflow-guidance-panel h2,
.overview-actions h2,
.workspace-panel h2 {
font-size: 1rem;
}
.status-next-action {
font-size: 0.86rem;
}
.status-strip-grid {
grid-template-columns: repeat(6, minmax(0, 1fr));
gap: 0.45rem;
}
.status-tile {
min-height: auto;
padding: 0.5rem;
border-radius: 6px;
}
.status-tile-topline {
gap: 0.28rem;
}
.status-tile strong {
margin-top: 0.25rem;
font-size: 0.84rem;
line-height: 1.2;
}
.status-tile p {
margin-top: 0.18rem;
font-size: 0.72rem;
line-height: 1.25;
}
.status-pill,
.workflow-step-status,
.status-badge {
border-radius: 999px;
padding: 0.16rem 0.38rem;
font-size: 0.62rem;
}
.workflow-guidance-panel {
border-left: 0;
background: #ffffff;
}
.workflow-guidance-steps {
gap: 0.45rem;
}
.workflow-guidance-step {
min-height: 4.35rem;
padding: 0.5rem 0.55rem;
border-color: var(--line);
}
.workflow-guidance-step small {
font-size: 0.7rem;
}
.inspector-tabs {
gap: 0.25rem;
}
.inspector-tab {
min-height: 2rem;
padding: 0.34rem 0.45rem;
font-size: 0.76rem;
}
.inspector-card {
padding: 0.68rem;
}
.inspector-field {
gap: 0.35rem;
}
@media (max-width: 1360px) {
.workbench-layout {
grid-template-columns: 9.5rem minmax(0, 1fr);
height: auto;
}
.workbench-inspector {
max-height: none;
}
}
@media (max-width: 980px) {
.workbench-topbar {
position: sticky;
grid-template-columns: 1fr;
gap: 0.45rem;
min-height: auto;
}
.context-bar {
justify-content: flex-start;
overflow-x: auto;
padding-bottom: 0.15rem;
}
.context-bar > div {
min-width: 9.25rem;
}
.workbench-sidebar {
top: 5.3rem;
}
.workspace-command-bar {
display: none;
}
.status-strip-grid {
grid-template-columns: repeat(3, minmax(0, 1fr));
}
}
@media (max-width: 620px) {
.workbench-topbar,
.workbench-main,
.workbench-inspector,
.workbench-sidebar {
padding: 0.62rem;
}
.context-bar > div {
min-width: 8.5rem;
}
.workbench-sidebar .nav-item {
min-width: 7.75rem;
min-height: 2.75rem;
}
.nav-item-active small {
display: none;
}
.workspace-heading {
display: block;
}
.workspace-heading p:last-child {
margin-top: 0.25rem;
text-align: left;
}
.status-strip-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}