AgentSkillsCN

canvas-edit

Live Annotation Feedback Toolbar,可直接在网页上叠加设计评审结果。对于存在问题的元素,工具会以数字标记显示问题编号、严重程度指示器、筛选功能,以及屏幕截图捕捉功能。与设计评审无缝对接,实现实时问题展示。触发条件包括:“显示注释”、“展示问题”、“为页面添加注释”、“叠加评审结果”,或在完成设计评审后自动触发。

SKILL.md
--- frontmatter
name: canvas-edit
description: Live Annotation Feedback Toolbar that overlays design review findings directly on web pages. Displays numbered badges on elements with issues, severity indicators, filtering, and screenshot capture. Integrates with design-review for real-time issue display. Triggers on "show annotations", "display issues", "annotate page", "overlay findings", or after running design-review.

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 FunctionalityNew Behavior
Text editing via textareaREMOVED
Style sliders (fontSize, etc.)REMOVED
"Save All to Code" buttonREPLACED with screenshot capture
contentEditable toggleREMOVED
edit commandREPLACED 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

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

Inject Annotations onto Page

bash
# 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

bash
# 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

code
┌─────────────────────────────────────┐
│ #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:

json
[
  {
    "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

FieldTypeDescription
idnumberUnique identifier
selectorstringCSS selector for target element
severitystring"blocking", "major", or "minor"
titlestringShort issue title

Optional Fields

FieldTypeDescription
descriptionstringDetailed explanation
pillarstringDesign pillar category
checkIdstringIdentifier for the check that found this
recommendationstringSuggested fix

Event API (Canvas Bus)

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

Events Emitted

EventPayloadWhen
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

EventAction
review.startedShow "Scanning..." state
review.issue_foundAdd badge for new issue
review.completedShow final count or success message
capture_mode.changedHide/show toolbar for agent-eyes

Integration Example

javascript
// 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:

code
.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

StateDisplayTrigger
Issues Found"N Issues" + severity badgesDefault when issues > 0
All Clear"✓ All looks good!" (randomized)Zero issues after review completes
Scanning"⟳ Analyzing..." with spinnerDuring review.started

Success messages rotate randomly:

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

Keyboard Navigation

KeyAction
TabNavigate toolbar controls
1-9Jump to badge by number
Arrow keysNavigate between visible badges
Enter/SpaceActivate focused button/badge
EscapeClose 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