Interactive Demo

Click any card to expand it and see detailed content. Click links to navigate between related cards. Cards with a grid icon have nested content - click "Explore nested content" to dive in. Use Ctrl+F to search. Pan and scroll to zoom.

Loading canvas...

Features

  • Pan & Zoom: Navigate large canvases with mouse drag and scroll wheel
  • Expand/Collapse Cards: Click cards to reveal detailed content with markdown support
  • Nested Hierarchies: Dive into cards that contain sub-canvases for unlimited depth
  • Connection Lines: Visual links between related cards with hover highlights
  • Fuzzy Search: Find cards by title, summary, or content across all levels
  • Breadcrumb Navigation: Track your path and navigate back through nested levels
  • Tooltips: Define terms that show explanations on hover
  • Responsive: Simplified mobile view with accordion-style cards
  • Accessible: Keyboard navigation, ARIA labels, screen reader support

Data Structure

The component accepts structured data defining the canvas and its cards:

const canvasData = {
  id: 'my-canvas',
  title: 'My Knowledge Base',
  defaultCardId: 'intro',  // Card to center on load
  config: {
    lineStyle: 'bezier',   // 'straight' | 'bezier' | 'orthogonal'
    background: { type: 'dots', color: '#00000010', gap: 24 },
    enableSearch: true,
    maxZoomOut: 0.1,
    maxZoomIn: 2
  },
  cards: [
    {
      id: 'intro',
      title: 'Introduction',
      summary: 'Brief overview shown when collapsed',
      position: { x: 0, y: 0 },
      content: [
        { type: 'markdown', content: '## Hello World\n...' },
        { type: 'image', src: '/diagram.png', alt: 'Diagram' }
      ],
      links: ['concept-a', 'concept-b'],  // IDs of related cards
      tooltips: [
        { term: 'example', definition: 'Shown on hover' }
      ],
      children: [  // Nested sub-canvas
        {
          id: 'detail-1',
          title: 'Detail 1',
          summary: '...',
          position: { x: 0, y: 0 },
          content: [{ type: 'markdown', content: '...' }]
        }
      ]
    }
  ]
};

Usage Examples

Direct Data

<script>
  import ExplainerCanvas from '$lib/components/ExplainerCanvas/ExplainerCanvas.svelte';
  import { myCanvasData } from './data';
</script>

<ExplainerCanvas data={myCanvasData} />

Load from JSON

<ExplainerCanvas src="/data/canvas.json" />

Custom Async Loader

<ExplainerCanvas
  loader={async () => {
    const res = await fetch('/api/canvas/123');
    return res.json();
  }}
/>

With Event Handlers

<ExplainerCanvas
  data={canvasData}
  onNavigate={(cardId, path) => console.log('Navigated:', cardId)}
  onExpand={(cardId) => trackAnalytics('card_expand', cardId)}
  onSearch={(query, results) => console.log('Search:', query)}
/>

Content Block Types

TypePropertiesDescription
markdowncontent: stringMarkdown text with syntax highlighting for code
imagesrc, alt?, caption?Responsive image with optional caption
embedurl, aspectRatio?iframe embed (videos, etc.)

Props

PropTypeDefaultDescription
dataExplainerCanvasDataβ€”Direct data object
srcstringβ€”URL to JSON file
loader() => Promiseβ€”Custom async loader function
initialCardIdstringβ€”Override defaultCardId from data
lineStyle'straight' | 'bezier' | 'orthogonal''bezier'Style of connection lines
classstringβ€”Additional CSS classes
onNavigate(cardId, path) => voidβ€”Called when navigating to a card
onExpand(cardId) => voidβ€”Called when a card is expanded
onCollapse(cardId) => voidβ€”Called when a card is collapsed
onSearch(query, results) => voidβ€”Called when search is performed

Keyboard Shortcuts

KeyAction
Ctrl/Cmd + FOpen search panel
EscapeClose expanded card or search
+ / -Zoom in / out
TabNavigate between cards
EnterExpand/collapse focused card

CSS Custom Properties

Customise the canvas appearance using CSS variables:

/* In your parent CSS */
.my-canvas {
  --ec-bg: #f9fafb;
  --ec-bg-card: #ffffff;
  --ec-border: #e0e0e0;
  --ec-text: #1a1a1a;
  --ec-text-muted: #666666;
  --ec-primary: #3b82f6;
  --ec-radius: 12px;
  --ec-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  --ec-line-color: #999999;
  --ec-line-opacity: 0.15;
  --ec-line-opacity-active: 1;
}

Dependencies

  • @panzoom/panzoom - Canvas pan and zoom
  • marked - Markdown rendering
  • highlight.js - Code syntax highlighting
  • fuse.js - Fuzzy search

Install with: bun add @panzoom/panzoom marked highlight.js fuse.js

Use Cases

  • Technical Documentation: Component architecture, API explanations
  • Business Process Mapping: Workflows, decision trees
  • Educational Content: Tutorials, course materials
  • Product Features: Feature explanations, onboarding flows
  • Knowledge Bases: Interconnected concepts, wikis