Skip to content

feat: ER diagram with pure HTML canvas, orthogonal routing, schema selector, and drag/pan#119

Merged
Blankll merged 26 commits into
masterfrom
feat/er-diagram-entry-button
Jul 23, 2026
Merged

feat: ER diagram with pure HTML canvas, orthogonal routing, schema selector, and drag/pan#119
Blankll merged 26 commits into
masterfrom
feat/er-diagram-entry-button

Conversation

@Blankll

@Blankll Blankll commented Jul 22, 2026

Copy link
Copy Markdown
Member

Summary

Complete rewrite of the ER diagram view. SVG+foreignObject replaced with pure HTML canvas, bringing native scroll pan, smooth drag, and reliable rendering across all browsers. 25 commits, 7 new files, ~1200 lines of changes.

Major Features

Entry Point

  • ER diagram button moved from toolbar to database actions dropdown (... menu)
  • Opens ER diagram for entire database (all schemas), not just selected schema

Rendering Architecture

  • Pure HTML canvas: overflow:auto viewport with CSS transform: scale() zoom, no more <foreignObject> rendering issues
  • SVG overlay (pointer-events:none): relationship lines rendered independently from table cards
  • TableCard.vue: extracted presentational component with header-only drag (cursor:grab)
  • Canvas auto-sizing: dimensions computed from table bounding box

Routing & Layout

  • Orthogonal path routing: relationship lines route rightward between/around tables. Left-edge candidates removed to prevent dangling line segments
  • Layout: dagre TB (top-to-bottom) only — no LR toggle
  • Canvas auto-size: minimal 960×540, expands to fit all tables

Interactions

Action Behavior
Left-click blank area + drag Pan canvas (cursor:grabbing)
Right-click Browser context menu (restored)
Table header drag Move table position (persists, minimum 16px boundary)
Double-click table header Open table data tab
Click table Highlight selected + connected tables via color only — no tables hidden
Ctrl+wheel / trackpad pinch Zoom centered on mouse position
Plain wheel Native vertical scroll

Toolbar

  • Schema selector (PostgreSQL multi-schema support)
  • Table search/filter
  • Info badges: table count, relationship count
  • View mode: Table / Engineering → Table only (engineering removed)
  • Reset Layout button (restores dagre positions)
  • Fit to Screen
  • Refresh
  • Zoom in/out buttons + percentage

Column Display

  • PK columns: key icon (amber)
  • FK columns: link icon (blue)
  • No-icon columns: spacer keeps alignment
  • "Show All Columns (N)" / "Show Less" toggle
  • No emoji — all icons are inline SVGs

Module Architecture

src/components/er-diagram/
├── types.ts                 # Shared types + layout constants
├── graph-routing.ts         # Pure orthogonal path routing
├── graph-layout.ts          # Dagre layout + canvas sizing + fit-to-screen
├── TableCard.vue            # Table view card component
├── ErDiagramView.vue        # Orchestrator (toolbar, canvas, overlay)

All pure TS modules have Jest characterization tests:

  • graph-routing.test.tsrangesOverlap, routeSideX, candidateRouteXs, computeRelationshipPath, buildTableRectMap
  • graph-layout.test.tscomputeDagreLayout, computeCanvasSize, fitToScreen

Technical Decisions

  • Record over Map: positions use Record<string, Position> for simpler reactivity (spread merge)
  • Separation of concerns: dagrePositions (auto-layout) + manualOverrides (user drag) merged via computed
  • Drag direct update: manualOverrides updated on every mousemove, no delta-offset indirection
  • Watcher scoping: only expandedTables triggers layout recompute — search/focus changes do not reset positions

Removed

  • Engineering View (entity-relationship mode)
  • Layout direction toggle (always TB)
  • Right-click pan
  • Focus mode (tables never hidden on click)
  • ForeignObject rendering
  • Custom relationships panel (was never merged to main)

Blankll and others added 26 commits July 22, 2026 23:23
Add a visible ER diagram button next to the refresh button in the database selector toolbar. Previously users could only access the ER diagram via right-click context menu on a table in the schema tree.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Handle showErDiagram action in handleDatabaseAction to call tabStore.openErDiagramTab with the active connection, selected database, and schema.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Remove standalone toolbar button, add 'ER Diagram' item to the database actions dropdown menu instead. This keeps the toolbar clean and groups all database-level actions together.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
When opening ER diagram from database toolbar, omit the schema parameter so all tables across all schemas are displayed instead of only the currently selected schema.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
… replace emoji icons

- Zoom: use proportional scaling based on deltaY for better trackpad precision
- Toolbar: add zoom in (+) and zoom out (-) buttons with step factor 1.3x
- Schema: add schema selector dropdown before filter input, default 'All Schemas'
- Icons: replace 🔑🔗• emoji with clean inline SVG icons (key, link, circle)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Schema selector was not showing because available schemas may not be populated in the store yet. Add fallback to call databaseStore.fetchSchemas when cache is empty.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Replace empty string '' with '__all__' for the 'all schemas' option to avoid Radix Vue Select issues
- Reorder zoom controls to: zoom out → zoom in → percentage (matching user expectation)
- Add z-[100] to SelectContent to ensure dropdown renders above other elements
- Add schemaParam computed to map '__all__' → null for API calls

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Use invoke('list_schemas', ...) directly to avoid any Pinia store reactivity issues when the store hasn't cached schemas for the current database yet.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…eral

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…ssues

