| name | Implement Custom D3 Question |
| description | Create D3 questions with unique, non-standard interactions. Fallback skill for questions not fitting standard patterns. |
Implement Custom D3 Question
Use this skill when creating questions that don't fit standard patterns. For unique visualizations or complex custom interactions.
When to Use This Pattern
Use when:
- Question requires truly unique interactions
- None of the standard patterns fit
- Complex custom visualization needed
- Multiple interaction types combined in novel ways
Try standard patterns first:
- implement-increment-controls-question
- implement-table-question
- implement-drag-match-question
- implement-slider-question
- implement-multiple-choice-question
- implement-text-response-question
- implement-graph-question
Components Available
All components in .claude/skills/question-types/snippets/ can be mixed and matched:
cards/- Standard cards, video players, explanation cardsform-inputs.js- Buttons, inputs, textareastables.js- D3 tablesdrag-match.js- Drag-and-drop systemsvg-basics.js- SVG shapes and diagrams
Core Architecture Requirements
All D3 questions MUST implement these patterns:
1. State Management
function createDefaultState() {
return {
// All student response data
};
}
let chartState = createDefaultState();
2. Message Protocol
function sendChartState() {
sendMessage("response_updated", {
// Send complete state
});
}
// Call after EVERY state change
3. Interactivity Locking
let interactivityLocked = false;
function setInteractivity(enabled) {
interactivityLocked = !enabled;
// Update all interactive elements
}
4. State Restoration
function applyInitialState(payload) {
if (!payload) return;
// Restore state from payload
chartState = { ...createDefaultState(), ...payload };
}
5. Message Handlers
window.addEventListener("message", (event) => {
const { data } = event;
if (!data || typeof data !== "object") return;
if (data.type === "setInitialState") {
applyInitialState(data.payload);
renderFromState(d3);
}
if (data.type === "set_lock") {
setInteractivity(data.payload === false);
}
if (data.type === "check_answer") {
sendChartState();
}
});
Implementation Guide
See PATTERN.md for detailed custom implementation guide.
Reference Example
Study existing questions for patterns:
# Find all D3 questions
find courses/ -name "chart.js" -type f
# Look for unique patterns
grep -r "createChart" courses/ | head -5
Checklist
- Defined
createDefaultState() - Implemented
sendChartState()with complete payload - Called
sendChartState()after every state change - Implemented
setInteractivity(enabled) - Implemented
applyInitialState(payload) - Set up message event listeners
- Implemented
window.clearChart() - Implemented
window.getSvg()(if using SVG) - Tested state restoration
- Tested interactivity locking
- Verified message protocol
Tips
- Start simple - Build incrementally
- Borrow liberally - Copy patterns from existing questions
- Test frequently - Use chart.html for local testing
- Document state - Comment what each state field represents
- Inline components - All components must be inlined in chart.js
Related Skills
- create-d3-question - Parent workflow skill
- All other question-type skills for standard patterns
Additional Resources
- PATTERN.md - Custom visualization pattern guide
- ../snippets/ - All reusable components
- ../../implement-d3-conversion/ - Original conversion skill