返回 Skill 列表
extension
分类: 开发与工程无需 API Key

canvas-edit

实时注释反馈工具栏,可将设计审查结果直接覆盖在网页上。在有问题的元素上显示编号徽章、严重性指示器、过滤器和屏幕截图捕获功能。与设计审查集成以实现实时问题显示。在“显示注释”、“显示问题”、“标注页面”、“叠加发现结果”操作后触发,或在运行设计审查之后触发。

person作者: jakexiaohubgithub

Canvas Edit - Live Annotation Toolbar

Floating toolbar that overlays design review findings directly on web pages in real-time. Displays numbered badges on problematic elements with severity-colored borders, hover popovers for issue details, and one-click screenshot capture.

Key features:

  • Live annotations - Numbered badges appear on elements as issues are found
  • Severity indicators - Color-coded badges (red/orange/blue) with counts
  • Issue popovers - Click badges to see full issue details and recommendations
  • Screenshot capture - Capture annotated page (toolbar hidden, annotations visible)
  • Shadow DOM - Toolbar is invisible to agent-eyes screenshots
  • Filtering - Filter by severity or pillar category

Breaking Changes from v1

This is a complete redesign. Canvas-edit is now a viewing tool, not an editing tool.

| Old Functionality | New Behavior | |-------------------|--------------| | Text editing via textarea | REMOVED | | Style sliders (fontSize, etc.) | REMOVED | | "Save All to Code" button | REPLACED with screenshot capture | | contentEditable toggle | REMOVED | | edit command | REPLACED with inject command |

For live editing, use agent-canvas --with-edit instead.

Prerequisites

  • Python 3.10+
  • uv package manager
  • Playwright browsers: playwright install chromium

Commands

SKILL_DIR=".claude/skills/canvas-edit/scripts"

Inject Annotations onto Page

# Inject toolbar with issues from JSON file
uv run $SKILL_DIR/canvas_edit.py inject http://localhost:3000 --issues issues.json

# Inject with issues from stdin
echo '[{"id": 1, "selector": "h1", "severity": "major", "title": "Contrast issue"}]' | \
  uv run $SKILL_DIR/canvas_edit.py inject http://localhost:3000 --issues -

# Auto-screenshot on load
uv run $SKILL_DIR/canvas_edit.py inject http://localhost:3000 --issues issues.json --screenshot

Typical Workflow: Design Review + Annotations

# 1. Run design review to find issues
uv run .claude/skills/design-review/scripts/design_review.py review http://localhost:3000 \
  --output-json issues.json

# 2. Inject annotations onto the page
uv run $SKILL_DIR/canvas_edit.py inject http://localhost:3000 --issues issues.json

# 3. User interacts with annotations, takes screenshots, closes browser

Toolbar Controls

The floating toolbar (top-right by default) provides:

Status Display

  • Issue count ("5 Issues" or "All looks good!")
  • Severity badges: 🔴 blocking, 🟡 major, 🔵 minor

Actions

  • 👁 Visibility: Show/hide all annotations
  • ⚙ Filter: Filter by severity or pillar category
  • 📸 Screenshot: Capture page with annotations (toolbar hidden)
  • ↕/↔ Orientation: Toggle vertical/horizontal toolbar
  • ✕ Dismiss: Remove toolbar and all annotations

Dragging

  • Grab the ☰ handle to drag toolbar anywhere on screen
  • Position persists during session

Annotation Badges

Each issue appears as a numbered badge on its target element:

  • Position: Top-right of target element (auto-adjusts at screen edges)
  • Color: Border matches severity (red/orange/blue)
  • Click: Opens popover with full issue details
  • Hover: Highlights the target element

Badge Popover Contents

┌─────────────────────────────────────┐
│ #3  Contrast issue         [major] │
├─────────────────────────────────────┤
│ Color contrast ratio 3.2:1 fails   │
│ WCAG AA requirement of 4.5:1       │
│                                     │
│ Pillar: Quality Craft               │
│ Check: color-contrast               │
├─────────────────────────────────────┤
│ Recommendation:                     │
│ Change text color to #1a1a1a or    │
│ background to #ffffff              │
└─────────────────────────────────────┘

