From db1bbc700504164b85f3e60b0c531e3c85f04109 Mon Sep 17 00:00:00 2001 From: Codex Date: Sat, 20 Jun 2026 01:11:45 +0200 Subject: [PATCH] Polish Data Map mobile layout --- CHANGELOG.md | 8 +++ .../test_sprint74_data_map_mobile_polish.py | 36 ++++++++++++ docs/CODEX_EXECUTION_LOG.md | 27 +++++++++ docs/TODO.md | 1 + frontend/README.md | 2 + frontend/src/styles/app.css | 55 ++++++++++++++++++- 6 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 backend/tests/test_sprint74_data_map_mobile_polish.py diff --git a/CHANGELOG.md b/CHANGELOG.md index c61a0bf9..c442df92 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ # Changelog +## Sprint 74 Data/Map mobile visual polish (2026-06-20) + +- Tightened mobile Data workspace upload form, file input and dataset action button sizing. +- Kept desktop dataset action grid width contract while adding compact mobile tracks. +- Tightened Map toolbar, layer control sliders and empty-map quick actions for narrow screens. +- Added static regression coverage for Data/Map mobile CSS contracts. +- No API contracts, migrations, backend behavior, provider fetching or AI model behavior changed. + ## Sprint 73 QA/QC result filtering (2026-06-20) - Added client-side QA/QC result search, status and check-type filters. diff --git a/backend/tests/test_sprint74_data_map_mobile_polish.py b/backend/tests/test_sprint74_data_map_mobile_polish.py new file mode 100644 index 00000000..c779838b --- /dev/null +++ b/backend/tests/test_sprint74_data_map_mobile_polish.py @@ -0,0 +1,36 @@ +from pathlib import Path + + +ROOT = Path(__file__).resolve().parents[2] + + +def test_data_and_map_mobile_polish_css_contracts() -> None: + css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8") + + assert ".file-input-label input[type='file']" in css + assert ".dataset-upload-form label" in css + assert ".dataset-action-grid" in css + assert ".dataset-action-button" in css + assert ".map-toolbar" in css + assert ".layer-control-card input[type='range']" in css + assert ".map-empty-action-grid" in css + assert ".map-empty-action-grid button" in css + assert "minmax(7.25rem, 1fr)" in css + assert "touch-action: pan-x;" in css + + +def test_data_and_map_components_keep_existing_workflow_markup() -> None: + dataset_panel = (ROOT / "frontend" / "src" / "components" / "datasets" / "DatasetPanel.tsx").read_text( + encoding="utf-8" + ) + map_workspace = (ROOT / "frontend" / "src" / "components" / "map" / "MapWorkspace.tsx").read_text( + encoding="utf-8" + ) + + assert 'className="dataset-upload-form"' in dataset_panel + assert 'className="file-input-label"' in dataset_panel + assert "dataset-action-grid" in dataset_panel + assert "dataset-action-button" in dataset_panel + assert "map-toolbar" in map_workspace + assert "layer-control-card" in map_workspace + assert "map-empty-action-grid" in map_workspace diff --git a/docs/CODEX_EXECUTION_LOG.md b/docs/CODEX_EXECUTION_LOG.md index cf01cc45..371a9ac9 100644 --- a/docs/CODEX_EXECUTION_LOG.md +++ b/docs/CODEX_EXECUTION_LOG.md @@ -2763,3 +2763,30 @@ Limitations: Next recommended pass: - Continue with Data/Map mobile visual polish, especially dataset upload/action forms and map toolbar density on narrow screens. + +## Sprint 74 Data/Map mobile visual polish (2026-06-20) + +Changed: +- Added mobile-density CSS for Data workspace upload forms, file input sizing and dataset action grids. +- Kept the desktop dataset action grid width contract intact while adding compact mobile tracks. +- Added touch/width containment for map toolbar controls, range sliders and empty-map quick actions. +- Reduced mobile map container height to keep controls and map visible together on narrow screens. +- Added `backend/tests/test_sprint74_data_map_mobile_polish.py`. +- Updated `frontend/README.md`, `docs/TODO.md` and `CHANGELOG.md`. + +Tested: +- Red step: `python -m pytest backend/tests/test_sprint74_data_map_mobile_polish.py -q` failed on missing mobile Data/Map CSS contracts. +- `python -m pytest backend/tests/test_sprint74_data_map_mobile_polish.py backend/tests/test_sprint72_mobile_overflow_hardening.py backend/tests/test_sprint69_dataset_action_polish.py backend/tests/test_sprint68_dataset_catalog_density.py backend/tests/test_sprint67_map_empty_state_quick_actions.py backend/tests/test_sprint63_map_overlay_ergonomics.py backend/tests/test_sprint50_workspace_usability_polish.py backend/tests/test_sprint30_workbench_components.py -q` (`21 passed`) +- `cd frontend && npm run typecheck` +- `cd frontend && npm run build` +- Local browser check against `http://127.0.0.1:5178` with live API proxy at a 390px viewport: Data upload form, file input and 8 dataset action buttons stayed within the viewport with no body-level horizontal overflow; Map toolbar, 2 layer controls, range sliders and empty-map quick actions also stayed within the viewport. +- Screenshots captured under `artifacts/sprint74-data-map-mobile-polish/`. + +Open: +- Run full readiness, redeploy Tower and verify live Data/Map mobile polish after deployment. + +Limitations: +- Frontend CSS polish only; no Data/Map workflow, API, persistence, migration, provider or AI/model changes. + +Next recommended pass: +- Continue with AI Labs mobile/density polish, especially detection and segmentation forms/tables. diff --git a/docs/TODO.md b/docs/TODO.md index 610bfc6b..466f9e56 100644 --- a/docs/TODO.md +++ b/docs/TODO.md @@ -63,6 +63,7 @@ This file now starts with the current implementation status. Older preparation/b - [x] Expand golden QA/QC benchmark coverage across partial, perfect, no-overlap and MultiPolygon scenarios. - [x] Improve workbench shell visual polish, mobile navigation density and AI result readability. - [x] Improve Map workspace layer provenance, empty guidance and selected-feature summary readability. +- [x] Add Data/Map mobile visual polish for upload forms, action grids and map toolbar density. ## Sprint 8 status diff --git a/frontend/README.md b/frontend/README.md index c3eab265..cb91c61a 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -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. +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. + ## Scope implemented - API client layer (`src/services/api`) - Project and area list/create flows diff --git a/frontend/src/styles/app.css b/frontend/src/styles/app.css index 226cfdc5..e10d6080 100644 --- a/frontend/src/styles/app.css +++ b/frontend/src/styles/app.css @@ -284,9 +284,11 @@ section { gap: 0.5rem; align-items: center; margin-top: 0.72rem; + min-width: 0; } .checkbox-row input { + flex: 0 0 auto; width: auto; min-height: auto; margin: 0; @@ -951,6 +953,19 @@ section th { background: var(--panel-soft); } +.dataset-upload-form label, +.file-input-label { + min-width: 0; +} + +.file-input-label input[type='file'] { + width: 100%; + min-width: 0; + max-width: 100%; + overflow: hidden; + text-overflow: ellipsis; +} + .data-density-grid { border: 1px solid var(--line); border-radius: 7px; @@ -1173,6 +1188,7 @@ button.entity-card { min-height: 3.25rem; margin-top: 0; text-align: left; + touch-action: pan-x; } .dataset-action-button span, @@ -1424,17 +1440,19 @@ button.entity-card { .map-empty-action-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(7.25rem, 1fr)); gap: 0.55rem; margin-top: 0.5rem; } .map-empty-action-grid button { display: grid; + min-width: 0; min-height: 4.2rem; gap: 0.18rem; margin-top: 0; text-align: left; + touch-action: pan-x; } .map-empty-action-grid span, @@ -1646,7 +1664,7 @@ button.entity-card { .map-toolbar { display: grid; - grid-template-columns: repeat(auto-fit, minmax(12rem, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr)); gap: 0.75rem; align-items: end; margin-bottom: 0.85rem; @@ -1655,17 +1673,22 @@ button.entity-card { .layer-control-card { display: grid; gap: 0.5rem; + min-width: 0; padding: 0.58rem 0.65rem; } .layer-control-card input[type='range'] { + width: 100%; + min-width: 0; min-height: auto; padding: 0; + touch-action: pan-x; } .map-status { display: grid; gap: 0.25rem; + min-width: 0; border: 1px solid var(--line); border-radius: 8px; padding: 0.62rem 0.72rem; @@ -2029,4 +2052,32 @@ button.entity-card { .status-strip-grid { grid-template-columns: 1fr; } + + .dataset-upload-form { + gap: 0.55rem; + padding: 0.68rem; + } + + .dataset-action-grid, + .map-empty-action-grid { + grid-template-columns: repeat(auto-fit, minmax(7.25rem, 1fr)); + } + + .dataset-action-button, + .map-empty-action-grid button { + min-height: 3rem; + padding: 0.48rem 0.56rem; + } + + .map-toolbar { + gap: 0.55rem; + } + + .layer-control-card { + padding: 0.52rem 0.58rem; + } + + .workbench-main .map-container { + height: 22rem; + } }