---
estimated_steps: 18
estimated_files: 3
skills_used: []
---

# T04: Build Export view UI with format selection, validation panel, and download wiring

This task builds the ExportView component — the final piece that wires everything together. The view receives canvas state from App.tsx (lifted in T02) and uses the export service (built in T03) to compose SVG, validate, call the engine API, and trigger downloads.

ExportView layout:
- Header with "Export" title and a "← Back to Design" button that navigates back to View 2
- Format selector: three cards/buttons for DXF, SVG, PNG with descriptions
- Unit selector (DXF/SVG only): inches or mm radio buttons, defaulting to the artboard's unit
- Validation panel: shows blocking errors (red, disables export) and warnings (yellow, allows export). Runs `validateForExport()` on mount and when objects change
- Canvas preview: a small thumbnail of the current design (use Konva `stage.toDataURL()` from the stageRef passed through App.tsx, captured before navigating to export view)
- Download button: disabled when blocking errors exist; triggers the appropriate export flow

Export flows by format:
- **DXF**: Call `composeCanvasSVG()` → call `exportAsDxf()` with units and scale_factor (1/96 for inches, 25.4/96 for mm) → `triggerDownload()` with the returned blob and filename `export.dxf`
- **SVG**: Call `composeCanvasSVG()` → create blob from SVG string → `triggerDownload()` with filename `export.svg`
- **PNG**: Use the preview data URL (captured from Konva stage before navigating) or re-render. Since stageRef may not be mounted in View 3, capture PNG data URL before transitioning to export view and pass it as a prop. Convert data URL to blob → `triggerDownload()` with filename `export.png`

PNG capture strategy: When user clicks 'Export' in View 2, capture `stageRef.current.toDataURL({ pixelRatio: 2 })` and store in App.tsx state, then navigate to export view. This avoids needing the Konva stage mounted in View 3.

App.tsx updates:
- Add `pngDataUrl` state, set it in the onExport handler before view transition
- Pass `pngDataUrl` to ExportView
- Wire ExportView's onBack to navigate back to canvas view

CSS: New `ExportView.module.css` with the view layout. Follow existing patterns from DesignCanvas.module.css and App.css.

## Inputs

- ``app/src/App.tsx` — updated in T02 with lifted canvas state and stageRef`
- ``app/src/utils/exportService.ts` — composeCanvasSVG(), validateForExport(), triggerDownload() from T03`
- ``app/src/api/engine.ts` — exportAsDxf() from T03`
- ``app/src/types/canvas.ts` — CanvasState, ArtboardConfig, CanvasObject types`
- ``app/src/utils/artboardShapes.ts` — fromPx() for unit display`
- ``app/src/views/DesignCanvas.module.css` — existing view CSS patterns to follow`

## Expected Output

- ``app/src/views/ExportView.tsx` — complete Export view with format selector, validation panel, unit selector, download button`
- ``app/src/views/ExportView.module.css` — view-specific styles`
- ``app/src/App.tsx` — wires ExportView with canvas state, pngDataUrl, and navigation callbacks`

## Verification

cd app && npx tsc -b --noEmit && npx vitest run
