Skip to content

Add infinite canvas artwork explorer with pan/zoom and clusters#1

Open
loopstrangest wants to merge 1 commit into
andrewdoak:mainfrom
loopstrangest:infinite-artwork-canvas-explorer
Open

Add infinite canvas artwork explorer with pan/zoom and clusters#1
loopstrangest wants to merge 1 commit into
andrewdoak:mainfrom
loopstrangest:infinite-artwork-canvas-explorer

Conversation

@loopstrangest

Copy link
Copy Markdown

Ticket | Artifacts | Task

What problems was I solving

The existing Art Institute of Chicago browser displayed artworks as a flat, paginated list limited to 20 items on page 1. Users couldn't explore relationships between artworks or navigate the collection spatially. The experience felt like scrolling a database rather than wandering through a museum.

This PR transforms the app into an infinite canvas where users can:

  • Pan and zoom through a 2D space containing artwork thumbnails
  • See artworks grouped into meaningful clusters by classification, department, or style
  • Discover artworks by exploring spatial relationships rather than scrolling a list
  • Click any artwork to see details without leaving the exploration context

What user-facing changes did I ship

  • Infinite canvas with pan/zoom — Mouse wheel zooms, click-drag pans, control buttons (+/-/reset) in top-right
  • Artwork clusters — Artworks grouped by classification (default), department, or style with labeled headers showing counts
  • Lazy-loading — Clusters load their artwork thumbnails only when they enter the viewport
  • Detail panel — Clicking an artwork opens a slide-in panel with larger image, metadata, and link to artic.edu
  • Grouping selector — Dropdown to switch between classification/department/style groupings
  • Search-to-viewport — Searching animates the canvas to focus on matching clusters

How I implemented it

New Dependencies

  • react-zoom-pan-pinch — Lightweight pan/zoom library using CSS transforms

New Components

  • src/components/InfiniteCanvas.jsx — Wraps content in TransformWrapper/TransformComponent, exposes zoomToBounds() and resetView() methods via ref, tracks viewport bounds on transform changes
  • src/components/Cluster.jsx — Renders a cluster with label and artwork grid, handles artwork positioning within cluster bounds
  • src/components/DetailPanel.jsx — Slide-in panel with artwork metadata, closes on backdrop click or Escape key
  • src/components/GroupingSelector.jsx — Dropdown for switching grouping dimension

New API Functions

  • src/api/fetchAggregations.js — Fetches cluster counts using AIC API's Elasticsearch aggregations with .keyword suffix and limit=0
  • src/api/fetchClusterArtworks.js — Fetches artworks for a specific cluster using bool query filters

New Utilities

  • src/utils/clusterLayout.js — Grid layout calculator that positions clusters based on doc_count, calculates artwork positions within clusters

App.jsx Changes

  • Added state for clusterMeta, groupByField, viewport, loadedClusters, loadingClusters, artworkData, selectedArtwork
  • Replaced flat card grid with positioned Cluster components
  • Added viewport-intersection logic for lazy loading
  • Added search debounce (500ms) with viewport animation to matching clusters
  • Wired up detail panel open/close

Deviations from the plan

Implemented as planned

  • Phase 1: react-zoom-pan-pinch integration with controls
  • Phase 2: Aggregation API and cluster layout engine
  • Phase 3: Positioned clusters with lazy-loading
  • Phase 4: Detail panel with slide-in animation
  • Phase 5: Grouping selector and search-to-viewport

Deviations/surprises

  • None significant — implementation followed the structure outline closely

Additions not in plan

  • Loading and empty state indicators in clusters
  • Escape key handling for detail panel
  • ARIA attributes for accessibility on detail panel

Items planned but not implemented

  • Open questions deferred: minimap for orientation, pagination within large clusters

How to verify it

Manual Testing

  • Open http://127.0.0.1:5173/ in a browser
  • Mouse wheel zooms the canvas in/out
  • Click-drag pans the viewport
  • Zoom buttons (+/-/reset) work
  • Clusters appear with labels (e.g., "Painting", "Photograph")
  • Zooming/panning to a cluster loads its artwork thumbnails
  • Clicking an artwork opens the detail panel
  • Detail panel shows larger image, title, artist, date, medium
  • "View on Art Institute of Chicago" link opens artic.edu in new tab
  • Close button or clicking outside closes the panel
  • Grouping dropdown switches between Classification/Department/Style
  • Changing grouping reloads clusters with new structure
  • Searching (e.g., "Monet") animates viewport to matching clusters

Automated Tests

npm run build
npm run lint

Description for the changelog

Add infinite canvas artwork explorer with pan/zoom, clustered artwork display by classification/department/style, lazy-loading, detail panel, and search-to-viewport navigation.

…ail panel

- Install react-zoom-pan-pinch for pan/zoom functionality
- Add InfiniteCanvas component with zoom controls (+/-/reset)
- Add API functions for AIC aggregations and cluster artwork fetching
- Add cluster layout engine for positioning clusters on canvas
- Replace flat card grid with positioned clusters grouped by classification
- Implement lazy-loading of artwork images as clusters enter viewport
- Add slide-in detail panel for artwork metadata
- Add grouping selector dropdown (classification/department/style)
- Add search-to-viewport animation that zooms to matching clusters

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@netlify

netlify Bot commented Jun 4, 2026

Copy link
Copy Markdown

Deploy Preview for aic-api-react ready!

Name Link
🔨 Latest commit ba5ad1e
🔍 Latest deploy log https://app.netlify.com/projects/aic-api-react/deploys/6a21bb6997f18400084a71c0
😎 Deploy Preview https://deploy-preview-1--aic-api-react.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

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