Repository navigation
UI redesign v3 - #1
Merged
Merged
Conversation
The screenshots the brief was written from lived in /tmp and would have been lost; they are the only record of the before state, so they move into docs/shots/audit-2026-09-02 re-encoded to stay under the 300 kB per-file rule. Adds the progress ledger and blocker tracker §33 expects, and anchors the gitignore progress.md pattern so the ledger is not swept up with the operator's personal deployment log. Co-authored-by: Cursor <cursoragent@cursor.com>
Adds the layer everything else in the redesign sits on: Base UI as the headless primitive source, Inter and a subsetted Material Symbols Rounded as the two fonts, Material 3-derived tokens, an explicit `ui/kit`, and a Czech string table so panels stop hardcoding copy. The icon font is subsetted from a closed vocabulary (`ui/kit/icons.ts`) because the full variable font is 5 MB — too much for the mobile-data budget the map has to fit in. `?kit=1` renders a gallery of every primitive in both themes, which is how the token work gets reviewed without booting the whole shell. Co-authored-by: Cursor <cursoragent@cursor.com>
The chrome was a stack of separate bars: a mode bar the sidebar had to dodge, a strip of single-letter source badges, and an expandable task centre. This replaces it with the composition from §3 of the redesign plan — a full-height sidebar from the top edge, one floating pill centred over whatever map area is left, the Podklady/Vrstvy rail, and a single activity pill for everything that is loading. Because the pill's space is the strip between the panel and the rail rather than the window, narrow desktops now stand the rail up as a column and, when even that is not enough, hand the settings button over to it, instead of sliding the pill underneath the Vrstvy button. The mobile sheet gets the peek/half/full snaps from §21.2, the map's camera padding follows the chrome so a selected pin is never behind the sheet, and at the full snap the strip above the sheet is a hit area that snaps back to half rather than a scrim that dims the map it is meant to leave readable. Also adds `test:css-tokens`, which fails on a `var(--x)` nothing declares — the class of bug that rendered twenty corners square via an undefined `--radius-md`. Co-authored-by: Cursor <cursoragent@cursor.com>
…nd the pill A stop, a route profile and a share action each carried their own explanatory card, and the AI offer sat behind a two-step preview. Departure context, the detour finder and the three footer overlays now report where the user already looks — at the segments, under the itinerary, and in one tabbed dialog — while provider names, request parameters and per-message disclaimers move into InfoTips, popovers and `?debug=1`. The activity pill keeps cancel and retry now that the task centre is gone, and the accent colour in the legacy panel stylesheet reads from the token. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Phase 4 of the redesign. The place detail stops being a modal over the map: it docks in the left context with a photo hero (or none at all rather than an empty gradient), the five Google-Maps-style actions, and a summary that loads itself instead of hiding behind a tab. The selected pin keeps a pulsing ring and the map only pans when the panel would cover it. The footer surfaces follow §4.11: legends collapse to one compact row per layer with the rest behind a dialog, and the timeline is a single header with a context chip, a live toggle and playback — visible only while something on the map actually has a time. A question typed into search can now continue as a conversation in the new Asistent panel, which answers with place cards that fly the map and open the detail. Toasts moved to the bottom above the footer with an optional undo. Co-authored-by: Cursor <cursoragent@cursor.com>
The gateway could only answer "nearest bar" and ten of the eleven catalogued tools threw "not composed", so every other question the client offered came back 422. AI-1 turns that into one conversation: a tool-calling adapter with tool-as-schema output, fast/strong model slots resolved once in modelRuntime, and POST /v2/ai/chat streaming the steps it takes as it takes them. Tools now answer from the same sources the map draws from — place search is the fused POI source find_nearest_poi already used, so search and the assistant cannot disagree. Without a model the deterministic path answers the same question from the same tool rather than apologising. In the client the panel reads the stream, names the running tool instead of spinning, and renders places as cards with one action; nothing moves the map until that action is taken. briefService also asks with verifiedPublic, which is why place summaries were never generated. Co-authored-by: Cursor <cursoragent@cursor.com>
…t layers and plans AI-2 gathers a region's guide from parallel collectors behind per-source timeouts, so the panel always has something to show instead of an empty state when one source is slow. AI-3 lets the model hand back work the user can act on: an inline layer that can be saved into Moje vrstvy, and plan edits that arrive as a reviewable diff rather than a silent mutation. Playwright now waits on /health instead of a bound port. A listening socket only proved the API had reached listen(), and the first specs of a run were reaching Vite's proxy while routes were still registering, which failed eight tests a run for no reason of their own. Co-authored-by: Cursor <cursoragent@cursor.com>
… control overflowing its row The route-preference control had a fixed height while the planner lets its labels wrap, so four profiles in a 380 px panel grew the segments out of the track and over the row beneath — far enough to swallow clicks meant for the departure-context InfoTip. `min-height` lets the control be as tall as its own labels. Segment variants move onto the segment line as chips (§16.2). They had been a "Varianty (2)" toggle over a grid of cards, which charged two clicks and a block of vertical space at exactly the point where the user has already decided they want the other route. `set_layer_selection_draft` was reaching the browser and being dropped: the card type existed in the panel's union with no branch to render it, so "zapni mi vrstvy pro…" answered with nothing. It now lists the proposed layers by catalogue name behind one "Zapnout v mapě". Three specs were measuring the wrong thing rather than finding bugs: the alternatives test read the first LineString, which is a dimmed variant drawn under the route; the bike test read a storage key from before the overlay decision; and `openPanel` returned before the carried-over question was answered, so a later stream could be served to that first turn too. Co-authored-by: Cursor <cursoragent@cursor.com>
…at shout The §31.3 audit round over 40 captures (10 shell states, both viewports, both themes) started at 376 findings and ends at 0. Most of it was one mistake repeated: a small control is a comfortable mouse target at 32 px and an uncomfortable thumb one. `--control-h-sm` now reaches the tap target on a phone, while `--control-visual-sm` keeps the small icon button's state layer at 32 px — the box and the drawn circle stop being the same measurement, so a row of icons is still compact without being fiddly. The same gap turned up hardcoded in three more places: segmented buttons gave the indicator's 3 px inset away from the segment that gets tapped, the stop field was 40 px with a real border, and the mobile top bar's 44 px included the pill's border and left the search field at 40. Following §21.1 to the letter had also gone wrong: explanations moved behind an info icon, and then eight info icons stacked down the Layers drawer were the same wall of ink drawn a different way. In rows they now wait for hover or focus; touch keeps them, having no hover to reveal them with. And a flake that predates this branch, 1 in 4 on a clean tree: the activity pill unmounts the moment its row list empties, but a layer refresh retires its task before starting the next one — so the pill and any popover open on it vanished mid-refresh, out from under whoever was reaching for Zkusit znovu. It lingers 400 ms now, and a row is keyed by layer rather than by attempt. Six of the audit's own checks were measuring the wrong thing and account for 336 of those 376 findings — holding icons to text contrast, comparing rects across a scrollport, a 4 px grid where the tokens step in 2, separator rules counted as enclosures, a fold a screen below the viewport, and widgets counted where the guidance means things. Each correction states the standard it now holds to, in visual-audit.mjs. Co-authored-by: Cursor <cursoragent@cursor.com>
Wave A of §6.6, built global-first: the items that serve every user before the country-specific ones. Legends were 0 of 8 despite Phase 2 claiming otherwise — they reach the footer through the v2 manifest, and the six structural overlays register the v1 way, which had no way to carry one. The v1 adapter now passes a legend through. Terrain comes from its own global DEM rather than the active background, so it works over imagery too, unlike the extruded buildings it sits beside. OpenInfraMap ships no style, so the networks are drawn with ours — which is why its legend can state the voltage scale exactly. It needed a vector overlay helper that supports several drawing rules over one source; the single-fill helper is now expressed through it. Also fills the offline fixture gaps this exposed: four overlay tile hosts and the EOX imagery background had no fixture, which only showed up once a test switched them on. Co-authored-by: Cursor <cursoragent@cursor.com>
The picker already preferred a screenshot over its schematic fallback; the script that makes them and the assets themselves were missing, so every card fell back. All eight are shot over one shared viewport, because the question a picker answers is "which of these do I want" and that comparison is impossible if each card shows a different city. Only backgrounds whose licence permits redistribution are rendered — a thumbnail is a copy of the provider's cartography — and a render that carries no information is dropped rather than committed: NASA's daily mosaic stops at z8 and paints black at this zoom, and a black card reads as a bug where a schematic reads as a style. Co-authored-by: Cursor <cursoragent@cursor.com>
…-quests layer GPX joins the layer import. A track is the one shape the parser could not hold: candidates carried a single point and non-Point geometry was rejected outright, so a ride would have imported as one dot. GeoFeature now admits a LineString, a route pin keeps its line in user_pins.path (migration 0011), and lng/lat stay as the anchor so a track is still one findable place in every list. GPX is read without an XML parser, which also removes XXE and entity expansion as concerns. Dense tracks are simplified with Ramer-Douglas-Peucker, which keeps the corners that uniform sampling would round off, and the user is told when it happened. The clustered pin source cannot draw lines at all, so routes get their own. Quest anchors move behind a cache. All four adapters were called live on every viewport, making a map pan a burst of requests to volunteer-run services for data that does not move. Migration 0012 adds quest_anchors with a GiST index and a sweep log, because 'nothing here' is an answer worth remembering. Each source states its own refresh window, a regional viewport never sweeps, and a failed sweep is not recorded so an outage is not cached as emptiness. Quests are also a plain pins layer now, available outside the 3D game mode. Co-authored-by: Cursor <cursoragent@cursor.com>
Remove a duplicated blank line that failed format:check in CI. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01J3QFugXbaTxPuuP3q3rR16
10 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change
Describe the user-visible outcome and the current-to-target delta.
Evidence
Layer or provider integration (if applicable)
Release safety
If a box does not apply, say why instead of checking it silently.