AI Skill Report Card

Coding Marketing Interactions

B+78·Feb 25, 2026·Source: Web
YAML
--- name: coding-marketing-interactions description: Implements JavaScript interaction patterns for marketing websites. Use when building scroll animations, menus, modals, forms, and user preferences without complex engineering. ---

Coding Marketing Interactions

15 / 15
HTML
<button class="menu-toggle" data-target="nav-menu">Menu</button> <nav id="nav-menu" class="menu">...</nav> <script> // Toggle any element with data-target document.addEventListener('click', e => { const toggle = e.target.closest('[data-target]'); if (!toggle) return; const target = document.getElementById(toggle.dataset.target); target.classList.toggle('is-open'); toggle.classList.toggle('is-active'); }); </script>
Recommendation
Reduce verbosity in Best Practices and Common Pitfalls sections - assumes Claude needs basics explained
12 / 15

Progress:

  • Set up event delegation for clicks
  • Add Intersection Observer for scroll effects
  • Implement smooth scrolling with offset
  • Create form submission handler
  • Add localStorage for preferences
  • Test all interactions on mobile
Recommendation
The workflow checklist is too generic - make it more specific to common marketing site patterns
18 / 20

Example 1: Scroll-triggered animations

CSS
.fade-up { opacity: 0; transform: translateY(30px); transition: all 0.6s ease; } .fade-up.is-visible { opacity: 1; transform: translateY(0); }
JavaScript
// Animate elements on scroll const observer = new IntersectionObserver(entries => { entries.forEach(entry => { if (entry.isIntersecting) { entry.target.classList.add('is-visible'); } }); }); document.querySelectorAll('.fade-up').forEach(el => observer.observe(el));

Example 2: Menu/Modal/Accordion pattern

HTML
<!-- Menu --> <button data-target="mobile-menu" data-toggle="menu">Menu</button> <nav id="mobile-menu" class="menu">...</nav> <!-- Modal --> <button data-target="contact-modal" data-toggle="modal">Contact</button> <div id="contact-modal" class="modal"> <button data-close>×</button> </div> <!-- Accordion --> <div data-target="faq-1" data-toggle="accordion">Question?</div> <div id="faq-1" class="accordion-content">Answer...</div>
JavaScript
// Universal toggle system document.addEventListener('click', e => { // Handle toggles const toggle = e.target.closest('[data-target]'); if (toggle) { const target = document.getElementById(toggle.dataset.target); const type = toggle.dataset.toggle; target.classList.toggle('is-open'); toggle.classList.toggle('is-active'); // Modal-specific: close on backdrop click if (type === 'modal') { document.body.classList.toggle('modal-open'); } } // Handle close buttons if (e.target.closest('[data-close]')) { const modal = e.target.closest('.modal'); modal.classList.remove('is-open'); document.body.classList.remove('modal-open'); } });

Example 3: Smooth scroll with fixed nav offset

JavaScript
// Smooth scroll for anchor links document.addEventListener('click', e => { const link = e.target.closest('a[href^="#"]'); if (!link) return; e.preventDefault(); const target = document.querySelector(link.getAttribute('href')); if (!target) return; const navHeight = document.querySelector('.fixed-nav')?.offsetHeight || 0; const targetPosition = target.offsetTop - navHeight - 20; window.scrollTo({ top: targetPosition, behavior: 'smooth' }); });

Example 4: Contact form without backend

HTML
<form class="contact-form" data-form="contact"> <input name="name" required> <input name="email" type="email" required> <textarea name="message" required></textarea> <button type="submit">Send Message</button> <div class="form-status"></div> </form>
JavaScript
// Form handler (stores to localStorage) document.addEventListener('submit', e => { const form = e.target.closest('[data-form]'); if (!form) return; e.preventDefault(); const formData = new FormData(form); const data = Object.fromEntries(formData); // Store submission (since no backend) const submissions = JSON.parse(localStorage.getItem('form-submissions') || '[]'); submissions.push({ ...data, timestamp: new Date().toISOString() }); localStorage.setItem('form-submissions', JSON.stringify(submissions)); // Show success message form.querySelector('.form-status').innerHTML = '<p class="success">Message sent! We\'ll get back to you soon.</p>'; form.reset(); });

Example 5: User preferences

JavaScript
// Theme toggle with persistence function setTheme(theme) { document.documentElement.dataset.theme = theme; localStorage.setItem('theme', theme); } // Load saved theme const savedTheme = localStorage.getItem('theme') || 'light'; setTheme(savedTheme); // Theme toggle button document.addEventListener('click', e => { if (e.target.matches('[data-theme-toggle]')) { const current = document.documentElement.dataset.theme; setTheme(current === 'light' ? 'dark' : 'light'); } });
Recommendation
Add one more concrete input/output example showing a complete before/after interaction result

CSS Classes for State

CSS
/* Always use is- prefix for JavaScript-controlled states */ .menu { transform: translateX(-100%); } .menu.is-open { transform: translateX(0); } .modal { opacity: 0; pointer-events: none; } .modal.is-open { opacity: 1; pointer-events: auto; } .accordion-content { max-height: 0; overflow: hidden; } .accordion-content.is-open { max-height: 500px; }

Data Attributes for Configuration

  • data-target="element-id" - What to toggle
  • data-toggle="type" - How to behave (menu, modal, accordion)
  • data-offset="80" - Custom scroll offset
  • data-delay="200" - Animation delay

Event Delegation Pattern Always use this pattern instead of individual event listeners:

JavaScript
document.addEventListener('click', e => { // Check what was clicked and respond accordingly if (e.target.matches('.selector')) { // Handle the click } });

Mobile-First Considerations

JavaScript
// Check if user prefers reduced motion const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches; if (!prefersReducedMotion) { // Add animations } // Touch-friendly click handling document.addEventListener('touchstart', () => {}, { passive: true });

Don't attach event listeners to elements that might not exist yet:

JavaScript
// Bad document.querySelector('.button').addEventListener('click', handler); // Good - uses event delegation document.addEventListener('click', e => { if (e.target.matches('.button')) handler(e); });

Don't forget to handle edge cases:

JavaScript
// Always check if elements exist const target = document.getElementById(targetId); if (!target) return; // Handle empty localStorage gracefully const data = JSON.parse(localStorage.getItem('key') || '[]');

Don't use complex state management - keep it simple:

JavaScript
// Good - direct DOM manipulation element.classList.toggle('is-open'); // Avoid - unnecessary state objects const state = { isOpen: false }; // You don't need this

Don't reinvent the wheel for animations:

CSS
/* Use CSS transitions, not JavaScript animations */ .element { transition: all 0.3s ease; transform: translateX(-100%); } .element.is-open { transform: translateX(0); }

Debugging Tips

JavaScript
// Add this to see what's being clicked document.addEventListener('click', e => { console.log('Clicked:', e.target, 'Data attrs:', e.target.dataset); }); // Check localStorage contents console.log('All stored data:', { ...localStorage });
0
Grade B+AI Skill Framework
Scorecard
Criteria Breakdown
Quick Start
15/15
Workflow
12/15
Examples
18/20
Completeness
18/20
Format
15/15
Conciseness
12/15