Issue JSON Format

Issues can come from design-review output or be manually constructed:

[
  {
    "id": 1,
    "selector": ".hero-title",
    "severity": "major",
    "title": "Contrast ratio insufficient",
    "description": "Text contrast 3.2:1 fails WCAG AA (4.5:1 required)",
    "pillar": "Quality Craft",
    "checkId": "color-contrast",
    "recommendation": "Use darker text (#1a1a1a) or lighter background"
  },
  {
    "id": 2,
    "selector": "button.submit",
    "severity": "minor",
    "title": "Touch target too small",
    "description": "Button is 36x28px, minimum is 44x44px",
    "pillar": "Quality Craft",
    "checkId": "touch-target-size"
  }
]

Required Fields

| Field | Type | Description | |-------|------|-------------| | id | number | Unique identifier | | selector | string | CSS selector for target element | | severity | string | "blocking", "major", or "minor" | | title | string | Short issue title |

Optional Fields

| Field | Type | Description | |-------|------|-------------| | description | string | Detailed explanation | | pillar | string | Design pillar category | | checkId | string | Identifier for the check that found this | | recommendation | string | Suggested fix |

Event API (Canvas Bus)

Canvas-edit integrates with other skills via the canvas bus event system.

Events Emitted

| Event | Payload | When | |-------|---------|------| | annotation.clicked | {issueId, selector, severity} | User clicks a badge | | screenshot.requested | {directory, filename, issueCount} | Screenshot button clicked | | screenshot.captured | {path, issueCount} | Screenshot saved (Python-side) | | annotations.cleared | {} | Dismiss button clicked | | filter.changed | {severity, pillars} | Filter settings changed |

Events Subscribed

| Event | Action | |-------|--------| | review.started | Show "Scanning..." state | | review.issue_found | Add badge for new issue | | review.completed | Show final count or success message | | capture_mode.changed | Hide/show toolbar for agent-eyes |

Integration Example

// In another skill's JavaScript
const bus = window.__canvasBus;

// Listen for annotation clicks
bus.subscribe('annotation.clicked', (payload) => {
  console.log(`Issue ${payload.issueId} clicked: ${payload.selector}`);
});

// Add an issue programmatically
window.__annotationLayer.addIssue({
  id: 99,
  selector: '.problematic-element',
  severity: 'major',
  title: 'New issue found'
});

Screenshot Output

Screenshots are saved to .canvas/screenshots/ with timestamp filenames:

.canvas/screenshots/
├── 2026-01-23T15-30-45_5-issues.png
└── 2026-01-23T15-45-12_0-issues.png

Filename format: YYYY-MM-DDTHH-MM-SS_N-issues.png

Screenshots capture:

  • Full page content
  • All visible annotation badges
  • Element highlights (if active)
  • NOT the toolbar (hidden during capture)

Toolbar States

| State | Display | Trigger | |-------|---------|---------| | Issues Found | "N Issues" + severity badges | Default when issues > 0 | | All Clear | "✓ All looks good!" (randomized) | Zero issues after review completes | | Scanning | "⟳ Analyzing..." with spinner | During review.started |

Success messages rotate randomly:

  • "All looks good!"
  • "Ship it!"
  • "Pixel perfect"
  • "Zero issues found"
  • "Looking sharp!"

Keyboard Navigation

| Key | Action | |-----|--------| | Tab | Navigate toolbar controls | | 1-9 | Jump to badge by number | | Arrow keys | Navigate between visible badges | | Enter/Space | Activate focused button/badge | | Escape | Close open popover |

Shadow DOM Isolation

The toolbar is rendered inside a closed Shadow DOM:

  • Invisible to document.querySelector()
  • Excluded from agent-eyes DOM snapshots
  • Hidden from screenshots (annotations remain visible)
  • Page styles cannot affect toolbar appearance

Notes

  • Toolbar auto-repositions to stay on screen when dragged or resized
  • Badges reposition when window resizes or scrolls
  • Multiple badges on the same element stack with offset
  • Orphaned badges (element removed) are automatically cleaned up
  • Filter state persists during session but resets on page reload