Skip to content

v1.8.0: web canvas interface rebuild, dark theme, responsive layout, 45 UI fixes - #71

Merged
xmpuspus merged 1 commit into
mainfrom
feat/v180-ui-rebuild
Jul 31, 2026
Merged

v1.8.0: web canvas interface rebuild, dark theme, responsive layout, 45 UI fixes#71
xmpuspus merged 1 commit into
mainfrom
feat/v180-ui-rebuild

Conversation

@xmpuspus

Copy link
Copy Markdown
Owner

A UI audit of all 15 frontend components (4,965 lines) found 45 defects: 12 correctness, 11 accessibility, 6 responsive, 7 design-system, 9 content. This closes every one. No backend contract changes, so the CLI, the MCP server and every API route behave exactly as in 1.7.0.

The bug that costs money

streamSucceeded only became true after the SSE loop returned. An error event raised after the spec had already arrived left it false, so the non-streaming fallback fired a second design call, and that architecture replaced the first. The fallback now runs only when the stream produced no spec.

What changed

Design system. packages/web/frontend/src/styles.css holds every colour, space, radius, shadow and type step as a CSS custom property. [data-theme="dark"] re-points the same tokens. The theme follows prefers-color-scheme until the user picks a side, then keeps that choice in localStorage. Nothing downloads a web font, so the strict CSP the server sends stays intact.

Responsive. The frontend had zero media queries and a hard 420px sidebar. Breakpoints now sit at 1180px, 900px and 620px. Below 900px it is a two-pane Chat/Workspace switch. The nine tabs scroll instead of clipping. 100dvh keeps the composer above the iOS URL bar.

Accessibility. Real WAI-ARIA tabs (role="tablist", aria-selected, aria-controls, roving tabindex, Arrow/Home/End). One :focus-visible ring replaces four outline: none rules. Every text token clears 4.5:1; 29 sites failed WCAG 1.4.3 before. A live region announces progress. The closed node panel unmounts instead of parking inputs off-screen in the tab order. A native <dialog> replaces three window.confirm calls.

Other correctness fixes. Panel results survive a tab switch. The catalog drawer starts closed instead of covering the diagram on load. Four silent-failure paths raise a toast. The YAML tab asks the server for authoritative YAML (the client serialiser quoted nothing, so region: no read back as false). The streaming dot animates (its keyframe was never defined). Enter checks isComposing. fitView actually fires. The dead cloudwright_last_session write is gone.

Reach. OpenTofu, Pulumi TypeScript and Pulumi Python shipped in cloudwright.exporter.FORMATS with no button in the web UI. The Export tab now offers 13 formats in three groups. The 90-line duplicate of the send path in the Modify tab collapses into one runTurn.

Verification

Gate Result
pytest packages/core/tests 1392 passed, 22 skipped
pytest packages/web/tests 152 passed, 68 skipped
pytest packages/cli/tests 137 passed
pytest packages/mcp/tests 35 passed
ruff check + ruff format --check clean, 285 files
tsc --noEmit clean
check_version_sync.py 1.8.0 all 13 markers agree
Wheel contents unzip -l confirms both new hashed assets ship

What CI gates here is test_static_bundle.py: 8 checks that read the shipped cloudwright_web/static/ bundle, so a frontend change that is built but never copied fails the build. The 9 new tests in test_agent_browser.py sit behind skip_no_browser, which needs playwright and an LLM key, so CI skips them. Those behaviours were proven separately: 13/13 assertions passed against the mock-LLM server (tab pattern, arrow keys, theme toggle, theme persistence across reload, panel persistence, dialog cancel/confirm/escape, data-testid bubbles, Shift+Enter, Cmd+K, drawer closed on load, side panel out of the tab order).

Visual QA: 40 screenshots, every tab, light and dark, at 1440px and 390px, each read back. docs/screenshots/ and both web demo GIFs were re-recorded against the new interface with scripts/ui_screenshots.py --readme and the two Playwright recorders.

Reviewed by Xavier Puspus

…45 UI fixes

A UI audit of all 15 frontend components found 45 defects: 12 correctness,
11 accessibility, 6 responsive, 7 design-system, 9 content. This closes every one.
No backend contract changes.

Design system
- styles.css holds every colour, space, radius and type step as a CSS custom
  property; [data-theme="dark"] re-points the same tokens
- theme follows prefers-color-scheme until the user picks a side, then persists
- no downloaded font, so the server's strict CSP stays intact
- breakpoints at 1180/900/620px; below 900px a two-pane Chat/Workspace switch
- nine workspace tabs scroll instead of clipping; 100dvh keeps the composer above
  the iOS URL bar

Accessibility
- WAI-ARIA tabs: role=tablist/tab, aria-selected, aria-controls, roving tabindex,
  Arrow/Home/End keys, role=tabpanel sections
- one :focus-visible ring replaces four `outline: none` rules (WCAG 2.4.7)
- every text token clears 4.5:1; 29 sites failed WCAG 1.4.3 before
- live region announces design progress
- closed node panel unmounts instead of parking inputs off-screen in the tab order
- native <dialog> replaces three window.confirm calls
- Cmd/Ctrl+K focuses the composer, Cmd/Ctrl+1..9 picks a tab, Escape closes overlays

Correctness
- a mid-stream error no longer bills a second generation: streamSucceeded became
  true only after the loop returned, so an error event raised after the spec
  arrived ran the non-streaming fallback and overwrote the first architecture
- panel results survive a tab switch; panels mount on first use and stay mounted
- catalog drawer starts closed instead of covering the diagram on every load
- diagram export, module insert, standards check and download raise a toast
  instead of returning silently
- YAML tab asks the server for the authoritative YAML; the local fallback
  serialiser now quotes anything that would change type
- streaming indicator animates; the pulse keyframe was never defined
- Enter checks isComposing, so an input-method candidate does not submit
- fitView refits when the node set changes, and leaves a dragged layout alone
- dead cloudwright_last_session localStorage write removed
- legend moved off the React Flow zoom controls; diagram toolbar fits at 390px

Reach
- Export tab offers OpenTofu, Pulumi TypeScript and Pulumi Python; all three
  shipped in cloudwright.exporter.FORMATS with no button. 13 formats in 3 groups
- the 90-line duplicate of the send path in the Modify tab collapses into runTurn
- composer is a textarea with Shift+Enter, autogrow and a stop button

Tests and artifacts
- test_static_bundle.py: 8 checks read the shipped static bundle so a frontend
  change that never reaches the wheel fails CI
- browser tests drop two inline-style selectors for data-testid; 9 new tests
  cover the tab pattern, theme persistence and the dialog
- scripts/ui_screenshots.py shoots every tab at 3 widths in both themes
- docs/screenshots and both web demo GIFs re-recorded against the new UI

Co-Authored-By: Xavier Puspus
@xmpuspus
xmpuspus merged commit f30f5a9 into main Jul 31, 2026
6 checks passed
@xmpuspus
xmpuspus deleted the feat/v180-ui-rebuild branch July 31, 2026 22:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant