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
Install & Import
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>
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
| Prop | Type | Default | Description |
|---|---|---|---|
width | number | 800 | Canvas width in pixels |
height | number | 600 | Canvas height in pixels |
background | string | "ocean" | Gradient variant or custom CSS |
overflow | string | "hidden" | "visible" or "hidden" |
className | string | "" | Additional CSS classes |
SEO & Accessibility Props
| Prop | Type | Default | Description |
|---|---|---|---|
ariaLabel | string | "Visual demonstration" | Screen reader label |
seoMetadata | object | null | SEO 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
✅ Add seoMetadata to:
- Landing pages (
/real-estate-crm,/idx-website) - Product feature showcases
- Marketing pages (unauthenticated)
- Public demos
❌ 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>hasclass="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>.
✅ 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
❌ 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
| Prop | Type | Default | Description |
|---|---|---|---|
canvasWidth | number | 1450 | Original canvas width |
canvasHeight | number | 850 | Original canvas height |
minHeight | number | 400 | Minimum height on mobile |
className | string | "" | Additional CSS classes |
children | ReactNode | - | 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
| Prop | Type | Default |
|---|---|---|
position | {x, y} | {x:0, y:0} |
size | {w, h} | {w:100, h:100} |
zoom | number | 1 |
zIndex | number | 0 |
Styling
| Prop | Type | Default |
|---|---|---|
rounded | number | 0 |
opacity | number | 1 |
borderWidth | number | 0 |
borderColor | string | rgba(...) |
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
| Prop | Type | Description |
|---|---|---|
blur | number | Blur in pixels |
brightness | number | Brightness % |
Animation Props
All Framer Motion props supported:
initial,animate,exittransitionwhileHover,whileTap,whileInViewviewport(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
transformanimations (scale, rotate, translate) over layout changes
Positioning
- Use absolute pixel values for precision
- Calculate responsive positions based on viewport
- Use
zIndexfor overlapping elements
Animations
- Start with presets, customize as needed
- Use
whileInViewfor scroll-triggered animations - Combine with
combinePresets()for complex effects
SEO & Accessibility
- Always add descriptive
ariaLabel(don't use default) - Add
seoMetadatato marketing pages only - Write features as complete sentences
- Include industry keywords naturally
- Skip SEO on authenticated pages
Related
- Components Overview - All available components
- Framer Motion - Animation library