- Click: remove opacity dimming on non-selected tables, just highlight selected + connected table cards
- Drag: add mouse-drag to reposition table nodes on the canvas
- Expand button: add whitespace-nowrap and increase button height to prevent truncation
- Nullable indicator: remove confusing circle icon (NOT NULL is the default assumption)
- Edge dimming: remove opacity reduction on non-highlighted edges

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
… badges

- Orthogonal path routing: relationship lines now route around table cards with collision avoidance, replacing straight dagre edges

- Ctrl/Meta+Wheel zoom: zoom now requires ctrl/meta modifier, centered on mouse position. Plain wheel scrolls vertically

- Focus mode: clicking a table filters the view to only show the selected table and its directly related tables (via FK)

- Info badges: toolbar shows table count and relationship count badges

- Column marker alignment: non-PK/FK columns now get an empty spacer to keep all column text aligned

- Gesture support: added gesturestart/gesturechange handlers for trackpad pinch-to-zoom

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…verflow

- Drag: use dragDelta offset ref instead of updating nodePositions on every mousemove. Node positions and edge routes only update on drop. Eliminates shaking and position drift.

- SVG: add overflow=visible to prevent table clipping outside viewport during drag/pan

- Tooltips: add titles to tables badge, relationships badge, and layout direction button

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…uto-size, header drag

- Pure HTML rendering: replaced SVG+foreignObject with HTML div cards in an overflow:auto viewport with CSS scale zoom. SVG overlay used only for relationship lines (pointer-events:none)

- Header-only drag: drag now originates only from table header (cursor:grab). Uses delta-offset pattern, commits position on drop only

- Engineering mode: new entity-relationship view with rounded entities and column pills. Toggle via segmented control in toolbar

- Canvas auto-sizing: canvas dimensions computed from bounding box of all positioned tables. fitToScreen centers content

- Reset Layout: toolbar button restores dagre auto-layout positions

- View mode toggle: table view / engineering view switch preserving all interactions

- Native scroll pan: viewport uses overflow:auto, pan is native browser scroll. Ctrl+wheel zoom centered on mouse

- Extracted pure modules: types.ts, graph-routing.ts, graph-layout.ts with Jest TDD (32 new tests)

- TableCard.vue and EngineeringEntity.vue: presentational components with matching prop/emit interfaces

- All existing features preserved: schema selector, search, info badges, focus mode, layout direction, expand/collapse, orthogonal routing, large schema warning

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Add right-click drag panning: hold right button on blank canvas area and drag to scroll the viewport. Prevents browser context menu during drag.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Move right-drag event handling from document listeners to template handlers on the viewport and content divs, so mousedown/mousemove/mouseup are captured reliably. Also add @mousedown on inner content wrapper for events that don't bubble.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Left-click drag on blank canvas now pans the viewport (single finger on trackpad). Target detection via .er-table-wrapper class prevents interfering with table card clicks

- Right-click drag also pans (context menu suppressed)

- Remove Engineering view and view mode toggle — table view only

- Cursor changes to grab/grabbing during pan and table drag

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Left-click-only pan. Right-click now shows browser context menu again.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- LR layout: use clean center-to-center bezier curves instead of orthogonal routing (which looked wrong horizontally with dangling lines)

- Selection style: simplified to just  — subtle color change, no thick rings or shadows

- Drag smoothness: add  on dragged table wrapper for GPU acceleration

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
… direct drag

- Remove layout direction toggle — always top-to-bottom dagre layout

- Change positions from Map to Record<string,Position> — simpler reactivity, aligns with reference approach

- Simplify drag: update manualOverrides directly on mousemove (no dragDelta intermediate), add minimum boundary (16px)

- Simplify canvas sizing: direct max-extent calculation instead of bounding-box pipeline

- Remove computeBoundingBox, simplify computeCanvasSize signature

- Remove computeRelationshipPath direction param

- Update all tests for new signatures (443 tests pass)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
- Remove manualOverrides reset from computeLayout — dagre layout no longer clears user-dragged positions

- Move manualOverrides reset to resetLayout only (explicit button)

- Change watcher to only watch expandedTables, not displayedTables (search/focus changes no longer trigger layout recompute)

Fixes: drag position reverting on blank click, canvas shifting during drag

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Orthogonal routing produced dangling line segments when candidate routeX fell outside table boundaries. Bezier curves between table centers are simpler, always clean, and eliminate 'headless line' artifacts.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…ode hiding

- Orthogonal routing: remove left-edge candidate (minLeft - ROUTE_PADDING), always route rightward between or past tables. No more dangling leftward segments or lines through tables

- Focus mode removed: clicking a table only highlights (color/opacity), never hides unrelated tables. No more tables disappearing on click

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
@Blankll Blankll changed the title feat: add visible ER diagram entry button to database toolbar feat: ER diagram with pure HTML canvas, orthogonal routing, schema selector, and drag/pan Jul 23, 2026
@Blankll
Blankll merged commit 2f2491c into master Jul 23, 2026
3 checks passed
@Blankll
Blankll deleted the feat/er-diagram-entry-button branch July 23, 2026 06:40
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