Harden mobile workbench overflow
This commit is contained in:
@@ -7,6 +7,15 @@
|
|||||||
|
|
||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Sprint 72 Mobile overflow hardening (2026-06-20)
|
||||||
|
|
||||||
|
- Clamped page-level horizontal overflow for the workbench shell on mobile.
|
||||||
|
- Kept sidebar navigation and workspace shortcut chips as contained horizontal scroll areas.
|
||||||
|
- Added wrapping/containment for long QA identifiers, dataset links and inspector values.
|
||||||
|
- Made inspector tabs two-column on narrow screens to avoid header overflow.
|
||||||
|
- Added static regression coverage for mobile overflow and long-identifier wrapping contracts.
|
||||||
|
- No API contracts, migrations, backend behavior, provider fetching or AI model behavior changed.
|
||||||
|
|
||||||
## Sprint 71 QA/QC metric card polish (2026-06-19)
|
## Sprint 71 QA/QC metric card polish (2026-06-19)
|
||||||
|
|
||||||
- Added core metric evidence cards for precision, recall, F1, mean IoU and false positive/negative counts.
|
- Added core metric evidence cards for precision, recall, F1, mean IoU and false positive/negative counts.
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
|
||||||
|
|
||||||
|
def test_mobile_overflow_hardening_css_contracts() -> None:
|
||||||
|
css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert "overflow-x: hidden;" in css
|
||||||
|
assert ".workbench-shell" in css
|
||||||
|
assert "max-width: 100vw;" in css
|
||||||
|
assert ".workbench-sidebar nav" in css
|
||||||
|
assert ".workspace-nav-cluster" in css
|
||||||
|
assert ".inspector-tabs" in css
|
||||||
|
assert "repeat(2, minmax(0, 1fr))" in css
|
||||||
|
assert "overflow-x: clip;" in css
|
||||||
|
assert "overscroll-behavior-x: contain;" in css
|
||||||
|
|
||||||
|
|
||||||
|
def test_long_identifier_wrapping_contracts() -> None:
|
||||||
|
css = (ROOT / "frontend" / "src" / "styles" / "app.css").read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert ".quality-check-dataset-link" in css
|
||||||
|
assert ".quality-score-row strong" in css
|
||||||
|
assert ".inspector-field strong" in css
|
||||||
|
assert "overflow-wrap: anywhere;" in css
|
||||||
|
assert "word-break: break-word;" in css
|
||||||
@@ -2697,3 +2697,32 @@ Limitations:
|
|||||||
|
|
||||||
Next recommended pass:
|
Next recommended pass:
|
||||||
- Continue with QA/QC metric/result filtering or result-card density for long-lived demo projects.
|
- Continue with QA/QC metric/result filtering or result-card density for long-lived demo projects.
|
||||||
|
|
||||||
|
## Sprint 72 Mobile overflow hardening (2026-06-20)
|
||||||
|
|
||||||
|
Changed:
|
||||||
|
- Clamped page-level horizontal overflow for `html`, `body` and the workbench shell.
|
||||||
|
- Kept mobile sidebar navigation and workspace shortcut chips as contained horizontal scroll regions with overscroll containment.
|
||||||
|
- Added min-width/max-width containment for the workbench layout, main area, inspector panel and card surfaces.
|
||||||
|
- Allowed long QA check IDs, dataset links and inspector values to wrap instead of widening result cards.
|
||||||
|
- Switched inspector tabs to a two-column layout on narrow screens.
|
||||||
|
- Added `backend/tests/test_sprint72_mobile_overflow_hardening.py`.
|
||||||
|
- Updated `frontend/README.md`, `docs/TODO.md` and `CHANGELOG.md`.
|
||||||
|
|
||||||
|
Tested:
|
||||||
|
- Red step: `python -m pytest backend/tests/test_sprint72_mobile_overflow_hardening.py -q` failed on missing mobile overflow and identifier wrapping contracts.
|
||||||
|
- `python -m pytest backend/tests/test_sprint72_mobile_overflow_hardening.py backend/tests/test_sprint71_quality_metric_polish.py backend/tests/test_sprint62_frontend_visual_polish.py backend/tests/test_sprint30_workbench_components.py -q` (`11 passed`)
|
||||||
|
- `cd frontend && npm run typecheck`
|
||||||
|
- `cd frontend && npm run build`
|
||||||
|
- Local browser check against `http://127.0.0.1:5176` with live API proxy at a 390px viewport: QA/QC workspace rendered 2 quality cards and 12 metric cards; body, shell, inspector, inspector panel and inspector tabs stayed within viewport width; sidebar/workspace nav retained contained horizontal scrolling; no console warnings/errors.
|
||||||
|
- Screenshot captured under `artifacts/sprint72-mobile-overflow-hardening/`.
|
||||||
|
- `bash scripts/run_readiness_check.sh` (`255 passed`)
|
||||||
|
|
||||||
|
Open:
|
||||||
|
- Redeploy Tower and verify live mobile overflow after deployment.
|
||||||
|
|
||||||
|
Limitations:
|
||||||
|
- Frontend CSS hardening only; no UI flow, API, persistence, migration, provider or AI/model changes.
|
||||||
|
|
||||||
|
Next recommended pass:
|
||||||
|
- Continue with QA/QC result filtering/density for long-lived demo projects, or a broader mobile visual pass across Data and Map once the overflow baseline is stable.
|
||||||
|
|||||||
@@ -343,3 +343,4 @@ This file now starts with the current implementation status. Older preparation/b
|
|||||||
- [x] Add Data catalog action polish for map, metadata, export and QA affordances.
|
- [x] Add Data catalog action polish for map, metadata, export and QA affordances.
|
||||||
- [x] Add QA/QC handoff polish for candidate/reference context and persisted results.
|
- [x] Add QA/QC handoff polish for candidate/reference context and persisted results.
|
||||||
- [x] Add QA/QC metric card polish for precision, recall, F1, IoU and error counts.
|
- [x] Add QA/QC metric card polish for precision, recall, F1, IoU and error counts.
|
||||||
|
- [x] Add mobile overflow hardening for workbench navigation, inspector and long QA identifiers.
|
||||||
|
|||||||
@@ -285,6 +285,8 @@ The frontend API client uses same-origin requests by default. In Docker Compose,
|
|||||||
|
|
||||||
The QA/QC workspace promotes core metrics into evidence cards before the raw metric list, keeping precision, recall, F1, mean IoU and false positive/negative counts scan-friendly while preserving the persisted raw metrics.
|
The QA/QC workspace promotes core metrics into evidence cards before the raw metric list, keeping precision, recall, F1, mean IoU and false positive/negative counts scan-friendly while preserving the persisted raw metrics.
|
||||||
|
|
||||||
|
The workbench shell clamps page-level horizontal overflow on mobile while keeping the sidebar and workspace shortcut rows intentionally scrollable. Long QA identifiers and inspector values wrap inside their cards instead of widening the viewport.
|
||||||
|
|
||||||
## Useful repository scripts
|
## Useful repository scripts
|
||||||
|
|
||||||
- `bash scripts/frontend_install.sh`
|
- `bash scripts/frontend_install.sh`
|
||||||
|
|||||||
@@ -25,10 +25,12 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
html {
|
html {
|
||||||
|
overflow-x: hidden;
|
||||||
background: var(--bg);
|
background: var(--bg);
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
overflow-x: hidden;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-family: Inter, 'Avenir Next', 'Segoe UI', sans-serif;
|
font-family: Inter, 'Avenir Next', 'Segoe UI', sans-serif;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
@@ -39,6 +41,11 @@ body {
|
|||||||
text-rendering: optimizeLegibility;
|
text-rendering: optimizeLegibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workbench-shell {
|
||||||
|
max-width: 100vw;
|
||||||
|
overflow-x: clip;
|
||||||
|
}
|
||||||
|
|
||||||
button,
|
button,
|
||||||
input,
|
input,
|
||||||
select,
|
select,
|
||||||
@@ -514,7 +521,8 @@ section li strong + div {
|
|||||||
|
|
||||||
.workbench-shell {
|
.workbench-shell {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
max-width: none;
|
max-width: 100vw;
|
||||||
|
overflow-x: clip;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background: #eef4f1;
|
background: #eef4f1;
|
||||||
}
|
}
|
||||||
@@ -579,10 +587,13 @@ section li strong + div {
|
|||||||
gap: 0;
|
gap: 0;
|
||||||
height: calc(100vh - 4.35rem);
|
height: calc(100vh - 4.35rem);
|
||||||
min-height: 42rem;
|
min-height: 42rem;
|
||||||
|
max-width: 100vw;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workbench-sidebar,
|
.workbench-sidebar,
|
||||||
.workbench-inspector {
|
.workbench-inspector {
|
||||||
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border-color: var(--line);
|
border-color: var(--line);
|
||||||
@@ -640,6 +651,7 @@ section li strong + div {
|
|||||||
.workbench-main {
|
.workbench-main {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
|
max-width: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding: 0.9rem 1.05rem 1.15rem;
|
padding: 0.9rem 1.05rem 1.15rem;
|
||||||
}
|
}
|
||||||
@@ -1066,6 +1078,7 @@ button.entity-card {
|
|||||||
.export-card,
|
.export-card,
|
||||||
.latest-export-card,
|
.latest-export-card,
|
||||||
.empty-state {
|
.empty-state {
|
||||||
|
min-width: 0;
|
||||||
padding: 0.85rem;
|
padding: 0.85rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1270,6 +1283,7 @@ button.entity-card {
|
|||||||
.quality-dataset-name,
|
.quality-dataset-name,
|
||||||
.quality-check-dataset-link {
|
.quality-check-dataset-link {
|
||||||
overflow-wrap: anywhere;
|
overflow-wrap: anywhere;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quality-dataset-name {
|
.quality-dataset-name {
|
||||||
@@ -1301,7 +1315,13 @@ button.entity-card {
|
|||||||
font-size: 0.9rem;
|
font-size: 0.9rem;
|
||||||
line-height: 1.25;
|
line-height: 1.25;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quality-score-row strong,
|
||||||
|
.inspector-field strong {
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
|
||||||
.quality-metric-section {
|
.quality-metric-section {
|
||||||
@@ -1710,11 +1730,17 @@ button.entity-card {
|
|||||||
.workbench-inspector-panel {
|
.workbench-inspector-panel {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.68rem;
|
gap: 0.68rem;
|
||||||
|
max-width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
overflow-x: clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inspector-header {
|
.inspector-header {
|
||||||
display: grid;
|
display: grid;
|
||||||
gap: 0.2rem;
|
gap: 0.2rem;
|
||||||
|
max-width: 100%;
|
||||||
|
min-width: 0;
|
||||||
|
overflow-x: clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inspector-header h2 {
|
.inspector-header h2 {
|
||||||
@@ -1734,12 +1760,14 @@ button.entity-card {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.inspector-tab {
|
.inspector-tab {
|
||||||
|
min-width: 0;
|
||||||
min-height: 2.2rem;
|
min-height: 2.2rem;
|
||||||
padding: 0.38rem 0.42rem;
|
padding: 0.38rem 0.42rem;
|
||||||
background: #ffffff;
|
background: #ffffff;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
font-size: 0.78rem;
|
font-size: 0.78rem;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
}
|
}
|
||||||
|
|
||||||
.inspector-tab-active {
|
.inspector-tab-active {
|
||||||
@@ -1882,6 +1910,7 @@ button.entity-card {
|
|||||||
position: sticky;
|
position: sticky;
|
||||||
top: 5.8rem;
|
top: 5.8rem;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
|
max-width: 100vw;
|
||||||
border-right: 0;
|
border-right: 0;
|
||||||
border-bottom: 1px solid var(--line);
|
border-bottom: 1px solid var(--line);
|
||||||
}
|
}
|
||||||
@@ -1941,16 +1970,26 @@ button.entity-card {
|
|||||||
padding: 0.75rem;
|
padding: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.workbench-inspector {
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
.context-bar,
|
.context-bar,
|
||||||
.quick-action-grid,
|
.quick-action-grid,
|
||||||
.workspace-nav-cluster {
|
.workspace-nav-cluster {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.inspector-tabs {
|
||||||
|
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||||
|
}
|
||||||
|
|
||||||
.workbench-sidebar nav {
|
.workbench-sidebar nav {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
|
max-width: 100%;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
overscroll-behavior-x: contain;
|
||||||
padding-bottom: 0.2rem;
|
padding-bottom: 0.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1961,7 +2000,9 @@ button.entity-card {
|
|||||||
.workspace-nav-cluster {
|
.workspace-nav-cluster {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
|
max-width: 100%;
|
||||||
overflow-x: auto;
|
overflow-x: auto;
|
||||||
|
overscroll-behavior-x: contain;
|
||||||
padding-bottom: 0.1rem;
|
padding-bottom: 0.1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user