Agent skill
Implement Drag Match Question
Create D3 questions with drag-and-drop matching interactions. Students drag items (tables, graphs, equations) to categories.
Stars
163
Forks
31
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/development/implement-drag-match-question
SKILL.md
Implement Drag Match Question
Use this skill when creating questions where students:
- Drag items to match them with categories or labels
- Categorize or sort visual elements
- Match representations (tables, graphs, equations)
When to Use This Pattern
Perfect for:
- "Match each table to the equation it represents"
- "Drag graphs to the descriptions that match"
- "Match scenarios to proportional relationships"
- Any "match X with Y" interaction
- Categorization tasks with 2+ categories
Not suitable for:
- Simple selection from options → use implement-multiple-choice-question
- Fill-in-the-blank tables → use implement-table-question
- Ordering/sequencing (use ordered list pattern instead)
Components Required
Copy these from .claude/skills/question-types/snippets/:
Required
drag-match.js→ FullcreateDragMatcher()system (sophisticated!)cards/standard-card.js→createStandardCard()
Optional
cards/explanation-card.js→createExplanationCard()- For student explanationscards/video-accordion.js→createVideoAccordion()- For help videostables.js→ If rendering tables inside draggable items
Quick Start
- Review the pattern guide: PATTERN.md
- Study the working example:
bash
cat courses/IM-8th-Grade/modules/Unit-3/assignments/510-Proportion-Equations/questions/06/attachments/chart.js
Key Implementation Decisions
- Define items - What can be dragged? (tables, graphs, equations, text)
- Define categories - Where can items be dropped? (2+ categories)
- Render function - How to display each item (table, graph, simple text)
- State structure - One array per category storing matched item IDs
Data Structure
javascript
const ITEMS = [
{ id: "item1", /* your item data */ },
{ id: "item2", /* your item data */ },
{ id: "item3", /* your item data */ },
];
const CATEGORIES = [
{ id: "cat1", text: "Category 1 description" },
{ id: "cat2", text: "Category 2 description" },
];
State Shape
javascript
function createDefaultState() {
return {
cat1Matches: [], // Array of matched item IDs
cat2Matches: [],
explanation: ""
};
}
Core Pattern
javascript
dragMatcher = createDragMatcher(d3, content, {
items: ITEMS.map(item => ({
id: item.id,
content: (container) => renderItem(container, item), // Custom render function
})),
categories: CATEGORIES.map(cat => ({
id: cat.id,
label: cat.text,
})),
state: {
cat1: chartState.cat1Matches,
cat2: chartState.cat2Matches,
},
onStateChange: (newState) => {
chartState.cat1Matches = newState.cat1 || [];
chartState.cat2Matches = newState.cat2 || [];
sendChartState();
},
locked: interactivityLocked,
});
Working Examples
In codebase:
- IM-8th-Grade Ramp-Up-01 Q03 - Match tables to movie download plans
In this skill:
Common Variations
Simple Text Items
For text-only items (not tables/graphs):
javascript
items: ITEMS.map(item => ({
id: item.id,
content: item.text, // String instead of render function
}))
3+ Categories
javascript
function createDefaultState() {
return {
cat1Matches: [],
cat2Matches: [],
cat3Matches: [],
explanation: ""
};
}
dragMatcher = createDragMatcher(d3, content, {
// ...
state: {
cat1: chartState.cat1Matches,
cat2: chartState.cat2Matches,
cat3: chartState.cat3Matches,
},
});
Custom Item Rendering (Tables, Graphs, Images)
javascript
function renderTableItem(container, tableData) {
// Use D3 to render a table
const table = container.append("table")
.style("width", "100%")
.style("border-collapse", "collapse");
// Add headers, rows, etc.
// See working example for full implementation
}
items: ITEMS.map(item => ({
id: item.id,
content: (container) => renderTableItem(container, item.data),
}))
Implementation Checklist
- Defined ITEMS array with unique IDs
- Defined CATEGORIES array
- Created render function for items (if complex)
- Created
createDefaultState()with one array per category - Implemented
createDragMatcher()withonStateChangecallback - Added explanation card (if needed)
- Implemented
setInteractivity()to calldragMatcher.setLocked() - Implemented
applyInitialState()to restore matches - Tested dragging items between categories
- Tested removing items from categories
- Tested locking/unlocking
- Verified state restoration
Tips
- Keep item rendering simple - Complex DOM structures can slow down dragging
- Use clear category labels - Students should know where to drag items
- Provide context - Use intro cards to explain the matching task
- Test on mobile - Drag-and-drop works on touch devices but test carefully
- Add visual feedback - The component provides this, but ensure it's visible
The createDragMatcher API
The createDragMatcher component is a complete drag-and-drop system. Key features:
- Automatic drag handling - No manual event listeners needed
- Touch support - Works on mobile devices
- Visual feedback - Highlights drop zones, shows drag state
- Remove buttons - Students can unmatch items
- Lock support - Disable dragging after submission via
.setLocked(true)
Important methods:
dragMatcher.setLocked(boolean)- Enable/disable draggingdragMatcher.getState()- Get current match statedragMatcher.setState(newState)- Update matches programmatically
Related Skills
- implement-multiple-choice-question - For simple selection
- implement-table-question - For table completion
- create-d3-question - Parent workflow skill
Additional Resources
- PATTERN.md - Detailed pattern guide
- snippets/drag-match.js - Component source code
Didn't find tool you were looking for?