Canvas

Learn how the Panda IDX website canvas works. Explore layout and editing concepts to arrange page content and review the visitor experience.

Overview

The Canvas system (components/visuals) lets you create visual compositions with absolute positioning and smooth animations - think of it as Adobe After Effects for React, now with built-in SEO optimization.

Perfect for:

  • Product demos and mockups
  • Marketing page visuals
  • Interactive presentations
  • Feature showcases

Built on Framer Motion for performant animations, and uses semantic HTML5 (<figure>) for better accessibility and SEO.


Quick Start

1

Install & Import

2

Create Your First Canvas

<Canvas width={1200} height={800} background="ocean">
  <CanvasElement
    position={{ x: 100, y: 100 }}
    size={{ w: 400, h: 300 }}
  >
    <YourComponent />
  </CanvasElement>
</Canvas>
3

Add SEO (Optional - Marketing Pages Only)

<Canvas
  ariaLabel="Product dashboard showing key metrics"
  seoMetadata={{
    title: "Dashboard Interface",
    description: "Visual demonstration of...",
    features: ["Feature 1", "Feature 2"]
  }}
>
  {/* Your visual */}
</Canvas>

Components

Canvas

A fixed-size container for absolutely positioned elements. Always renders as <figure role="img"> for semantic HTML, accessibility, and SEO.

Core Props

PropTypeDefaultDescription
widthnumber800Canvas width in pixels
heightnumber600Canvas height in pixels
backgroundstring"ocean"Gradient variant or custom CSS
overflowstring"hidden""visible" or "hidden"
classNamestring""Additional CSS classes

SEO & Accessibility Props

PropTypeDefaultDescription
ariaLabelstring"Visual demonstration"Screen reader label
seoMetadataobjectnullSEO metadata (see below)

v2.0 Breaking Change: Canvas now always renders as <figure>. Props fallbackImage and role have been removed.

seoMetadata Structure

{
  title: string           // "Feature Name" (50-70 chars)
  description: string     // Detailed description (150-200 words)
  features: string[]      // Array of 5-10 features
}

Background Gradients

Built-in presets: ocean (default), sunset, dusk, forest, sunrise, midnight, lavender, tropical, autumn, aurora

Or custom CSS: background="linear-gradient(...)"


Usage Examples

Basic Usage

For internal dashboards or when SEO isn't needed:

<Canvas width={1200} height={800} background="ocean">
  <CanvasElement
    position={{ x: 100, y: 100 }}
    size={{ w: 400, h: 300 }}
  >
    <DashboardPreview />
  </CanvasElement>
</Canvas>

Renders as:

<figure role="img" aria-label="Visual demonstration">
  <div style="width: 1200px; height: 800px">
    <!-- Your content -->
  </div>
</figure>

SEO Best Practices

When to Add SEO

1

✅ Add seoMetadata to:

  • Landing pages (/real-estate-crm, /idx-website)
  • Product feature showcases
  • Marketing pages (unauthenticated)
  • Public demos
2

❌ Skip seoMetadata for:

  • Internal dashboards (behind login)
  • Admin panels
  • User-specific content
  • Development/staging environments

Writing Good ariaLabel

Describe what a user sees in the visual.

✅ Good Examples:

"CRM contact table with 247 leads and price filters"
"Deal pipeline showing 12 deals across 5 stages"
"Email inbox with client conversations and search"

❌ Bad Examples:

"Visual demonstration"  // Too generic
"Canvas component"       // Technical detail
"Screenshot"            // Not descriptive

Tip: Read your ariaLabel out loud. If someone could draw a rough sketch from it, it's good.

SEO Metadata Guidelines

Title (50-70 characters)

  • Include primary keyword ("Real Estate CRM")
  • Describe the specific feature shown
  • Will be rendered as <h3> in figcaption
title: "Real Estate CRM Contact Management Interface"
title: "Deal Pipeline with Drag-and-Drop"
title: "AI-Powered Email Inbox for Real Estate"

Description (150-200 words)

  • Expand on what's visible in the screenshot
  • Include secondary keywords naturally
  • Mention integrations and capabilities
  • Focus on benefits, not just features

Features (5-10 items)

  • Specific, measurable features
  • Include technical details ("100MB storage")
  • Mention integrations ("WhatsApp, Telegram")
  • Use action-oriented language

Only describe features visible in the visual. Don't mention AI if it's not shown.


Accessibility

How Screen Readers Announce

<Canvas ariaLabel="CRM dashboard with lead tracking">
  {/* content */}
</Canvas>

Screen reader: "Image: CRM dashboard with lead tracking"

Figcaption Behavior

When seoMetadata is provided:

  • <figcaption> has class="sr-only" (visually hidden)
  • aria-hidden="false" lets screen readers access it
  • Search engines crawl the full text

Best for: Marketing pages Skip for: Internal tools


Responsiveness

When to Use ResponsiveCanvas

Canvas uses fixed pixel dimensions by default. For responsive layouts (especially marketing pages), wrap Canvas in <ResponsiveCanvas>.

1

✅ Use ResponsiveCanvas for:

  • Marketing/landing pages - Needs to work on all screen sizes
  • Public-facing demos - Viewed on desktop, tablet, and mobile
  • Hero sections - Full-width responsive visuals
  • Feature showcases - Adapts to viewport width
2

❌ Use Canvas alone for:

  • Internal dashboards - Typically desktop-only
  • Fixed layouts - When you control the container size
  • Admin panels - Desktop-first applications
  • Embed contexts - When container size is known

