
Team Interactive Craft
- 14 installs
- 2.1k repo stars
- Updated June 18, 2026
- catlog22/claude-code-workflow
Support for team-interactive-craft
About
Provides workflow support for team-interactive-craft. Solo builders use this to streamline development.
- team-interactive-craft
Team Interactive Craft by the numbers
- 14 all-time installs (skills.sh)
- Ranked #2,126 of 3,282 Productivity & Planning skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/catlog22/claude-code-workflow --skill team-interactive-craftAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 14 |
|---|---|
| repo stars | ★ 2.1k |
| Last updated | June 18, 2026 |
| Repository | catlog22/claude-code-workflow ↗ |
What it does
Support for team-interactive-craft
Files
Team Interactive Craft
Systematic interactive component pipeline: research -> interaction design -> build -> a11y test. Built on team-worker agent architecture -- all worker roles share a single agent definition with role-specific Phase 2-4 loaded from roles/<role>/role.md.
Architecture
Skill(skill="team-interactive-craft", args="task description")
|
SKILL.md (this file) = Router
|
+--------------+--------------+
| |
no --role flag --role <name>
| |
Coordinator Worker
roles/coordinator/role.md roles/<name>/role.md
|
+-- analyze -> dispatch -> spawn workers -> STOP
|
+-------+-------+-------+-------+
v v v v
[team-worker agents, each loads roles/<role>/role.md]
researcher interaction-designer builder a11y-testerRole Registry
| Role | Path | Prefix | Inner Loop |
|---|---|---|---|
| coordinator | roles/coordinator/role.md | -- | -- |
| researcher | roles/researcher/role.md | RESEARCH-* | false |
| interaction-designer | roles/interaction-designer/role.md | INTERACT-* | false |
| builder | roles/builder/role.md | BUILD-* | true |
| a11y-tester | roles/a11y-tester/role.md | A11Y-* | false |
Role Router
Parse $ARGUMENTS:
- Has
--role <name>-> Readroles/<name>/role.md, execute Phase 2-4 - No
--role->@roles/coordinator/role.md, execute entry router
Shared Constants
- Session prefix:
IC - Session path:
.workflow/.team/IC-<slug>-<date>/ - CLI tools:
ccw cli --mode analysis(read-only),ccw cli --mode write(modifications) - Message bus:
mcp__ccw-tools__team_msg(session_id=<session-id>, ...) - Max GC rounds: 2
Worker Spawn Template
Coordinator spawns workers using this template:
Agent({
subagent_type: "team-worker",
description: "Spawn <role> worker for <task-id>",
team_name: "interactive-craft",
name: "<role>",
run_in_background: true,
prompt: `## Role Assignment
role: <role>
role_spec: <skill_root>/roles/<role>/role.md
session: <session-folder>
session_id: <session-id>
team_name: interactive-craft
requirement: <task-description>
inner_loop: <true|false>
## Progress Milestones
session_id: <session-id>
Report progress via team_msg at natural phase boundaries (context loaded -> core work done -> verification).
Report blockers immediately via team_msg type="blocker".
Report completion via team_msg type="task_complete" after final SendMessage.
Read role_spec file (@<skill_root>/roles/<role>/role.md) to load Phase 2-4 domain instructions.
Execute built-in Phase 1 (task discovery) -> role Phase 2-4 -> built-in Phase 5 (report).`
})User Commands
| Command | Action |
|---|---|
check / status | View execution status graph |
resume / continue | Advance to next step |
Specs Reference
- specs/pipelines.md -- Pipeline definitions and task registry
- specs/interaction-patterns.md -- Interaction pattern catalog
- specs/vanilla-constraints.md -- Zero-dependency rules
Session Directory
.workflow/.team/IC-<slug>-<date>/
+-- .msg/
| +-- messages.jsonl # Team message bus
| +-- meta.json # Pipeline config + GC state
+-- research/ # Researcher output
| +-- interaction-inventory.json
| +-- browser-api-audit.json
| +-- pattern-reference.json
+-- interaction/ # Interaction designer output
| +-- blueprints/
| +-- {component-name}.md
+-- build/ # Builder output
| +-- components/
| +-- {name}.js
| +-- {name}.css
+-- a11y/ # A11y tester output
| +-- a11y-audit-{NNN}.md
+-- wisdom/ # Cross-task knowledgeError Handling
| Scenario | Resolution |
|---|---|
| Unknown command | Error with available command list |
| Role not found | Error with role registry |
| Session corruption | Attempt recovery, fallback to manual |
| Fast-advance conflict | Coordinator reconciles on next callback |
| Completion action fails | Default to Keep Active |
| GC loop stuck > 2 rounds | Escalate to user: accept / retry / terminate |
Accessibility Tester
Test interactive components for keyboard navigation, screen reader compatibility, reduced motion fallback, focus management, and color contrast. Act as Critic in the builder<->a11y-tester Generator-Critic loop. Serve as quality gate before pipeline completion.
Phase 2: Context & Artifact Loading
| Input | Source | Required |
|---|---|---|
| Built components | <session>/build/components/.js, .css | Yes |
| Interaction blueprints | <session>/interaction/blueprints/*.md | Yes |
| Research artifacts | <session>/research/browser-api-audit.json | No |
| Previous audits | <session>/a11y/a11y-audit-*.md | Only for GC re-audit |
| .msg/meta.json | <session>/wisdom/.msg/meta.json | Yes |
1. Extract session path from task description 2. Read all built component files (JS + CSS) 3. Read interaction blueprints for expected behavior reference 4. If GC re-audit: read previous audit to track improvement/regression 5. Load audit history from meta.json for trend analysis
Phase 3: Audit Execution
Test 5 accessibility dimensions. For each, evaluate every built component:
Dimension 1: Keyboard Navigation (Weight: 25%)
| Check | Method | Pass Criteria |
|---|---|---|
| Tab order | Scan tabindex values, focusable elements | Logical tab order, no tabindex > 0 |
| Arrow key navigation | Check onKeyDown for ArrowLeft/Right/Up/Down | All navigable items reachable via arrows |
| Enter/Space activation | Check onKeyDown for Enter, Space | All interactive elements activatable |
| Escape dismissal | Check onKeyDown for Escape | Overlays/modals dismiss on Escape |
| Focus trap (overlays) | Check focus cycling logic | Tab stays within overlay when open |
| No keyboard trap | Verify all states have keyboard exit | Can always Tab/Escape out of component |
Score: count(pass) / count(total_checks) * 10
Dimension 2: Screen Reader Compatibility (Weight: 25%)
| Check | Method | Pass Criteria |
|---|---|---|
| ARIA role | Scan for role attribute | Appropriate role set (slider, dialog, tablist, etc.) |
| ARIA label | Scan for aria-label, aria-labelledby | All interactive elements have accessible name |
| ARIA states | Scan for aria-expanded, aria-selected, aria-hidden | Dynamic states update with interaction |
| Live regions | Scan for aria-live, aria-atomic | State changes announced (polite/assertive as needed) |
| Semantic HTML | Check element types | Uses button/a/input where appropriate, not div-only |
| Alt text | Check img/svg elements | Decorative: aria-hidden; informative: alt/aria-label |
Score: count(pass) / count(total_checks) * 10
Dimension 3: Reduced Motion (Weight: 20%)
| Check | Method | Pass Criteria |
|---|---|---|
| Media query present | Search CSS for prefers-reduced-motion | @media (prefers-reduced-motion: reduce) exists |
| Transitions disabled | Check reduced-motion block | transition-duration near 0 or removed |
| Animations disabled | Check reduced-motion block | animation-duration near 0 or removed |
| Content still accessible | Verify no content depends on animation | Information conveyed without motion |
| JS respects preference | Check matchMedia usage | JS checks prefers-reduced-motion before animating |
Score: count(pass) / count(total_checks) * 10
Dimension 4: Focus Management (Weight: 20%)
| Check | Method | Pass Criteria |
|---|---|---|
| Visible focus indicator | Search CSS for :focus-visible | Visible outline/ring on keyboard focus |
| Focus contrast | Check outline color against background | >= 3:1 contrast ratio |
| Focus on open | Check overlay/modal open logic | Focus moves to first interactive element |
| Focus on close | Check overlay/modal close logic | Focus returns to trigger element |
| No focus loss | Check state transitions | Focus never moves to non-interactive element |
| Skip link (page mode) | Check for skip navigation | Present if multiple interactive sections |
Score: count(pass) / count(total_checks) * 10
Dimension 5: Color Contrast (Weight: 10%)
| Check | Method | Pass Criteria |
|---|---|---|
| Text contrast | Evaluate CSS color vs background | >= 4.5:1 for normal text, >= 3:1 for large text |
| UI component contrast | Evaluate interactive element borders/fills | >= 3:1 against adjacent colors |
| Focus indicator contrast | Evaluate outline color | >= 3:1 against background |
| State indication | Check non-color state indicators | State not conveyed by color alone |
Score: count(pass) / count(total_checks) * 10
Overall Score Calculation
overallScore = round(keyboard*0.25 + screenReader*0.25 + reducedMotion*0.20 + focus*0.20 + contrast*0.10)
Issue Classification
| Severity | Definition | Examples |
|---|---|---|
| Critical | Component unusable for assistive tech users | No keyboard access, no ARIA role, focus trap |
| High | Significant barrier, workaround exists | Missing aria-label, no reduced motion, poor focus |
| Medium | Minor inconvenience | Suboptimal tab order, missing live region |
| Low | Enhancement opportunity | Could improve contrast, better semantic HTML |
Signal Determination
| Condition | Signal |
|---|---|
| 0 critical AND 0 high issues | a11y_passed (GC CONVERGED) |
| 0 critical AND high_count > 0 | a11y_result (GC REVISION NEEDED) |
| critical_count > 0 | fix_required (CRITICAL FIX NEEDED) |
Phase 4: Report & Output
1. Write audit report to <session>/a11y/a11y-audit-{NNN}.md:
# A11y Audit Report - {NNN}
## Summary
- **Overall Score**: X/10
- **Signal**: a11y_passed | a11y_result | fix_required
- **Critical**: N | **High**: N | **Medium**: N | **Low**: N
## Dimension Scores
| Dimension | Score | Weight | Weighted |
|-----------|-------|--------|----------|
| Keyboard Navigation | X/10 | 25% | X.XX |
| Screen Reader | X/10 | 25% | X.XX |
| Reduced Motion | X/10 | 20% | X.XX |
| Focus Management | X/10 | 20% | X.XX |
| Color Contrast | X/10 | 10% | X.XX |
## Issues
### Critical
- [C-001] {description} | File: {file}:{line} | Fix: {remediation}
### High
- [H-001] {description} | File: {file}:{line} | Fix: {remediation}
### Medium
- [M-001] {description} | File: {file}:{line} | Fix: {remediation}
## GC Loop Status
- **Signal**: {signal}
- **Action Required**: {none | builder fix | escalate}
## Trend (if previous audit exists)
- Previous score: X/10 -> Current: X/10 ({improving|stable|declining})
- Resolved issues: [list]
- New issues: [list]2. Update <session>/wisdom/.msg/meta.json under a11y-tester namespace:
- Read existing -> merge
{ "a11y-tester": { audit_id, score, critical_count, high_count, signal, timestamp } }-> write back
Interactive Component Builder
Implement vanilla JS + CSS interactive components from interaction blueprints. Zero dependencies, ES modules, progressive enhancement, GPU-only animations, touch-aware. Act as Generator in the builder<->a11y-tester Generator-Critic loop.
Phase 2: Context & Artifact Loading
| Input | Source | Required |
|---|---|---|
| Interaction blueprints | <session>/interaction/blueprints/*.md | Yes |
| Research artifacts | <session>/research/*.json | Yes |
| .msg/meta.json | <session>/wisdom/.msg/meta.json | Yes |
| A11y audit feedback | <session>/a11y/a11y-audit-*.md | Only for GC fix tasks |
1. Extract session path from task description 2. Read interaction blueprint for target component 3. Read research artifacts: browser-api-audit.json (API availability), pattern-reference.json (reference patterns) 4. Detect task type from subject: numbered -> New component, "fix" -> GC fix 5. If GC fix task: read latest a11y audit feedback
Phase 3: Implementation Execution
Component Implementation (BUILD-001, BUILD-002, etc.):
JavaScript (ES Module)
Implement component class in <session>/build/components/{name}.js:
// Structure template (adapt to component type)
export class ComponentName {
// --- Configuration ---
static defaults = { /* configurable params from blueprint */ };
// --- Lifecycle ---
constructor(element, options = {}) { /* merge options, query DOM, bind events */ }
init() { /* setup observers, initial state */ }
destroy() { /* cleanup: remove listeners, disconnect observers */ }
// --- State Machine ---
#state = 'idle';
#setState(next) { /* validate transition, update, trigger side effects */ }
// --- Event Handlers (from blueprint event flow map) ---
#onPointerDown(e) { /* setPointerCapture, transition state */ }
#onPointerMove(e) { /* lerp interpolation, update transform */ }
#onPointerUp(e) { /* releasePointerCapture, settle animation */ }
#onKeyDown(e) { /* keyboard mapping from blueprint */ }
// --- Animation ---
#lerp(current, target, speed) { return current + (target - current) * speed; }
#animate() { /* requestAnimationFrame loop, GPU-only transforms */ }
// --- Observers ---
#resizeObserver = null; // responsive behavior
#intersectionObserver = null; // scroll triggers
// --- Accessibility ---
#announceToScreenReader(message) { /* aria-live region update */ }
}
// Auto-init: progressive enhancement
document.querySelectorAll('[data-component-name]').forEach(el => {
new ComponentName(el);
});Requirements:
- Pure ES module with
export(no CommonJS, no bundler) - Class-based with private fields (#)
- Constructor accepts DOM element + options object
- State machine from blueprint with validated transitions
- Event handlers from blueprint event flow map
- Lerp interpolation for smooth drag/follow (speed from blueprint)
- requestAnimationFrame for frame-synced updates
- setPointerCapture for reliable drag tracking
- ResizeObserver for responsive layout adjustments
- IntersectionObserver for scroll-triggered behavior (when applicable)
- Proper cleanup in destroy() method
- Auto-init via data attribute for progressive enhancement
CSS (Custom Properties)
Implement styles in <session>/build/components/{name}.css:
/* Structure template */
/* --- Custom Properties (configurable) --- */
.component-name {
--component-duration: 400ms;
--component-easing: cubic-bezier(0.16, 1, 0.3, 1);
--component-color-primary: #1a1a2e;
/* ... from blueprint animation choreography */
}
/* --- Base Layout (works without JS) --- */
.component-name { /* progressive enhancement base */ }
/* --- States (from blueprint state machine) --- */
.component-name[data-state="idle"] { }
.component-name[data-state="hover"] { }
.component-name[data-state="active"] { }
.component-name[data-state="dragging"] { }
/* --- Animations (GPU-only: transform + opacity) --- */
.component-name__element {
transform: translateX(0);
opacity: 1;
transition: transform var(--component-duration) var(--component-easing),
opacity var(--component-duration) var(--component-easing);
will-change: transform, opacity;
}
/* --- Focus Styles --- */
.component-name:focus-visible {
outline: 2px solid var(--component-focus-color, #4a9eff);
outline-offset: 2px;
}
/* --- Reduced Motion --- */
@media (prefers-reduced-motion: reduce) {
.component-name,
.component-name * {
transition-duration: 0.01ms !important;
animation-duration: 0.01ms !important;
}
}
/* --- Responsive --- */
@media (max-width: 768px) { /* touch-optimized sizes */ }Requirements:
- CSS custom properties for all configurable values (no preprocessor)
- Base layout works without JavaScript (progressive enhancement)
- State-driven via data attributes (
data-state,data-active) - GPU-only animations: transform + opacity ONLY (no width/height/top/left)
will-changeon animated elementsprefers-reduced-motionmedia query with instant transitionsfocus-visiblefor keyboard-only focus ring- Responsive breakpoints for touch targets (min 44x44px)
- No inline styles from JS -- use CSS classes and custom properties
Native Platform APIs (prefer over custom implementations)
Dialog API (<dialog>):
- Use
<dialog>for modals — provides built-in focus trap and backdrop dialog.showModal()for modal (with backdrop, escape-to-close, focus trap)dialog.show()for non-modaldialog.close()to dismiss- Style
::backdroppseudo-element for overlay - Returns focus to trigger element on close
- Add
inertattribute to siblings when modal is open (prevents background interaction)
Popover API (native tooltips/dropdowns):
<div popover>for light-dismiss popovers (click-outside-to-close)<button popovertarget="id">for trigger- Auto-stacking (no z-index management needed)
- Built-in accessibility (focus management, escape-to-close)
- Use for: tooltips, dropdown menus, date pickers, color pickers
CSS Anchor Positioning (Chrome 125+, progressive enhancement):
anchor-name: --triggeron trigger elementposition-anchor: --triggeron positioned element@position-tryfor fallback positioning- Fallback:
position: fixedwith JS-calculated coordinates
GC Fix Mode (BUILD-fix-N):
- Parse a11y audit feedback for specific issues
- Re-read affected component files
- Apply targeted fixes: missing ARIA attributes, keyboard handlers, focus management, contrast adjustments
- Re-write affected files
- Signal
build_revisioninstead ofbuild_ready
Phase 4: Self-Validation & Output
1. Zero-dependency check:
| Check | Pass Criteria |
|---|---|
| No imports from npm | No import from node_modules paths |
| No require() | No CommonJS require statements |
| ES module exports | Uses export class or export function |
| No build tools needed | Runs directly in browser with <script type="module"> |
2. State machine completeness:
| Check | Pass Criteria |
|---|---|
| All states from blueprint | Every blueprint state has corresponding code path |
| All transitions | Every transition has handler code |
| Error recovery | All states can reach idle via reset |
3. Accessibility baseline:
| Check | Pass Criteria |
|---|---|
| Keyboard handlers | onKeyDown handles Enter, Space, Escape, Arrows |
| ARIA attributes | role, aria-label, aria-expanded (as needed) set |
| Focus management | tabindex, focus-visible styles present |
| Reduced motion | prefers-reduced-motion media query in CSS |
4. Performance baseline:
| Check | Pass Criteria |
|---|---|
| GPU-only transforms | No width/height/top/left in transitions |
| No forced reflow | No offsetWidth/getBoundingClientRect in animation loop |
| Cleanup | destroy() disconnects all observers and listeners |
5. Update <session>/wisdom/.msg/meta.json under builder namespace:
- Read existing -> merge
{ "builder": { task_type, component_name, file_count, output_dir, states_implemented, events_bound } }-> write back
Analyze Task
Parse user task -> detect interactive component scope -> identify browser APIs -> determine pipeline mode.
CONSTRAINT: Text-level analysis only. NO source code reading, NO codebase exploration.
Signal Detection
| Keywords | Capability | Pipeline Hint |
|---|---|---|
| split, compare, before/after, slider, divider | split-compare | single |
| gallery, carousel, scroll-snap, horizontal scroll | scroll-snap-gallery | gallery |
| lightbox, modal, overlay, fullscreen view | lightbox | single |
| scroll reveal, appear on scroll, fade in, stagger | scroll-reveal | single or gallery |
| glass, terminal, frosted, blur, backdrop | glass-terminal | single |
| lens, magnify, zoom, loupe | lens-effect | single |
| drag, resize, pointer, touch | pointer-interaction | single |
| page, landing, sections, multi-section | interactive-page | page |
| multiple components, collection, set | multi-component | gallery or page |
Scope Determination
| Signal | Pipeline Mode |
|---|---|
| Single component mentioned | single |
| Gallery or scroll-based multi-component | gallery |
| Full interactive page or multi-section | page |
| Unclear | ask user |
Complexity Scoring
| Factor | Points |
|---|---|
| Single component | +1 |
| Gallery / scroll collection | +2 |
| Full interactive page | +3 |
| Pointer/drag interactions | +1 |
| Scroll-based triggers (IntersectionObserver) | +1 |
| Touch gestures (pinch, swipe) | +1 |
| Overlay/modal with focus trap | +1 |
| Animation choreography (stagger, sequence) | +1 |
Results: 1-2 Low (single), 3-4 Medium (gallery), 5+ High (page)
Browser API Detection
| Keywords | Browser API |
|---|---|
| scroll, appear, visibility, threshold | IntersectionObserver |
| resize, container, responsive, layout | ResizeObserver |
| drag, pointer, mouse, click | Pointer Events |
| touch, swipe, pinch, gesture | Touch Events |
| scroll snap, snap point, mandatory | CSS scroll-snap |
| clip, mask, reveal, wipe | CSS clip-path |
| blur, frosted, glass | CSS backdrop-filter |
| animate, transition, keyframe | Web Animations API |
| focus, trap, tab, keyboard | Focus Management |
Output
Write scope context to coordinator memory:
{
"pipeline_mode": "<single|gallery|page>",
"scope": "<description>",
"interaction_type": "<pointer|scroll|overlay|mixed>",
"components": ["<detected-component-types>"],
"browser_apis": ["<detected-apis>"],
"complexity": { "score": 0, "level": "Low|Medium|High" }
}Command: Dispatch
Create the interactive craft task chain with correct dependencies and structured task descriptions. Supports single, gallery, and page pipeline modes.
Phase 2: Context Loading
| Input | Source | Required |
|---|---|---|
| User requirement | From coordinator Phase 1 | Yes |
| Session folder | From coordinator Phase 2 | Yes |
| Pipeline mode | From session meta.json pipeline | Yes |
| Interaction type | From session meta.json interaction_type | Yes |
1. Load user requirement and scope from session meta.json 2. Load pipeline stage definitions from specs/pipelines.md 3. Read pipeline and interaction_type from session meta.json
Phase 3: Task Chain Creation (Mode-Branched)
Task Description Template
Every task description uses structured format:
TaskCreate({
subject: "<TASK-ID>",
description: "PURPOSE: <what this task achieves> | Success: <measurable completion criteria>
TASK:
- <step 1: specific action>
- <step 2: specific action>
- <step 3: specific action>
CONTEXT:
- Session: <session-folder>
- Scope: <interaction-scope>
- Components: <component-list>
- Upstream artifacts: <artifact-1>, <artifact-2>
- Shared memory: <session>/wisdom/.msg/meta.json
EXPECTED: <deliverable path> + <quality criteria>
CONSTRAINTS: <scope limits, focus areas>"
})
TaskUpdate({ taskId: "<TASK-ID>", addBlockedBy: [<dependency-list>], owner: "<role>" })Mode Router
| Mode | Action |
|---|---|
single | Create 4 tasks: RESEARCH -> INTERACT -> BUILD -> A11Y |
gallery | Create 6 tasks: RESEARCH -> INTERACT-001 -> BUILD-001 -> INTERACT-002 -> BUILD-002 -> A11Y |
page | Create 4+ tasks: RESEARCH -> INTERACT -> [BUILD-001..N parallel] -> A11Y |
---
Single Pipeline Task Chain
RESEARCH-001 (researcher):
TaskCreate({
subject: "RESEARCH-001",
description: "PURPOSE: Analyze interaction patterns, browser API availability, and reference implementations | Success: 3 research artifacts with valid data
TASK:
- Catalog existing interactive components in project
- Audit browser API usage (IntersectionObserver, ResizeObserver, Pointer Events, Touch Events)
- Collect reference patterns for target component type
CONTEXT:
- Session: <session-folder>
- Scope: <interaction-scope>
- Components: <component-list>
- Shared memory: <session>/wisdom/.msg/meta.json
EXPECTED: <session>/research/*.json | All 3 research files with valid JSON
CONSTRAINTS: Read-only analysis | Focus on <interaction-scope>"
})
TaskUpdate({ taskId: "RESEARCH-001", owner: "researcher" })INTERACT-001 (interaction-designer):
TaskCreate({
subject: "INTERACT-001",
description: "PURPOSE: Design complete interaction blueprint with state machine and event flows | Success: Blueprint with all states, events, and keyboard mappings defined
TASK:
- Define state machine (idle -> hover -> active -> animating -> complete)
- Map event flows (pointer/touch/keyboard -> handlers -> state transitions)
- Specify gesture parameters (lerp speed, thresholds, easing)
- Design animation choreography (entry/exit/idle transitions)
- Create touch/keyboard/mouse mapping table
CONTEXT:
- Session: <session-folder>
- Scope: <interaction-scope>
- Upstream artifacts: research/*.json
- Shared memory: <session>/wisdom/.msg/meta.json
EXPECTED: <session>/interaction/blueprints/<component-name>.md | Complete state machine + event map + keyboard coverage
CONSTRAINTS: Vanilla JS only | GPU-only animations | Progressive enhancement"
})
TaskUpdate({ taskId: "INTERACT-001", addBlockedBy: ["RESEARCH-001"], owner: "interaction-designer" })BUILD-001 (builder):
TaskCreate({
subject: "BUILD-001",
description: "PURPOSE: Implement interactive component as vanilla JS + CSS | Success: Working ES module + CSS with all states, touch-aware, keyboard accessible
TASK:
- Implement ES module component class from interaction blueprint
- Write CSS with custom properties (no preprocessor)
- Add progressive enhancement (content works without JS)
- Use GPU-only animations (transform + opacity)
- Implement pointer events with touch fallback
- Add ResizeObserver for responsive behavior
- Add IntersectionObserver for scroll triggers (if applicable)
CONTEXT:
- Session: <session-folder>
- Scope: <interaction-scope>
- Upstream artifacts: interaction/blueprints/*.md, research/*.json
- Shared memory: <session>/wisdom/.msg/meta.json
EXPECTED: <session>/build/components/<name>.js + <name>.css | Zero dependencies, all states implemented
CONSTRAINTS: No npm packages | ES modules only | No inline styles | < 5ms per frame"
})
TaskUpdate({ taskId: "BUILD-001", addBlockedBy: ["INTERACT-001"], owner: "builder" })A11Y-001 (a11y-tester):
TaskCreate({
subject: "A11Y-001",
description: "PURPOSE: Audit accessibility of built component | Success: Audit report with pass/fail per check, 0 critical issues
TASK:
- Test keyboard navigation (tab order, arrow keys, escape, enter/space)
- Check screen reader compatibility (ARIA roles, states, live regions)
- Verify reduced motion fallback (prefers-reduced-motion)
- Test focus management (visible indicator, focus trap for overlays)
- Check color contrast (foreground/background ratio)
CONTEXT:
- Session: <session-folder>
- Scope: <interaction-scope>
- Upstream artifacts: build/components/*.js, build/components/*.css, interaction/blueprints/*.md
- Shared memory: <session>/wisdom/.msg/meta.json
EXPECTED: <session>/a11y/a11y-audit-001.md | Per-check pass/fail with remediation suggestions
CONSTRAINTS: Read-only analysis | GC convergence: 0 critical issues"
})
TaskUpdate({ taskId: "A11Y-001", addBlockedBy: ["BUILD-001"], owner: "a11y-tester" })---
Gallery Pipeline Task Chain
Create tasks in dependency order:
| Task | Role | blockedBy | Description |
|---|---|---|---|
| RESEARCH-001 | researcher | (none) | Interaction patterns + browser API audit |
| INTERACT-001 | interaction-designer | RESEARCH-001 | Base component interaction blueprint |
| BUILD-001 | builder | INTERACT-001 | Base component implementation |
| INTERACT-002 | interaction-designer | BUILD-001 | Gallery/scroll-snap interaction blueprint |
| BUILD-002 | builder | INTERACT-002 | Gallery container + navigation implementation |
| A11Y-001 | a11y-tester | BUILD-002 | Full gallery accessibility audit |
Task descriptions follow same template as single pipeline, with subject-specific content:
- INTERACT-002 focuses on scroll-snap container, navigation dots, active item detection
- BUILD-002 focuses on gallery container with CSS scroll-snap, IntersectionObserver for active item, navigation controls
---
Page Pipeline Task Chain
| Task | Role | blockedBy | Description |
|---|---|---|---|
| RESEARCH-001 | researcher | (none) | Interaction patterns for all page sections |
| INTERACT-001 | interaction-designer | RESEARCH-001 | Blueprints for all interactive sections |
| BUILD-001..N | builder | INTERACT-001 | One task per section (parallel fan-out) |
| A11Y-001 | a11y-tester | BUILD-001..N (all) | Full page accessibility audit |
Parallel fan-out: Create one BUILD task per distinct interactive section detected in the interaction blueprint. Each BUILD task is blocked only by INTERACT-001. A11Y-001 is blocked by ALL BUILD tasks.
Task descriptions for each BUILD-00N specify which section to implement, referencing the corresponding section in the interaction blueprint.
---
Phase 4: Validation
Verify task chain integrity:
| Check | Method | Expected |
|---|---|---|
| Task count correct | TaskList count | single: 4, gallery: 6, page: 3+N |
| Dependencies correct | Trace dependency graph | Acyclic, correct blockedBy |
| No circular dependencies | Trace dependency graph | Acyclic |
| Task IDs use correct prefixes | Pattern check | RESEARCH/INTERACT/BUILD/A11Y |
| Structured descriptions complete | Each has PURPOSE/TASK/CONTEXT/EXPECTED/CONSTRAINTS | All present |
If validation fails, fix the specific task and re-validate.
Monitor Pipeline
Event-driven pipeline coordination. Beat model: coordinator wake -> process -> spawn -> STOP.
Constants
- SPAWN_MODE: background
- ONE_STEP_PER_INVOCATION: true
- FAST_ADVANCE_AWARE: true
- WORKER_AGENT: team-worker
- MAX_GC_ROUNDS: 2
Handler Router
| Source | Handler |
|---|---|
| Message contains [researcher], [interaction-designer], [builder], [a11y-tester] | handleCallback |
| "capability_gap" | handleAdapt |
| "check" or "status" | handleCheck |
| "resume" or "continue" | handleResume |
| All tasks completed | handleComplete |
| Default | handleSpawnNext |
handleCallback
Worker completed. Process and advance.
1. Parse message to identify role and task ID:
| Message Pattern | Role |
|---|---|
[researcher] or RESEARCH-* | researcher |
[interaction-designer] or INTERACT-* | interaction-designer |
[builder] or BUILD-* | builder |
[a11y-tester] or A11Y-* | a11y-tester |
2. Mark task completed: TaskUpdate({ taskId: "<task-id>", status: "completed" }) 3. Record completion in session state
4. Check checkpoint for completed task:
| Completed Task | Checkpoint | Action |
|---|---|---|
| RESEARCH-001 | - | Notify user: research complete |
| INTERACT-001 | - | Proceed to BUILD-001 (single/gallery) or BUILD-001..N (page parallel) |
| INTERACT-002 | - | Proceed to BUILD-002 (gallery) |
| BUILD-001 | - | Check mode: single -> A11Y-001; gallery -> INTERACT-002; page -> check if all BUILD done |
| BUILD-001..N | - | Page mode: check if all BUILD tasks done -> A11Y-001 |
| BUILD-002 | - | Gallery: proceed to A11Y-001 |
| A11Y-001 | QUALITY: A11y Gate | Check a11y signal -> GC loop or complete |
5. A11y Gate handling (A11Y task completed): Read a11y signal from message: a11y_passed, a11y_result, or fix_required
| Signal | Condition | Action |
|---|---|---|
a11y_passed | 0 critical issues | GC converged -> record gate -> handleComplete |
a11y_result | Minor issues only | gc_rounds < max -> create BUILD-fix task |
fix_required | Critical issues found | gc_rounds < max -> create BUILD-fix task (CRITICAL) |
| Any | gc_rounds >= max | Escalate to user |
GC Fix Task Creation:
TaskCreate({ subject: "BUILD-fix-<round>",
description: "PURPOSE: Address a11y audit feedback | Success: All critical/high issues resolved
TASK:
- Parse a11y audit feedback for specific issues
- Apply targeted fixes to component JS/CSS
CONTEXT:
- Session: <session-folder>
- Upstream artifacts: a11y/a11y-audit-<NNN>.md" })
TaskUpdate({ taskId: "BUILD-fix-<round>", owner: "builder" })Then create new A11Y task blocked by fix. Increment gc_state.round.
GC Escalation Options (when max rounds exceeded): 1. Accept current implementation - skip remaining a11y fixes 2. Try one more round 3. Terminate
6. -> handleSpawnNext
handleCheck
Read-only status report, then STOP.
Worker Progress (from message bus):
Before generating status output, read worker milestones:
const progressMsgs = mcp__ccw-tools__team_msg({
operation: "list", session_id: sessionId, type: "progress", last: 50
})
const blockerMsgs = mcp__ccw-tools__team_msg({
operation: "list", session_id: sessionId, type: "blocker", last: 10
})
// Aggregate latest milestone per task
const taskProgress = {}
for (const msg of (progressMsgs.result?.messages || [])) {
const tid = msg.data?.task_id
if (tid && (!taskProgress[tid] || msg.ts > taskProgress[tid].ts)) {
taskProgress[tid] = { phase: msg.data.phase, pct: msg.data.progress_pct, ts: msg.ts }
}
}Include in status output:
- Per-worker latest milestone (phase + progress_pct) next to task status
- Active blockers section (if any blockerMsgs found)
Pipeline Status (<pipeline-mode>):
[DONE] RESEARCH-001 (researcher) -> research/*.json
[DONE] INTERACT-001 (interaction-designer) -> blueprints/*.md
[RUN] BUILD-001 (builder) -> building component...
[WAIT] A11Y-001 (a11y-tester) -> blocked by BUILD-001
GC Rounds: 0/2
Session: <session-id>
Commands: 'resume' to advance | 'check' to refreshOutput status -- do NOT advance pipeline.
handleResume
1. Audit task list for inconsistencies:
- Tasks stuck in "in_progress" -> reset to "pending"
- Tasks with completed blockers but still "pending" -> include in spawn list
2. -> handleSpawnNext
handleSpawnNext
Find ready tasks, spawn workers, STOP.
1. Collect: completedSubjects, inProgressSubjects, readySubjects (pending + all blockedBy completed) 2. No ready + work in progress -> report waiting, STOP 3. No ready + nothing in progress -> handleComplete 4. Has ready -> for each: a. Check inner loop role with active worker -> skip (worker picks up) b. TaskUpdate -> in_progress c. team_msg log -> task_unblocked d. Spawn team-worker:
Agent({
subagent_type: "team-worker",
description: "Spawn <role> worker for <task-id>",
team_name: "interactive-craft",
name: "<role>",
run_in_background: true,
prompt: `## Role Assignment
role: <role>
role_spec: <project>/.claude/skills/team-interactive-craft/roles/<role>/role.md
session: <session-folder>
session_id: <session-id>
team_name: interactive-craft
requirement: <task-description>
inner_loop: <true|false>
## Progress Milestones
session_id: <session-id>
Report progress via team_msg at natural phase boundaries (context loaded -> core work done -> verification).
Report blockers immediately via team_msg type="blocker".
Report completion via team_msg type="task_complete" after final SendMessage.
Read role_spec file to load Phase 2-4 domain instructions.
Execute built-in Phase 1 (task discovery) -> role Phase 2-4 -> built-in Phase 5 (report).`
})Parallel spawn rules by mode:
| Mode | Scenario | Spawn Behavior |
|---|---|---|
| single | Sequential | One task at a time |
| gallery | Sequential | One task at a time |
| page | After INTERACT-001 | Spawn BUILD-001..N in parallel (CP-3 fan-out) |
| page | After all BUILD done | Spawn A11Y-001 |
5. Add to active_workers, update session, output summary, STOP
handleComplete
Pipeline done. Generate report and completion action.
Completion check by mode:
| Mode | Completion Condition |
|---|---|
| single | All 4 tasks (+ fix tasks) completed |
| gallery | All 6 tasks (+ fix tasks) completed |
| page | All 3+N tasks (+ fix tasks) completed |
1. If any tasks not completed -> handleSpawnNext 2. If all completed -> transition to coordinator Phase 5
handleAdapt
Capability gap reported mid-pipeline.
1. Parse gap description 2. Check if existing role covers it -> redirect 3. Role count < 5 -> generate dynamic role spec 4. Create new task, spawn worker 5. Role count >= 5 -> merge or pause
Fast-Advance Reconciliation
On every coordinator wake: 1. Read team_msg entries with type="fast_advance" 2. Sync active_workers with spawned successors 3. No duplicate spawns
Coordinator Role
Interactive Craft Team coordinator. Orchestrate pipeline: analyze -> dispatch -> spawn -> monitor -> report. Manages task chains for interactive component creation, GC loops between builder and a11y-tester, parallel fan-out for page mode.
Identity
- Name: coordinator | Tag: [coordinator]
- Responsibility: Analyze task -> Create team -> Dispatch tasks -> Monitor progress -> Report results
Boundaries
MUST
- All output (SendMessage, team_msg, logs) must carry
[coordinator]identifier - Use
team-workeragent type for all worker spawns (NOTgeneral-purpose) - Dispatch tasks with proper dependency chains and blockedBy
- Monitor worker progress via message bus and route messages
- Handle Generator-Critic loops with max 2 iterations
- Maintain session state persistence
MUST NOT
- Implement domain logic (researching, designing, building, testing) -- workers handle this
- Spawn workers without creating tasks first
- Skip sync points when configured
- Force-advance pipeline past failed a11y audit
- Modify source code or component artifacts directly -- delegate to workers
- Omit
[coordinator]identifier in any output
Command Execution Protocol
When coordinator needs to execute a command (analyze, dispatch, monitor):
1. Read commands/<command>.md 2. Follow the workflow defined in the command 3. Commands are inline execution guides, NOT separate agents 4. Execute synchronously, complete before proceeding
Entry Router
| Detection | Condition | Handler |
|---|---|---|
| Worker callback | Message contains [researcher], [interaction-designer], [builder], [a11y-tester] | -> handleCallback (monitor.md) |
| Status check | Args contain "check" or "status" | -> handleCheck (monitor.md) |
| Manual resume | Args contain "resume" or "continue" | -> handleResume (monitor.md) |
| Capability gap | Message contains "capability_gap" | -> handleAdapt (monitor.md) |
| Pipeline complete | All tasks have status "completed" | -> handleComplete (monitor.md) |
| Interrupted session | Active/paused session exists in .workflow/.team/IC-* | -> Phase 0 |
| New session | None of above | -> Phase 1 |
For callback/check/resume/adapt/complete: load @commands/monitor.md, execute matched handler, STOP.
Phase 0: Session Resume Check
1. Scan .workflow/.team/IC-*/.msg/meta.json for active/paused sessions 2. No sessions -> Phase 1 3. Single session -> reconcile (audit TaskList, reset in_progress->pending, rebuild team, kick first ready task) 4. Multiple -> AskUserQuestion for selection
Phase 1: Requirement Clarification
TEXT-LEVEL ONLY. No source code reading.
1. Parse task description from arguments 2. Detect interactive scope:
| Signal | Pipeline Mode |
|---|---|
| Single component (split compare, lightbox, lens, scroll reveal, glass terminal) | single |
| Gallery, carousel, scroll-snap collection, multi-component scroll | gallery |
| Full interactive page, landing page, multi-section interactive | page |
| Unclear | ask user |
3. Ask for missing parameters if scope unclear:
AskUserQuestion({
questions: [
{ question: "Interactive component scope?", header: "Scope", options: [
{ label: "Single component", description: "One interactive element (split compare, lightbox, etc.)" },
{ label: "Gallery / Scroll collection", description: "Scroll-snap gallery or multi-component scroll" },
{ label: "Full interactive page", description: "Complete page with multiple interactive sections" }
]},
{ question: "Primary interaction type?", header: "Interaction", options: [
{ label: "Pointer/drag", description: "Drag, resize, slider interactions" },
{ label: "Scroll-based", description: "Scroll snap, scroll reveal, parallax" },
{ label: "Overlay/modal", description: "Lightbox, lens, tooltip overlays" },
{ label: "Mixed" }
]}
]
})4. Delegate to @commands/analyze.md -> output scope context 5. Record: pipeline_mode, interaction_type, complexity
Phase 2: Create Team + Initialize Session
1. Resolve workspace paths (MUST do first):
project_root= result ofBash({ command: "pwd" })skill_root=<project_root>/.claude/skills/team-interactive-craft
2. Generate session ID: IC-<slug>-<YYYY-MM-DD> 3. Create session folder structure:
.workflow/.team/IC-<slug>-<date>/research/
.workflow/.team/IC-<slug>-<date>/interaction/blueprints/
.workflow/.team/IC-<slug>-<date>/build/components/
.workflow/.team/IC-<slug>-<date>/a11y/
.workflow/.team/IC-<slug>-<date>/wisdom/
.workflow/.team/IC-<slug>-<date>/.msg/4. Initialize .msg/meta.json via team_msg state_update with pipeline metadata 5. TeamCreate(team_name="interactive-craft") 6. Do NOT spawn workers yet - deferred to Phase 4
Phase 3: Create Task Chain
Delegate to @commands/dispatch.md. Task chains by mode:
| Mode | Task Chain |
|---|---|
| single | RESEARCH-001 -> INTERACT-001 -> BUILD-001 -> A11Y-001 |
| gallery | RESEARCH-001 -> INTERACT-001 -> BUILD-001 -> INTERACT-002 -> BUILD-002 -> A11Y-001 |
| page | RESEARCH-001 -> INTERACT-001 -> [BUILD-001..N parallel] -> A11Y-001 |
Phase 4: Spawn-and-Stop
Delegate to @commands/monitor.md#handleSpawnNext: 1. Find ready tasks (pending + blockedBy resolved) 2. Spawn team-worker agents (see SKILL.md Spawn Template) 3. Output status summary 4. STOP
Phase 5: Report + Completion Action
1. Read session state -> collect all results 2. List deliverables:
| Deliverable | Path |
|---|---|
| Interaction Inventory | <session>/research/interaction-inventory.json |
| Browser API Audit | <session>/research/browser-api-audit.json |
| Pattern Reference | <session>/research/pattern-reference.json |
| Interaction Blueprints | <session>/interaction/blueprints/*.md |
| Component JS Files | <session>/build/components/*.js |
| Component CSS Files | <session>/build/components/*.css |
| A11y Audit Reports | <session>/a11y/a11y-audit-*.md |
3. Calculate: completed_tasks, gc_rounds, a11y_score, components_built 4. Output pipeline summary with [coordinator] prefix 5. Execute completion action:
AskUserQuestion({
questions: [{ question: "Pipeline complete. What next?", header: "Completion", options: [
{ label: "Archive & Clean", description: "Archive session and clean up team resources" },
{ label: "Keep Active", description: "Keep session for follow-up work" },
{ label: "Export Results", description: "Export deliverables to specified location" }
]}]
})Error Handling
| Error | Resolution |
|---|---|
| Task timeout | Log, mark failed, ask user to retry or skip |
| Worker crash | Reset task to pending, respawn worker |
| Dependency cycle | Detect, report to user, halt |
| Invalid scope | Reject with error, ask to clarify |
| Session corruption | Attempt recovery, fallback to manual reconciliation |
| GC loop stuck > 2 rounds | Escalate to user: accept / try one more / terminate |
Interaction Blueprint Designer
Design complete interaction blueprints: state machines, event flows, gesture specifications, animation choreography, and input mapping tables. Consume research artifacts to produce blueprints for the builder role.
Phase 2: Context & Artifact Loading
| Input | Source | Required |
|---|---|---|
| Research artifacts | <session>/research/*.json | Yes |
| .msg/meta.json | <session>/wisdom/.msg/meta.json | Yes |
| Existing blueprints | <session>/interaction/blueprints/*.md | Only for INTERACT-002+ |
1. Extract session path from task description 2. Read research findings: interaction-inventory.json, browser-api-audit.json, pattern-reference.json 3. Detect task type from subject: "001" -> Primary blueprint, "002" -> Secondary/gallery blueprint 4. If INTERACT-002+: read existing blueprints for consistency with base component
Phase 3: Design Execution
Primary Blueprint (INTERACT-001):
For each target component, produce a blueprint document containing:
State Machine
Define complete state diagram:
[idle] --(pointerenter)--> [hover]
[hover] --(pointerdown)--> [active]
[hover] --(pointerleave)--> [idle]
[active] --(pointermove)--> [dragging/animating]
[active] --(pointerup)--> [hover]
[dragging] --(pointerup)--> [settling]
[settling] --(transitionend)--> [idle]
[any] --(focus)--> [focused]
[focused] --(blur)--> [previous-state]
[any] --(keydown:Escape)--> [idle]- All states must be reachable
- All states must have exit transitions
- Error/reset transitions from every state back to idle
Event Flow Map
Map events to handlers to state transitions:
| Event | Source | Handler | State Transition | Side Effect |
|---|---|---|---|---|
| pointerdown | element | onPointerDown | idle->active | setPointerCapture, preventDefault |
| pointermove | document | onPointerMove | active->dragging | update position via lerp |
| pointerup | document | onPointerUp | dragging->settling | releasePointerCapture |
| keydown:ArrowLeft | element | onKeyDown | - | decrement value |
| keydown:ArrowRight | element | onKeyDown | - | increment value |
| keydown:Escape | element | onKeyDown | any->idle | reset to default |
| keydown:Enter/Space | element | onKeyDown | idle->active | toggle/activate |
Gesture Specification
For pointer/touch interactions:
| Gesture | Detection | Parameters |
|---|---|---|
| Drag | pointerdown + pointermove > 3px | lerp speed: 0.15, axis: x/y/both |
| Swipe | pointerup with velocity > 0.5px/ms | direction: left/right/up/down |
| Pinch | 2+ touch points, distance change | scale factor, min/max zoom |
| Scroll snap | CSS scroll-snap-type: x mandatory | align: start/center, behavior: smooth |
- Lerp interpolation:
current += (target - current) * speed - Dead zone: ignore movements < 3px from start
- Velocity tracking: store last 3-5 pointer positions with timestamps
Animation Choreography
Define animation sequences:
| Animation | Trigger | Properties | Duration | Easing | GPU |
|---|---|---|---|---|---|
| Entry | mount/reveal | opacity 0->1, translateY 20px->0 | 400ms | cubic-bezier(0.16,1,0.3,1) | Yes |
| Exit | unmount/hide | opacity 1->0, translateY 0->-10px | 200ms | ease-in | Yes |
| Drag follow | pointermove | translateX via lerp | per-frame | linear (lerp) | Yes |
| Settle | pointerup | translateX to snap point | 300ms | cubic-bezier(0.16,1,0.3,1) | Yes |
| Hover | pointerenter | scale 1->1.02 | 200ms | ease-out | Yes |
| Focus ring | focus-visible | outline-offset 0->2px | 150ms | ease-out | No (outline) |
| Stagger | intersection | delay: index * 80ms | 400ms+delay | cubic-bezier(0.16,1,0.3,1) | Yes |
- ALL animations must use transform + opacity only (GPU-composited)
- Exception: outline for focus indicators
- Reduced motion: replace all motion with opacity-only crossfade (200ms)
Input Mapping Table
Unified mapping across input methods:
| Action | Mouse | Touch | Keyboard | Screen Reader |
|---|---|---|---|---|
| Activate | click | tap | Enter/Space | Enter/Space |
| Navigate prev | - | swipe-right | ArrowLeft | ArrowLeft |
| Navigate next | - | swipe-left | ArrowRight | ArrowRight |
| Drag/adjust | pointerdown+move | pointerdown+move | Arrow keys (step) | Arrow keys (step) |
| Dismiss | click outside | tap outside | Escape | Escape |
| Focus | pointermove (hover) | - | Tab | Tab |
Platform API Preference
When designing interaction blueprints, prefer native APIs over custom implementations:
| Need | Native API | Custom Fallback |
|---|---|---|
| Modal dialog | <dialog> + showModal() | Custom with focus trap + inert |
| Tooltip/popover | Popover API (popover attribute) | Custom with click-outside listener |
| Dropdown positioning | CSS Anchor Positioning | position: fixed + JS coords |
| Focus trap | <dialog> built-in or inert attribute | Manual focus cycling with tabindex |
| Escape-to-close | Built into <dialog> and Popover | Manual keydown listener |
Document in blueprint: which native API to use, what the fallback is for unsupported browsers, and how to feature-detect.
Gallery/Secondary Blueprint (INTERACT-002):
- Design scroll-snap container interaction
- Navigation controls (prev/next arrows, dots/indicators)
- Active item detection via IntersectionObserver
- Keyboard navigation within gallery (ArrowLeft/ArrowRight between items)
- Touch momentum and snap behavior
- Reference base component blueprint for consistency
Output: <session>/interaction/blueprints/{component-name}.md
Phase 4: Self-Validation
| Check | Pass Criteria |
|---|---|
| State machine complete | All states reachable, all states have exit |
| Event coverage | All events mapped to handlers |
| Keyboard complete | All interactive actions have keyboard equivalent |
| Touch parity | All mouse actions have touch equivalent |
| GPU-only animations | No width/height/top/left animations |
| Reduced motion | prefers-reduced-motion fallback defined |
| Screen reader path | All actions accessible via screen reader |
If any check fails, revise the blueprint before output.
Update <session>/wisdom/.msg/meta.json under interaction-designer namespace:
- Read existing -> merge
{ "interaction-designer": { task_type, components_designed, states_count, events_count, gestures } }-> write back
Interaction Pattern Researcher
Analyze existing interactive components, audit browser API usage, and collect reference patterns for target component types. Produce foundation data for downstream interaction-designer, builder, and a11y-tester roles.
Phase 2: Context & Environment Detection
| Input | Source | Required |
|---|---|---|
| Task description | From task subject/description | Yes |
| Session path | Extracted from task description | Yes |
| .msg/meta.json | <session>/wisdom/.msg/meta.json | No |
1. Extract session path and target scope from task description 2. Detect project structure and existing interactive patterns:
| File Pattern | Detected Pattern |
|---|---|
| *.js with addEventListener | Event-driven components |
| IntersectionObserver usage | Scroll-triggered animations |
| ResizeObserver usage | Responsive layout components |
| pointer/mouse/touch events | Interactive drag/gesture components |
| scroll-snap in CSS | Scroll-snap gallery |
| backdrop-filter in CSS | Glass/frosted effects |
| clip-path in CSS | Reveal/mask animations |
3. Use CLI tools (e.g., ccw cli -p "..." --tool gemini --mode analysis) or direct tools (Glob, Grep) to scan for existing interactive components, animation patterns, event handling approaches 4. Read interaction type context from session config
Phase 3: Research Execution
Execute 3 analysis streams:
Stream 1 -- Interaction Inventory:
- Search for existing interactive components (event listeners, observers, animation code)
- Identify interaction patterns in use (drag, scroll, overlay, reveal)
- Map component lifecycle (init, mount, resize, destroy)
- Find dependency patterns (any external libs vs vanilla)
- Catalog gesture handling approaches (pointer vs mouse+touch)
- Output:
<session>/research/interaction-inventory.json - Schema:
{
"existing_components": [
{ "name": "", "type": "", "events": [], "observers": [], "file": "" }
],
"patterns": {
"event_handling": "",
"animation_approach": "",
"lifecycle": "",
"dependency_model": ""
},
"summary": { "total_interactive": 0, "vanilla_count": 0, "lib_count": 0 }
}Stream 2 -- Browser API Audit:
- Check availability and usage of target browser APIs:
- IntersectionObserver (scroll triggers, lazy loading, visibility detection)
- ResizeObserver (responsive layout, container queries)
- Pointer Events (unified mouse/touch/pen input)
- Touch Events (gesture recognition, multi-touch)
- CSS scroll-snap (snap points, scroll behavior)
- CSS clip-path (shape masking, reveal animations)
- CSS backdrop-filter (blur, brightness, glass effects)
- Web Animations API (programmatic animation control)
- requestAnimationFrame (frame-synced updates)
- Identify polyfill needs for target browser support
- Output:
<session>/research/browser-api-audit.json - Schema:
{
"apis": {
"<api-name>": {
"available": true,
"in_use": false,
"support": "baseline|modern|polyfill-needed",
"usage_count": 0,
"notes": ""
}
},
"polyfill_needs": [],
"min_browser_target": ""
}Stream 3 -- Pattern Reference:
- Collect reference patterns for each target component type
- For each component, document: state machine pattern, event flow, animation approach, touch handling, accessibility pattern
- Reference well-known implementations (e.g., scroll-snap gallery, split-view compare, lightbox overlay)
- Note performance considerations and gotchas per pattern
- Output:
<session>/research/pattern-reference.json - Schema:
{
"patterns": [
{
"component_type": "",
"state_machine": { "states": [], "transitions": [] },
"events": { "primary": [], "fallback": [] },
"animation": { "approach": "", "gpu_only": true, "easing": "" },
"touch": { "gestures": [], "threshold_px": 0 },
"a11y": { "role": "", "aria_states": [], "keyboard": [] },
"performance": { "budget_ms": 0, "gotchas": [] }
}
]
}Compile research summary metrics: existing_interactive_count, vanilla_ratio, apis_available, polyfill_count, patterns_collected.
Phase 4: Validation & Output
1. Verify all 3 output files exist and contain valid JSON with required fields:
| File | Required Fields |
|---|---|
| interaction-inventory.json | existing_components array, patterns object |
| browser-api-audit.json | apis object |
| pattern-reference.json | patterns array |
2. If any file missing or invalid, re-run corresponding stream
3. Update <session>/wisdom/.msg/meta.json under researcher namespace:
- Read existing -> merge
{ "researcher": { interactive_count, vanilla_ratio, apis_available, polyfill_needs, scope } }-> write back
Interaction Pattern Catalog
Reference patterns for common interactive components. Each pattern defines the core interaction model, browser APIs, state machine, animation approach, and accessibility requirements.
---
Glass Terminal Pattern
Split-view layout with frosted glass effect, tab navigation, and command input simulation.
Core Interaction:
- Tab-based view switching (2-4 panels)
- Command input field with syntax-highlighted output
- Frosted glass background via
backdrop-filter: blur() - Resize-aware layout via ResizeObserver
State Machine:
[idle] --(tab-click)--> [switching]
[switching] --(transition-end)--> [idle]
[idle] --(input-focus)--> [input-active]
[input-active] --(Enter)--> [processing]
[processing] --(output-ready)--> [idle]
[input-active] --(Escape)--> [idle]Browser APIs: ResizeObserver, CSS backdrop-filter, CSS custom properties
Animation:
- Tab switch: opacity crossfade (200ms, ease-out), GPU-only
- Output appear: translateY(10px)->0 + opacity (300ms, ease-out)
- Cursor blink: CSS animation (1s steps(2))
CSS Key Properties:
.glass-terminal {
backdrop-filter: blur(12px) saturate(180%);
-webkit-backdrop-filter: blur(12px) saturate(180%);
background: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
}Accessibility:
- role="tablist" + role="tab" + role="tabpanel"
- aria-selected on active tab
- Arrow keys navigate tabs, Enter/Space activates
- Input field: role="textbox", aria-label
- Output: aria-live="polite" for new content
---
Split Compare Pattern
Before/after overlay with draggable divider for visual comparison.
Core Interaction:
- Draggable vertical divider splits two overlapping images/views
- Pointer events for drag with Lerp interpolation (speed: 0.15)
- clip-path animation reveals before/after content
- Touch-friendly with full pointer event support
State Machine:
[idle] --(pointerenter)--> [hover]
[hover] --(pointerdown on divider)--> [dragging]
[hover] --(pointerleave)--> [idle]
[dragging] --(pointermove)--> [dragging] (update position)
[dragging] --(pointerup)--> [settling]
[settling] --(lerp-complete)--> [idle]
[any] --(focus + ArrowLeft/Right)--> [keyboard-adjusting]
[keyboard-adjusting] --(keyup)--> [idle]Browser APIs: Pointer Events, CSS clip-path, ResizeObserver, requestAnimationFrame
Animation:
- Divider follow: Lerp
current += (target - current) * 0.15per frame - Clip-path update:
clip-path: inset(0 0 0 ${position}%)on after layer - Settle: natural Lerp deceleration to final position
- Hover hint: divider scale(1.1) + glow (200ms, ease-out)
CSS Key Properties:
.split-compare__after {
clip-path: inset(0 0 0 var(--split-position, 50%));
transition: none; /* JS-driven via lerp */
}
.split-compare__divider {
cursor: col-resize;
touch-action: none; /* prevent scroll during drag */
}Keyboard:
- Tab to divider element (tabindex="0")
- ArrowLeft/ArrowRight: move divider 2% per keypress
- Home/End: move to 0%/100%
Accessibility:
- role="slider", aria-valuenow, aria-valuemin="0", aria-valuemax="100"
- aria-label="Image comparison slider"
- Keyboard step: 2%, large step (PageUp/PageDown): 10%
---
Scroll-Snap Gallery Pattern
Horizontal scroll with CSS scroll-snap, navigation controls, and active item detection.
Core Interaction:
- CSS scroll-snap-type: x mandatory on container
- scroll-snap-align: start on children
- Touch-friendly: native momentum scrolling
- Navigation dots/arrows update with IntersectionObserver
- Keyboard: ArrowLeft/ArrowRight navigate between items
State Machine:
[idle] --(scroll-start)--> [scrolling]
[scrolling] --(scroll-end)--> [snapped]
[snapped] --(intersection-change)--> [idle] (update active)
[idle] --(arrow-click)--> [navigating]
[navigating] --(scrollTo-complete)--> [idle]
[idle] --(keyboard-arrow)--> [navigating]Browser APIs: CSS scroll-snap, IntersectionObserver, Element.scrollTo(), Pointer Events
Animation:
- Scroll: native CSS scroll-snap (browser-handled, smooth)
- Active dot: scale(1) -> scale(1.3) + opacity change (200ms, ease-out)
- Item entry: opacity 0->1 as intersection threshold crossed (CSS transition)
- Arrow hover: translateX(+-2px) (150ms, ease-out)
CSS Key Properties:
.gallery__track {
display: flex;
overflow-x: auto;
scroll-snap-type: x mandatory;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
scrollbar-width: none; /* Firefox */
}
.gallery__track::-webkit-scrollbar { display: none; }
.gallery__item {
scroll-snap-align: start;
flex: 0 0 100%; /* or 80% for peek */
}IntersectionObserver Config:
new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) updateActiveItem(entry.target);
});
}, { root: trackElement, threshold: 0.5 });Accessibility:
- role="region", aria-label="Image gallery"
- role="group" on each item, aria-roledescription="slide"
- aria-label="Slide N of M" on each item
- Navigation: role="tablist" on dots, role="tab" on each dot
- ArrowLeft/ArrowRight between items, Home/End to first/last
---
Scroll Reveal Pattern
Elements animate into view as user scrolls, using IntersectionObserver with staggered delays.
Core Interaction:
- IntersectionObserver with threshold: 0.1 triggers entry animation
- data-reveal attribute marks revealable elements
- Staggered delay: index * 80ms for grouped items
- GPU-only: translateY(20px)->0 + opacity 0->1
- One-shot: element stays visible after reveal
State Machine:
[hidden] --(intersection: entering)--> [revealing]
[revealing] --(animation-end)--> [visible]
[visible] -- (terminal state, no transition out)Browser APIs: IntersectionObserver, CSS transitions, requestAnimationFrame
Animation:
- Entry: translateY(20px) -> translateY(0) + opacity 0->1
- Duration: 400ms
- Easing: cubic-bezier(0.16, 1, 0.3, 1)
- Stagger: CSS custom property
--reveal-delay: calc(var(--reveal-index) * 80ms) - Reduced motion: opacity-only crossfade (200ms)
CSS Key Properties:
[data-reveal] {
opacity: 0;
transform: translateY(20px);
transition: opacity 400ms cubic-bezier(0.16, 1, 0.3, 1),
transform 400ms cubic-bezier(0.16, 1, 0.3, 1);
transition-delay: var(--reveal-delay, 0ms);
}
[data-reveal="visible"] {
opacity: 1;
transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
[data-reveal] {
transform: none;
transition: opacity 200ms ease;
}
}IntersectionObserver Config:
new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.dataset.reveal = 'visible';
observer.unobserve(entry.target); // one-shot
}
});
}, { threshold: 0.1 });Accessibility:
- Content must be accessible in DOM before reveal (no display:none)
- Use opacity + transform only (content readable by screen readers at all times)
- aria-hidden NOT used (content is always in accessibility tree)
- Stagger delay < 500ms total to avoid perception of broken page
---
Lens/Overlay Pattern
Magnification overlay that follows pointer position over an image or content area.
Core Interaction:
- Circular/rectangular lens follows pointer over source content
- Magnified view rendered via CSS transform: scale() on background
- Lens positioned via transform: translate() (GPU-only)
- Toggle on click/tap, follow on pointermove
State Machine:
[inactive] --(click/tap on source)--> [active]
[active] --(pointermove)--> [active] (update lens position)
[active] --(click/tap)--> [inactive]
[active] --(pointerleave)--> [inactive]
[active] --(Escape)--> [inactive]
[inactive] --(Enter/Space on source)--> [active-keyboard]
[active-keyboard] --(Arrow keys)--> [active-keyboard] (move lens)
[active-keyboard] --(Escape)--> [inactive]Browser APIs: Pointer Events, CSS transform, CSS clip-path/border-radius, requestAnimationFrame
Animation:
- Lens appear: opacity 0->1 + scale(0.8)->scale(1) (200ms, ease-out)
- Lens follow: Lerp position tracking (speed: 0.2)
- Lens dismiss: opacity 1->0 + scale(1)->scale(0.9) (150ms, ease-in)
CSS Key Properties:
.lens__overlay {
position: absolute;
width: 150px;
height: 150px;
border-radius: 50%;
overflow: hidden;
pointer-events: none;
transform: translate(var(--lens-x), var(--lens-y));
will-change: transform;
}
.lens__magnified {
transform: scale(var(--lens-zoom, 2));
transform-origin: var(--lens-origin-x) var(--lens-origin-y);
}Accessibility:
- Source: role="img" with descriptive aria-label
- Lens toggle: aria-expanded on source element
- Keyboard: Enter/Space to activate, Arrow keys to pan, Escape to dismiss
- Screen reader: aria-live="polite" announces zoom state changes
- Not essential content: decorative enhancement, base content always visible
---
Lightbox Pattern
Full-viewport overlay for content viewing with background dim and entry animation.
Core Interaction:
- Click/tap thumbnail opens full-viewport overlay
- Background dim via backdrop-filter + background overlay
- Scale-up entry animation from thumbnail position
- Dismiss: click outside, Escape key, close button
- Focus trap: Tab cycles within lightbox
- Scroll lock on body while open
State Machine:
[closed] --(click thumbnail)--> [opening]
[opening] --(animation-end)--> [open]
[open] --(click-outside / Escape / close-btn)--> [closing]
[closing] --(animation-end)--> [closed]
[open] --(ArrowLeft)--> [navigating-prev]
[open] --(ArrowRight)--> [navigating-next]
[navigating-*] --(content-loaded)--> [open]Browser APIs: CSS backdrop-filter, Focus trap (manual), CSS transitions, Pointer Events
Animation:
- Open: scale(0.85)->scale(1) + opacity 0->1 (300ms, cubic-bezier(0.16,1,0.3,1))
- Close: scale(1)->scale(0.95) + opacity 1->0 (200ms, ease-in)
- Backdrop: opacity 0->1 (250ms, ease-out)
- Navigation: translateX crossfade between items (250ms)
CSS Key Properties:
.lightbox__backdrop {
position: fixed;
inset: 0;
background: rgba(0, 0, 0, 0.8);
backdrop-filter: blur(4px);
z-index: 1000;
}
.lightbox__content {
transform: scale(var(--lb-scale, 0.85));
opacity: var(--lb-opacity, 0);
transition: transform 300ms cubic-bezier(0.16, 1, 0.3, 1),
opacity 300ms cubic-bezier(0.16, 1, 0.3, 1);
}
.lightbox--open .lightbox__content {
--lb-scale: 1;
--lb-opacity: 1;
}Focus Trap Implementation:
// On open: store trigger, move focus to first focusable in lightbox
// On Tab: cycle within lightbox (first <-> last focusable)
// On close: restore focus to original trigger element
// Prevent body scroll: document.body.style.overflow = 'hidden'Accessibility:
- role="dialog", aria-modal="true", aria-label="Image viewer"
- Close button: aria-label="Close lightbox"
- Focus trap: Tab cycles within dialog
- Escape dismisses
- ArrowLeft/ArrowRight for gallery navigation
- aria-live="polite" announces current item "Image N of M"
- Scroll lock: prevent background scroll while open
Pipeline Definitions
Interactive craft pipeline modes and task registry.
Pipeline Modes
| Mode | Description | Task Count |
|---|---|---|
| single | Single component: research -> interaction design -> build -> a11y test | 4 tasks |
| gallery | Gallery: base component + scroll container, two build phases | 6 tasks |
| page | Full page: parallel component builds after single interaction design | 3 + N tasks |
Single Pipeline Task Registry
| Task ID | Role | blockedBy | Description |
|---|---|---|---|
| RESEARCH-001 | researcher | [] | Interaction inventory, browser API audit, pattern reference |
| INTERACT-001 | interaction-designer | [RESEARCH-001] | State machine, event flow, gesture spec, animation choreography |
| BUILD-001 | builder | [INTERACT-001] | Vanilla JS + CSS component: ES module, GPU animations, touch-aware |
| A11Y-001 | a11y-tester | [BUILD-001] | Keyboard, screen reader, reduced motion, focus, contrast audit |
Gallery Pipeline Task Registry
| Task ID | Role | blockedBy | Description |
|---|---|---|---|
| RESEARCH-001 | researcher | [] | Interaction patterns for base component + gallery container |
| INTERACT-001 | interaction-designer | [RESEARCH-001] | Base component interaction blueprint |
| BUILD-001 | builder | [INTERACT-001] | Base component implementation |
| INTERACT-002 | interaction-designer | [BUILD-001] | Gallery/scroll-snap container blueprint |
| BUILD-002 | builder | [INTERACT-002] | Gallery container + navigation implementation |
| A11Y-001 | a11y-tester | [BUILD-002] | Full gallery accessibility audit |
Page Pipeline Task Registry
| Task ID | Role | blockedBy | Description |
|---|---|---|---|
| RESEARCH-001 | researcher | [] | Interaction patterns for all page sections |
| INTERACT-001 | interaction-designer | [RESEARCH-001] | Blueprints for all interactive sections |
| BUILD-001 | builder | [INTERACT-001] | Section 1 component |
| BUILD-002 | builder | [INTERACT-001] | Section 2 component |
| ... | builder | [INTERACT-001] | Additional sections (parallel) |
| BUILD-00N | builder | [INTERACT-001] | Section N component |
| A11Y-001 | a11y-tester | [BUILD-001..N] | Full page accessibility audit |
Quality Gate (A11y Checkpoint)
| Checkpoint | Task | Condition | Action |
|---|---|---|---|
| A11Y Gate | A11Y-001 completes | 0 critical, 0 high | Pipeline complete |
| A11Y GC Loop | A11Y-* completes | Critical or high issues | Create BUILD-fix task, new A11Y task (max 2 rounds) |
GC Loop Behavior
| Signal | Condition | Action |
|---|---|---|
| a11y_passed | 0 critical, 0 high | GC converged -> pipeline complete |
| a11y_result | 0 critical, high > 0 | gc_rounds < max -> create BUILD-fix task |
| fix_required | critical > 0 | gc_rounds < max -> create BUILD-fix task (CRITICAL) |
| Any | gc_rounds >= max | Escalate to user: accept / try one more / terminate |
Parallel Spawn Rules
| Mode | After | Spawn Behavior |
|---|---|---|
| single | Sequential | One task at a time |
| gallery | Sequential | One task at a time |
| page | INTERACT-001 | Spawn BUILD-001..N in parallel (CP-3 fan-out) |
| page | All BUILD complete | Spawn A11Y-001 |
Collaboration Patterns
| Pattern | Roles | Description |
|---|---|---|
| CP-1 Linear Pipeline | All | Base sequential flow for single/gallery modes |
| CP-2 Review-Fix | builder <-> a11y-tester | GC loop with max 2 rounds |
| CP-3 Parallel Fan-out | builder (multiple) | Page mode: multiple BUILD tasks in parallel |
Output Artifacts
| Task | Output Path |
|---|---|
| RESEARCH-001 | <session>/research/*.json |
| INTERACT-* | <session>/interaction/blueprints/*.md |
| BUILD-* | <session>/build/components/.js + .css |
| A11Y-* | <session>/a11y/a11y-audit-*.md |
{
"team_name": "interactive-craft",
"team_display_name": "Interactive Craft",
"description": "Interactive component team with vanilla JS + CSS. Research -> interaction design -> build -> a11y test.",
"version": "1.0.0",
"roles": {
"coordinator": {
"task_prefix": null,
"responsibility": "Scope assessment, pipeline orchestration, GC loop control between builder and a11y-tester",
"message_types": ["task_unblocked", "a11y_checkpoint", "fix_required", "error", "shutdown"]
},
"researcher": {
"task_prefix": "RESEARCH",
"responsibility": "Interaction pattern analysis, browser API audit, reference pattern collection",
"message_types": ["research_ready", "research_progress", "error"]
},
"interaction-designer": {
"task_prefix": "INTERACT",
"responsibility": "State machine design, event flow mapping, gesture specification, animation choreography",
"message_types": ["blueprint_ready", "blueprint_revision", "blueprint_progress", "error"]
},
"builder": {
"task_prefix": "BUILD",
"inner_loop": true,
"responsibility": "Vanilla JS + CSS component implementation, progressive enhancement, GPU-only animations",
"message_types": ["build_ready", "build_revision", "build_progress", "error"]
},
"a11y-tester": {
"task_prefix": "A11Y",
"responsibility": "Keyboard navigation, screen reader, reduced motion, focus management, contrast testing",
"message_types": ["a11y_passed", "a11y_result", "fix_required", "error"]
}
},
"pipelines": {
"single": {
"description": "Single component: research -> interaction design -> build -> a11y test",
"task_chain": ["RESEARCH-001", "INTERACT-001", "BUILD-001", "A11Y-001"],
"complexity": "low"
},
"gallery": {
"description": "Gallery with base component + scroll container: two build phases",
"task_chain": [
"RESEARCH-001",
"INTERACT-001", "BUILD-001",
"INTERACT-002", "BUILD-002",
"A11Y-001"
],
"complexity": "medium"
},
"page": {
"description": "Full interactive page with parallel component builds",
"task_chain": [
"RESEARCH-001",
"INTERACT-001",
"BUILD-001..N (parallel)",
"A11Y-001"
],
"parallel_stage": "BUILD-001..N",
"complexity": "high"
}
},
"innovation_patterns": {
"generator_critic": {
"generator": "builder",
"critic": "a11y-tester",
"max_rounds": 2,
"convergence": "a11y.critical_count === 0 && a11y.high_count === 0",
"escalation": "Coordinator intervenes after max rounds"
},
"shared_memory": {
"file": "shared-memory.json",
"fields": {
"researcher": ["interaction_inventory", "browser_apis"],
"interaction-designer": ["state_machines", "event_flows"],
"builder": ["component_registry", "implementation_decisions"],
"a11y-tester": ["audit_history"]
}
},
"dynamic_pipeline": {
"criteria": {
"single": "scope.component_count <= 1",
"gallery": "scope.has_gallery || scope.has_scroll_collection",
"page": "scope.is_full_page || scope.section_count > 2"
}
},
"parallel_fanout": {
"pattern": "CP-3",
"description": "Multiple BUILD tasks spawned in parallel after single INTERACT blueprint",
"trigger": "page mode after INTERACT-001 completes",
"fallback": "If parallel fails, coordinator falls back to sequential execution"
}
},
"session_dirs": {
"base": ".workflow/.team/IC-{slug}-{YYYY-MM-DD}/",
"research": "research/",
"interaction": "interaction/blueprints/",
"build": "build/components/",
"a11y": "a11y/",
"messages": ".workflow/.team-msg/{team-name}/"
}
}
Vanilla Constraints
Zero-dependency rules for all interactive components built by this team. These constraints are non-negotiable and apply to every BUILD task output.
Dependency Rules
| Rule | Requirement |
|---|---|
| No npm packages | Zero import from node_modules or CDN URLs |
| No build tools required | Components run directly via <script type="module"> |
| No framework dependency | No React, Vue, Svelte, Angular, jQuery, etc. |
| No CSS preprocessor | No Sass, Less, PostCSS, Tailwind -- pure CSS only |
| No bundler required | No webpack, Vite, Rollup, esbuild in critical path |
JavaScript Rules
| Rule | Requirement |
|---|---|
| ES modules only | export class, export function, import syntax |
| Class-based components | Private fields (#), constructor(element, options) |
| No inline styles from JS | Set CSS custom properties or toggle CSS classes |
| No document.write | Use DOM APIs (createElement, append, etc.) |
| No eval or innerHTML | Use textContent or DOM construction |
| requestAnimationFrame | All animation loops use rAF, not setInterval |
| Pointer Events primary | Use pointer events; touch events as fallback only |
| Cleanup required | destroy() method disconnects all observers/listeners |
| Auto-init pattern | document.querySelectorAll('[data-component]') on load |
CSS Rules
| Rule | Requirement |
|---|---|
| Custom properties | All configurable values as CSS custom properties |
| No inline styles | JS sets --custom-prop values, not style.left/top |
| State via data attributes | [data-state="active"], not inline style changes |
| GPU-only animations | transform and opacity ONLY in transitions/animations |
| No layout animations | Never animate width, height, top, left, margin, padding |
| will-change on animated | Hint browser for animated elements |
| Reduced motion | @media (prefers-reduced-motion: reduce) with instant fallback |
| focus-visible | :focus-visible for keyboard-only focus indicators |
| Responsive | Min touch target 44x44px on mobile, use @media breakpoints |
Progressive Enhancement
| Rule | Requirement |
|---|---|
| Content without JS | Base content visible and readable without JavaScript |
| CSS-only fallback | Essential layout works with CSS alone |
| No-JS class | Optional [data-js-enabled] class for JS-enhanced styles |
| Semantic HTML base | Use appropriate elements (button, a, nav, dialog) |
Performance Budget
| Metric | Budget |
|---|---|
| Frame time | < 5ms per frame (leaves room for browser work in 16ms budget) |
| Interaction response | < 50ms from input to visual feedback |
| Animation jank | 0 frames dropped at 60fps for GPU-composited animations |
| Observer callbacks | < 1ms per IntersectionObserver/ResizeObserver callback |
| Component init | < 100ms from constructor to interactive |
| Memory | No detached DOM nodes after destroy() |
| Listeners | All removed in destroy(), no orphaned listeners |
Forbidden Patterns
| Pattern | Why |
|---|---|
element.style.left = ... | Forces layout recalc, not GPU composited |
element.offsetWidth in animation loop | Forces synchronous layout (reflow) |
setInterval for animation | Not synced to display refresh rate |
setTimeout for animation | Not synced to display refresh rate |
innerHTML = userContent | XSS vector |
| Passive: false on scroll/touch without need | Blocks scrolling performance |
!important in component CSS | Breaks cascade, unmaintainable |
| Global CSS selectors (tag-only) | Leaks styles outside component scope |
File Output Convention
| File | Purpose | Location |
|---|---|---|
{name}.js | ES module component class | <session>/build/components/ |
{name}.css | Component styles with custom properties | <session>/build/components/ |
demo.html | Optional: standalone demo page | <session>/build/components/ |