HI-FI: Edit Mode Layout and Banner Styling#153
Conversation
Align the results header with the mock by using a compact app label plus Save/Export actions while preserving the existing sidebar toggle and pending-edit cancel behavior. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Refine the sidebar title section, edit action, and footer copy styling to better match the hifi mock while keeping the route list behavior unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
Use route palette colors for map pins and switch marker visuals from plain dots to pin-style markers so map markers align with route styling. Co-authored-by: Cursor <cursoragent@cursor.com>
Match the edit-mode layout with a wider results panel, save-edits CTA styling, and centered map status banner while keeping existing route behavior intact. Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
b5568dc to
c10b43a
Compare
kirillakovalenko
left a comment
There was a problem hiding this comment.
Code Review: PR #153 — HI-FI: Edit Mode Layout and Banner Styling
Author: Kesar Singh Sidhu | +302 / -184 across 5 files | State: Open
Overview
Converts the Results page edit-mode visuals from the old amber toggle/inset-shadow design to the hi-fi spec: teal "Save edits" pill, teal-bordered route cards, an edit-mode map banner, a wider sidebar (w-72 → w-[26rem]), and the shared edit-page nav rail. Also wires the Results nav button to activate when sessionStorage has optimize results, and upgrades map pins to route-colored SVG teardrops. UI-only — no API or persistence changes.
Correctness Issues
1. Map pin anchor offset is wrong (AdvancedMarkers path)
Map.tsx — createRoutePinElement:
wrapper.style.transform = "translate(-50%, -50%)";
The comment says the goal is to place the SVG tip on the stop. translate(-50%, -50%) centers the element horizontally and vertically over the coordinate — so the circle body sits on the stop, not the tip. The fallback (non-AdvancedMarker) path gets this right with anchor: new google.maps.Point(MARKER_ICON_WIDTH / 2, MARKER_ICON_HEIGHT). The Advanced Markers path should use translate(-50%, -100%) instead to land the tip at the coordinate.
2. "Save" button always rendered regardless of pendingPinMove
page.tsx — The old code showed both Cancel and Save only when pendingPinMove != null. Now Cancel is conditionally shown but Save is always rendered and always calls savePendingPinMove. When there's no pending move, clicking Save is a no-op at best or may surface an error. This appears to be an unintentional behavioral change rather than a design decision.
Code Quality
Good:
- hasOptimizeResults.ts is clean: SSR guard (
typeof window === "undefined"),try/catchonJSON.parse, and only checksArray.isArray && length > 0— exactly as much as needed. - Disabled nav item now correctly uses
<span aria-disabled="true">instead of<Link href="#" aria-disabled>— the old approach didn't actually prevent keyboard/screen-reader navigation. fill="currentColor"on the SVG replaces the hardcoded CSS-variable reference — better practice.aria-hiddenadded to SVG,aria-current="page"for the active Results item.- The
markerSvgDataUrlXSS concern is mitigated:fillColoralways comes fromrouteColorHex()(a predefined palette), which the comment calls out explicitly.
Concerns:
isSidebarOpenis hardcoded totrueand the toggle button is removed. If the hi-fi spec permanently removes sidebar toggling, the deadconst isSidebarOpen = trueand thetransition-[width]class on the container are unused complexity. Clean them up or document the intent.- The "Export" button in the navbar has no
onClick— it's a non-functional stub with no TODO comment or disabled state to signal that to reviewers. - Module-level mutable
let markerScaledSizein Map.tsx is a singleton that persists across hot-reloads in dev. Low risk, but worth knowing.
Design / Token Debt
As called out in the PR description, #7BCFC2 and #6CCBBE are hardcoded in three places (Sidebar, page.tsx, SidebarResultsButton). The PR acknowledges this; just confirm there's a tracked follow-up task for token consolidation before these values proliferate further.
Validation Gaps
The PR has several unchecked validation items:
npm run testandnpm run build— these should be green before merge.- No screenshots despite the PR checklist noting they're missing.
The risk is low (UI-only), but the test and build checks should not be skipped for a merge.
Summary
# | Severity | Issue -- | -- | -- 1 | Bug | AdvancedMarker pin anchor uses translate(-50%, -50%) — should be translate(-50%, -100%) to place tip at stop 2 | Bug | "Save" button always visible/clickable regardless of pendingPinMove state 3 | Minor | isSidebarOpen = true hardcoded with dead transition code; should be cleaned up or documented 4 | Minor | "Export" button is a non-functional stub with no affordance for that state 5 | Process | npm run test and npm run build not confirmed passingFix issues 1 and 2 before merging — everything else is polish or known tech debt.
Code Review: PR #153 — HI-FI: Edit Mode Layout and Banner Styling Author: Kesar Singh Sidhu | +302 / -184 across 5 files | State: OpenOverview
Converts the Results page edit-mode visuals from the old amber toggle/inset-shadow design to the hi-fi spec: teal "Save edits" pill, teal-bordered route cards, an edit-mode map banner, a wider sidebar (w-72 → w-[26rem]), and the shared edit-page nav rail. Also wires the Results nav button to activate when sessionStorage has optimize results, and upgrades map pins to route-colored SVG teardrops. UI-only — no API or persistence changes.
Correctness Issues
- Map pin anchor offset is wrong (AdvancedMarkers path)
Map.tsx — createRoutePinElement:
wrapper.style.transform = "translate(-50%, -50%)";
The comment says the goal is to place the SVG tip on the stop. translate(-50%, -50%) centers the element horizontally and vertically over the coordinate — so the circle body sits on the stop, not the tip. The fallback (non-AdvancedMarker) path gets this right with anchor: new google.maps.Point(MARKER_ICON_WIDTH / 2, MARKER_ICON_HEIGHT). The Advanced Markers path should use translate(-50%, -100%) instead to land the tip at the coordinate.
- "Save" button always rendered regardless of pendingPinMove
page.tsx — The old code showed both Cancel and Save only when pendingPinMove != null. Now Cancel is conditionally shown but Save is always rendered and always calls savePendingPinMove. When there's no pending move, clicking Save is a no-op at best or may surface an error. This appears to be an unintentional behavioral change rather than a design decision.
Code Quality
Good:
hasOptimizeResults.ts is clean: SSR guard (typeof window === "undefined"), try/catch on JSON.parse, and only checks Array.isArray && length > 0 — exactly as much as needed.
Disabled nav item now correctly uses instead of — the old approach didn't actually prevent keyboard/screen-reader navigation.
fill="currentColor" on the SVG replaces the hardcoded CSS-variable reference — better practice.
aria-hidden added to SVG, aria-current="page" for the active Results item.
The markerSvgDataUrl XSS concern is mitigated: fillColor always comes from routeColorHex() (a predefined palette), which the comment calls out explicitly.
Concerns:
isSidebarOpen is hardcoded to true and the toggle button is removed. If the hi-fi spec permanently removes sidebar toggling, the dead const isSidebarOpen = true and the transition-[width] class on the container are unused complexity. Clean them up or document the intent.
The "Export" button in the navbar has no onClick — it's a non-functional stub with no TODO comment or disabled state to signal that to reviewers.
Module-level mutable let markerScaledSize in Map.tsx is a singleton that persists across hot-reloads in dev. Low risk, but worth knowing.
Design / Token Debt
As called out in the PR description, #7BCFC2 and #6CCBBE are hardcoded in three places (Sidebar, page.tsx, SidebarResultsButton). The PR acknowledges this; just confirm there's a tracked follow-up task for token consolidation before these values proliferate further.
Validation Gaps
The PR has several unchecked validation items:
npm run test and npm run build — these should be green before merge.
No screenshots despite the PR checklist noting they're missing.
The risk is low (UI-only), but the test and build checks should not be skipped for a merge.
Summary
Severity Issue
1 Bug AdvancedMarker pin anchor uses translate(-50%, -50%) — should be translate(-50%, -100%) to place tip at stop
2 Bug "Save" button always visible/clickable regardless of pendingPinMove state
3 Minor isSidebarOpen = true hardcoded with dead transition code; should be cleaned up or documented
4 Minor "Export" button is a non-functional stub with no affordance for that state
5 Process npm run test and npm run build not confirmed passing
Fix issues 1 and 2 before merging — everything else is polish or known tech debt.
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Checked the latest commit (6088dfe) — the two bugs Kirill marked as must-fix are done:
Three items still need attention before this is mergeable: 1. Export button is a live no-op 2. Cancel and Save have identical styling 3. Also worth a follow-up (not a blocker): |
|
No new commits since Quick triage on severity:
If the build is green, this is good to go. Everything else can be a follow-up. |
Summary
upstream/mainand keeps shared Results infrastructure (directions polylines, distance updates, route-colored map pins, edit nav rail).Motivation
Changes
Frontend
app/ui/src/app/results/page.tsxisEditModeis true (teal pill, non-interactive overlay).w-72tow-[26rem]for card layout room.NAVBAR_V2_*) and left edit nav rail (EditSidebar,SidebarEditButton,SidebarResultsButton).edit.module.cssroot tokens on<main>for shared design variables.app/ui/src/app/results/components/Sidebar.tsx#7BCFC2when active).#6CCBBE), white background; view mode keeps zinc styling.border-l-4+routeColorHex;whitespace-nowrapon “Optimized Routes” title.app/ui/src/app/results/components/Map.tsxapp/ui/src/app/edit/components/layout/sidebar/SidebarResultsButton.tsx+app/ui/src/app/edit/utils/hasOptimizeResults.tsoptimizeResultsexists insessionStorage(post-rebase wiring).Validation
Frontend
npm --prefix app/ui run lintnpm --prefix app/ui run format:checknpm --prefix app/ui run typechecknpm --prefix app/ui run testnpm --prefix app/ui run buildnpm --prefix app/mobile run lintnpm --prefix app/mobile run typecheckBackend
cmake --preset dev.github/scripts/check-backend-static.sh build/devcmake --build --preset dev --parallelctest --preset dev --output-on-failure --no-tests=error -LE 'e2e|docker'docker compose -f deploy/compose/docker-compose.arm64.yml --env-file deploy/env/http-server.arm64.env configManual: on
/results, toggle Edit → confirm teal Save edits, map banner, wider sidebar, and teal-bordered route cards; toggle off → banner and edit styling clear.Risk
#7BCFC2,#6CCBBE) rather than CSS tokens; future token consolidation may need a small follow-up.Rollout and Recovery
High-Signal PR Checklist