How ResponsiveCanvas Works

Automatically scales the Canvas to fit the viewport while maintaining aspect ratio:

<ResponsiveCanvas
  canvasWidth={1450}   // Original design width
  canvasHeight={850}   // Original design height
  minHeight={400}      // Minimum height on small screens
>
  <Canvas width={1450} height={850} background="transparent">
    <CanvasElement position={{ x: 100, y: 100 }} size={{ w: 400, h: 300 }}>
      <YourVisual />
    </CanvasElement>
  </Canvas>
</ResponsiveCanvas>

What happens:

  • Desktop (1450px+): Shows at full size (scale: 1)
  • Tablet (768-1449px): Scales down proportionally
  • Mobile (under 768px): Scales to fit width, minimum 400px height

With Animations

ResponsiveCanvas supports Framer Motion animations:

<ResponsiveCanvas
  canvasWidth={1450}
  canvasHeight={850}
  initial={{ opacity: 0, y: 100 }}
  whileInView={{ opacity: 1, y: 0 }}
  viewport={{ once: true }}
  transition={{ duration: 0.5 }}
>
  <Canvas>{/* Your visual */}</Canvas>
</ResponsiveCanvas>

Tip: Use ResponsiveCanvas for scroll-triggered animations on landing pages. It handles both scaling AND animation.

ResponsiveCanvas Props

PropTypeDefaultDescription
canvasWidthnumber1450Original canvas width
canvasHeightnumber850Original canvas height
minHeightnumber400Minimum height on mobile
classNamestring""Additional CSS classes
childrenReactNode-Canvas component(s)

Plus all Framer Motion props: initial, animate, whileInView, transition, etc.


CanvasElement

Absolutely positioned element with animation support. Use inside Canvas to position content.

Key Props

Position & Size

PropTypeDefault
position{x, y}{x:0, y:0}
size{w, h}{w:100, h:100}
zoomnumber1
zIndexnumber0

Styling

PropTypeDefault
roundednumber0
opacitynumber1
borderWidthnumber0
borderColorstringrgba(...)

Shadow

shadow={{
  x: 0,
  y: 20,
  blur: 40,
  spread: 0,
  color: "rgba(0,0,0,0.2)"
}}

Or use presets: "sm", "md", "lg", "xl", "2xl", "3xl"

3D Perspective

perspective={{
  rotateX: 5,
  rotateY: -8,
  perspective: 1500
}}

Filters

PropTypeDescription
blurnumberBlur in pixels
brightnessnumberBrightness %

Animation Props

All Framer Motion props supported:

  • initial, animate, exit
  • transition
  • whileHover, whileTap, whileInView
  • viewport (for scroll animations)
  • drag, dragConstraints

Animation Presets

Pre-built animations for common patterns.

<CanvasElement {...AnimationPresets.fadeIn}>
  {/* Content */}
</CanvasElement>

Available Presets

Entrance: fadeIn, slideUp, slideDown, slideLeft, slideRight, scaleIn

Loop: float, rotate, pulse, breathe, swing

Hover: lift, grow, glow, tilt

Tap: press, bounce

Combined: fadeInAndFloat, slideInWithLift

Helpers

// Combine animations
const combined = combinePresets(
  AnimationPresets.fadeIn,
  AnimationPresets.lift
)

// Stagger children
const staggered = withStagger(AnimationPresets.slideUp, 0.1)

Complete Examples

Layered Composition

<Canvas background="sunrise" width={1400} height={900} overflow="visible">
  {/* Background layer */}
  <CanvasElement
    position={{ x: 50, y: 50 }}
    size={{ w: 800, h: 600 }}
    zIndex={1}
    shadow={{ y: 30, blur: 50 }}
    {...AnimationPresets.fadeIn}
  >
    <BackgroundVisual />
  </CanvasElement>

  {/* Foreground layer */}
  <CanvasElement
    position={{ x: 200, y: 150 }}
    size={{ w: 600, h: 400 }}
    zIndex={2}
    rounded={24}
    borderWidth={12}
    borderColor="rgba(255, 255, 255, 0.2)"
    shadow={{ y: 40, blur: 60 }}
    perspective={{ rotateX: 5, rotateY: -8, perspective: 1500 }}
    {...AnimationPresets.slideInWithLift}
  >
    <ForegroundVisual />
  </CanvasElement>
</Canvas>

Custom Animation

<CanvasElement
  position={{ x: 0, y: 0 }}
  size={{ w: 400, h: 300 }}
  initial={{ opacity: 0, scale: 0.5 }}
  animate={{ opacity: 1, scale: 1 }}
  transition={{ duration: 0.8, ease: "easeOut" }}
  whileHover={{ scale: 1.05, y: -10 }}
>
  <ProductCard />
</CanvasElement>

Best Practices

Performance

  • Use overflow="hidden" when possible for better rendering
  • Limit simultaneous animations on screen
  • Prefer transform animations (scale, rotate, translate) over layout changes

Positioning

  • Use absolute pixel values for precision
  • Calculate responsive positions based on viewport
  • Use zIndex for overlapping elements

Animations

  • Start with presets, customize as needed
  • Use whileInView for scroll-triggered animations
  • Combine with combinePresets() for complex effects

SEO & Accessibility

  • Always add descriptive ariaLabel (don't use default)
  • Add seoMetadata to marketing pages only
  • Write features as complete sentences
  • Include industry keywords naturally
  • Skip SEO on authenticated pages