Claude-skill-registry Implement Drag Match Question
Create D3 questions with drag-and-drop matching interactions. Students drag items (tables, graphs, equations) to categories.
install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/implement-drag-match-question" ~/.claude/skills/majiayu000-claude-skill-registry-implement-drag-match-question && rm -rf "$T"
manifest:
skills/data/implement-drag-match-question/SKILL.mdsource content
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
→ Fulldrag-match.js
system (sophisticated!)createDragMatcher()
→cards/standard-card.jscreateStandardCard()
Optional
→cards/explanation-card.js
- For student explanationscreateExplanationCard()
→cards/video-accordion.js
- For help videoscreateVideoAccordion()
→ If rendering tables inside draggable itemstables.js
Quick Start
- Review the pattern guide: PATTERN.md
- Study the working example:
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
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
function createDefaultState() { return { cat1Matches: [], // Array of matched item IDs cat2Matches: [], explanation: "" }; }
Core Pattern
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):
items: ITEMS.map(item => ({ id: item.id, content: item.text, // String instead of render function }))
3+ Categories
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)
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
with one array per categorycreateDefaultState() - Implemented
withcreateDragMatcher()
callbackonStateChange - Added explanation card (if needed)
- Implemented
to callsetInteractivity()dragMatcher.setLocked() - Implemented
to restore matchesapplyInitialState() - 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:
- Enable/disable draggingdragMatcher.setLocked(boolean)
- Get current match statedragMatcher.getState()
- Update matches programmaticallydragMatcher.setState(newState)
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