feat(ui): align workbench with Stitch screens
This commit is contained in:
@@ -13,6 +13,14 @@
|
||||
Atlas Workbench. The new shell uses one compact icon navigation rail, one
|
||||
context bar and task-specific work surfaces across Map, Sources, AI
|
||||
Questions, Quality, Image Analysis, Downloads, Status and Administration.
|
||||
- Completed a screen-by-screen Stitch parity pass with dedicated designs for
|
||||
Quality, Image Analysis, Downloads and Status/Administration. Sources,
|
||||
Quality, Image Analysis and Downloads now use the same master-detail and
|
||||
inspector structures as their Stitch references instead of generic panel
|
||||
stacks.
|
||||
- Bundled Public Sans and Manrope locally and aligned the implementation with
|
||||
the exact Stitch canvas, context, ink, border, teal, steel and amber tokens.
|
||||
No API, persistence, GIS or AI behavior changed.
|
||||
- Restored the normal desktop map to one stable theme/map/insight row, made
|
||||
the map absorb ultrawide space, bounded the mobile theme list and removed
|
||||
the duplicate workspace command bar. API, database, GIS and AI behavior are
|
||||
|
||||
@@ -10861,3 +10861,51 @@ Behavior preservation:
|
||||
calculation, model runtime or persistence flow changed.
|
||||
- Existing map selection, source loading, local Ollama, QA, analysis and
|
||||
download actions remain wired through their original hooks and services.
|
||||
|
||||
## 2026-07-19 - Stitch screen parity and responsive refinement
|
||||
|
||||
Implemented:
|
||||
|
||||
- Extended the Stitch project with dedicated Quality, Image Analysis,
|
||||
Downloads and Status/Administration screens, all using design-system asset
|
||||
`4667932515738184526`.
|
||||
- Replaced the residual dark navigation treatment with the white 88-pixel
|
||||
Stitch rail, pale context bar and locally bundled Public Sans/Manrope
|
||||
typography.
|
||||
- Made Sources a deterministic three-pane workspace after removing a legacy
|
||||
full-width catalogue override.
|
||||
- Added the Stitch control/result/inspector structure to the empty Quality
|
||||
state and kept the existing populated evidence/history implementation.
|
||||
- Compacted detection model administration into one row above the existing
|
||||
configuration/result/QA workbench.
|
||||
- Reorganized Downloads as artifact actions, current/history results and a
|
||||
preview inspector without changing export callbacks or formats.
|
||||
- Kept the MapLibre map full-height with icon controls and stable rails on
|
||||
normal and ultrawide displays.
|
||||
|
||||
Visual verification:
|
||||
|
||||
- compared Map, Sources, AI Questions, Quality, Image Analysis, Downloads,
|
||||
Status and Administration against their dedicated Stitch references;
|
||||
- reviewed live-backend states at 1280x720, 1920x1080 and 390x844;
|
||||
- confirmed that the widescreen map absorbs the additional width and that the
|
||||
mobile workspaces remain vertically navigable without document overflow.
|
||||
|
||||
Validation:
|
||||
|
||||
- the complete readiness gate passed 1,052 backend tests, 22 frontend tests,
|
||||
frontend typecheck/build and Alembic head `202607160001`;
|
||||
- the final UX browser audit passed at 390x844, 1366x768 and 2560x1080 with
|
||||
zero horizontal overflow, console errors or failed requests;
|
||||
- all seven Belgium/North Sea release journeys passed through the redesigned
|
||||
local frontend against the live backend;
|
||||
- the journey retry caught and verified a fixed Sources grid containment issue
|
||||
that previously allowed the Area panel to intercept a scrolled Project
|
||||
management control.
|
||||
|
||||
Behavior preservation:
|
||||
|
||||
- no backend, API contract, migration, persistence, GIS metric, provider,
|
||||
Ollama or model-runtime behavior changed;
|
||||
- all existing actions continue through the original React hooks and service
|
||||
layer.
|
||||
|
||||
@@ -15,9 +15,15 @@ The redesign was developed in Stitch under:
|
||||
- Map Explorer screen: `c24113d1f1474c91b332b2365be24993`
|
||||
- Sources screen: `239796f2d66a44e7983e5fc588305ff8`
|
||||
- AI Questions screen: `246aa57bbe974861885325ff9d10c6bd`
|
||||
- Quality screen: `06b4b69387d847a0bba33c6953563860`
|
||||
- Image Analysis screen: `200a196f4e524c979167e40905ae87f2`
|
||||
- Downloads screen: `f6d91a48e98141bb94f680f626078a1e`
|
||||
- Status and Administration screen: `3d685f83c61d4e9687bdfdf608220b26`
|
||||
|
||||
The React implementation remains the source of truth for behavior. Stitch is
|
||||
the design reference for hierarchy, spacing and component treatment.
|
||||
the design reference for hierarchy, spacing and component treatment. Each
|
||||
primary workspace has a dedicated Stitch screen; new layout work must compare
|
||||
against the corresponding screen rather than only borrowing the color palette.
|
||||
|
||||
## Product hierarchy
|
||||
|
||||
@@ -37,6 +43,12 @@ command bars or competing shortcut rows must not be reintroduced.
|
||||
|
||||
- Desktop uses an 88-pixel navigation rail and a 56-pixel context bar.
|
||||
- The normal map layout is `theme drawer / map / insight inspector`.
|
||||
- Sources uses `workspace and area / source inventory / loaded datasets`.
|
||||
- AI Questions uses `area context / conversation and composer`.
|
||||
- Quality uses `controls / result history / evidence inspector`.
|
||||
- Image Analysis uses `configuration / persisted results / QA`.
|
||||
- Downloads uses `artifact actions / export history / preview inspector`.
|
||||
- Administration uses `source category / provider status and provenance`.
|
||||
- Theme and insight rails stay stable on ultrawide displays; the map receives
|
||||
the additional width.
|
||||
- Non-map workspaces use one task header and one primary work surface.
|
||||
@@ -50,17 +62,21 @@ command bars or competing shortcut rows must not be reintroduced.
|
||||
|
||||
| Role | Value |
|
||||
| --- | --- |
|
||||
| Canvas | `#f3f6f5` |
|
||||
| Canvas | `#f5f7f6` |
|
||||
| Surface | `#ffffff` |
|
||||
| Ink | `#152522` |
|
||||
| Muted text | `#687773` |
|
||||
| Border | `#dce4e1` |
|
||||
| Pale context | `#eef8f5` |
|
||||
| Ink | `#162622` |
|
||||
| Muted text | `#64726f` |
|
||||
| Border | `#e1e7e5` |
|
||||
| Primary teal | `#0b6b62` |
|
||||
| Context blue | `#315d73` |
|
||||
| Attention amber | `#a55c23` |
|
||||
| Attention amber | `#b46432` |
|
||||
| Error red | `#a33c39` |
|
||||
| Radius | `4px` |
|
||||
|
||||
Body and labels use locally bundled Public Sans. Headings use locally bundled
|
||||
Manrope. The interface must not depend on a remote font request.
|
||||
|
||||
The UI does not use gradients, decorative blobs, oversized hero sections,
|
||||
nested cards or pill-heavy status presentation.
|
||||
|
||||
@@ -84,6 +100,8 @@ nested cards or pill-heavy status presentation.
|
||||
`frontend/src/styles/atlas-workbench.css`
|
||||
- Map workflow:
|
||||
`frontend/src/components/map/MapWorkspace.tsx`
|
||||
- Empty and populated quality review:
|
||||
`frontend/src/components/quality/QualityResultsPanel.tsx`
|
||||
- API, persistence and GIS behavior remain outside the design system.
|
||||
|
||||
Any future visual change must retain the browser acceptance widths of
|
||||
|
||||
@@ -127,6 +127,16 @@ The visual contract, Stitch project and screen references are documented in
|
||||
hierarchy only; API, persistence and GIS behavior remain owned by the existing
|
||||
hooks and services.
|
||||
|
||||
All eight user-facing destinations now use the Stitch Atlas composition
|
||||
directly. Map is a flush theme/canvas/insight surface; Sources is a
|
||||
workspace/catalog/dataset master-detail view; AI Questions keeps context beside
|
||||
the conversation; Quality keeps controls, results and evidence in three stable
|
||||
panes; Image Analysis keeps run configuration, persisted results and QA aligned;
|
||||
Downloads separates artifact actions, history and preview; Status and
|
||||
Administration use compact operational rows. Public Sans and Manrope are
|
||||
bundled with the frontend, so typography remains identical without a remote
|
||||
font dependency.
|
||||
|
||||
## Current component boundaries
|
||||
|
||||
`App.tsx` remains the shared workspace orchestrator, while focused surfaces
|
||||
|
||||
Generated
+20
@@ -8,6 +8,8 @@
|
||||
"name": "geointel-frontend",
|
||||
"version": "1.0.0",
|
||||
"dependencies": {
|
||||
"@fontsource/manrope": "^5.3.0",
|
||||
"@fontsource/public-sans": "^5.3.0",
|
||||
"lucide-react": "^1.25.0",
|
||||
"maplibre-gl": "^4.7.1",
|
||||
"react": "^18.2.0",
|
||||
@@ -898,6 +900,24 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/manrope": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/manrope/-/manrope-5.3.0.tgz",
|
||||
"integrity": "sha512-obJ1Dv3+uCA6HlHgW8u4BGYxJR9In2HW7gjJhlflEvkrj1X1iSEwu0fToL+JYGC/FEKFfIz1sBuPduvcL2gIAA==",
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
},
|
||||
"node_modules/@fontsource/public-sans": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@fontsource/public-sans/-/public-sans-5.3.0.tgz",
|
||||
"integrity": "sha512-kjODI0S3zdv0mBYCIQ8TbBayaiqszpc2UbhJiO3bjIqVVXzcWfHSt2o3WBCLOY3juaGaQoy4MoWCcgmfI5hCuA==",
|
||||
"license": "OFL-1.1",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ayuhito"
|
||||
}
|
||||
},
|
||||
"node_modules/@jridgewell/gen-mapping": {
|
||||
"version": "0.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
"node": "^20.19.0 || >=22.12.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fontsource/manrope": "^5.3.0",
|
||||
"@fontsource/public-sans": "^5.3.0",
|
||||
"lucide-react": "^1.25.0",
|
||||
"maplibre-gl": "^4.7.1",
|
||||
"react": "^18.2.0",
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react'
|
||||
import '@fontsource/manrope/latin-500.css'
|
||||
import '@fontsource/manrope/latin-600.css'
|
||||
import '@fontsource/manrope/latin-700.css'
|
||||
import '@fontsource/public-sans/latin-400.css'
|
||||
import '@fontsource/public-sans/latin-500.css'
|
||||
import '@fontsource/public-sans/latin-600.css'
|
||||
import './styles/app.css'
|
||||
import './styles/premium.css'
|
||||
import './styles/atlas-workbench.css'
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState, type KeyboardEvent } from 'react'
|
||||
import { BoxSelect, MapPinned, SlidersHorizontal, Trash2 } from 'lucide-react'
|
||||
import GeoMap from '../GeoMap'
|
||||
import type { AreaRead, CoverageResolveResponse, CoverageStatus, DatasetCreateResponse, DetectionQaResult, MapResultExportRequest, MapViewportState, OrthophotoAcquisitionResult, OrthophotoProductRead, ProjectRead, QaComparisonResult, VectorSelectionBBox, VectorSelectionMetric, VectorSelectionResponse } from '../../types'
|
||||
import { useMapThemeSelectionInsights, type MapThemeAcquisition, type MapThemeQuery } from '../../hooks/useMapThemeSelectionInsights'
|
||||
@@ -1905,8 +1906,11 @@ export function MapWorkspace({
|
||||
onClick={() => setAdvancedMode(true)}
|
||||
aria-expanded={advancedMode}
|
||||
aria-controls="geo-advanced-workbench"
|
||||
aria-label="Geavanceerde werkbank"
|
||||
title="Geavanceerde werkbank"
|
||||
>
|
||||
Geavanceerde werkbank
|
||||
<SlidersHorizontal aria-hidden="true" />
|
||||
<span>Geavanceerde werkbank</span>
|
||||
</button>
|
||||
</header>
|
||||
|
||||
@@ -2210,6 +2214,7 @@ export function MapWorkspace({
|
||||
type="button"
|
||||
onClick={startBboxSelection}
|
||||
>
|
||||
<BoxSelect aria-hidden="true" />
|
||||
{bboxSelectionMode ? 'Teken op de kaart…' : 'Teken rechthoek'}
|
||||
</button>
|
||||
<button
|
||||
@@ -2223,9 +2228,11 @@ export function MapWorkspace({
|
||||
}
|
||||
onClick={() => selectedAreaBbox && void analyzeSelection(selectedAreaBbox, selectedMapArea?.id)}
|
||||
>
|
||||
<MapPinned aria-hidden="true" />
|
||||
{regionalRasterThemeActive || regionalOnDemandThemeActive ? 'Selecteer een deelgebied' : 'Volledig werkgebied'}
|
||||
</button>
|
||||
<button className="secondary-action" disabled={!mapSelectionBbox} type="button" onClick={clearAreaSelection}>
|
||||
<Trash2 aria-hidden="true" />
|
||||
Wis selectie
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -208,14 +208,48 @@ export function QualityResultsPanel({
|
||||
</div>
|
||||
|
||||
{qualityChecks.length === 0 ? (
|
||||
<div className="result-state result-state-empty quality-user-empty-state">
|
||||
<strong>Nog geen kwaliteitscontrole uitgevoerd</strong>
|
||||
<p>Selecteer een gebied op de kaart en vergelijk een bewaard resultaat met een officiële referentielaag.</p>
|
||||
<div className="quality-empty-workbench" aria-label="Lege kwaliteitswerkruimte">
|
||||
<aside className="quality-empty-context">
|
||||
<span className="eyebrow">Controles</span>
|
||||
<strong>Nog geen resultaten</strong>
|
||||
<p>Kwaliteitscontroles verschijnen hier nadat een resultaat met een officiële referentielaag is vergeleken.</p>
|
||||
<div className="quality-empty-context-stat">
|
||||
<span>Te controleren lagen</span>
|
||||
<strong>{candidateDatasets.length}</strong>
|
||||
</div>
|
||||
<div className="quality-empty-context-stat">
|
||||
<span>Referentielagen</span>
|
||||
<strong>{referenceDatasets.length}</strong>
|
||||
</div>
|
||||
<button type="button" className="secondary-action" onClick={onRefresh} disabled={!selectedProjectId}>
|
||||
Resultaten vernieuwen
|
||||
</button>
|
||||
</aside>
|
||||
<div className="quality-empty-results">
|
||||
<div className="quality-empty-column-heading">
|
||||
<strong>Resultaten</strong>
|
||||
<span>0 controles</span>
|
||||
</div>
|
||||
<div className="result-state result-state-empty quality-user-empty-state">
|
||||
<strong>Nog geen kwaliteitscontrole uitgevoerd</strong>
|
||||
<p>Selecteer een gebied op de kaart en vergelijk een bewaard resultaat met een officiële referentielaag.</p>
|
||||
</div>
|
||||
</div>
|
||||
<aside className="quality-empty-inspector">
|
||||
<div className="quality-empty-column-heading">
|
||||
<strong>Controle-inspector</strong>
|
||||
<span>Geen selectie</span>
|
||||
</div>
|
||||
<div className="result-state result-state-empty">
|
||||
<strong>Geen bewijs geselecteerd</strong>
|
||||
<p>Scores, databronnen en kaartbewijs worden hier samen getoond zodra een controle beschikbaar is.</p>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{qualityChecks.length > 0 ? (
|
||||
<details className="quality-advanced-disclosure">
|
||||
<details className="quality-advanced-disclosure" open>
|
||||
<summary>
|
||||
<span>Details, kaartbewijs en historiek</span>
|
||||
<strong>{qualityChecks.length} bewaarde controles</strong>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user