export function featureVotingForm(form: FormTs) {
// Feature Voting & Prioritization Form
// Demonstrates: MatrixQuestion, CheckboxList, StarRating, RatingScale,
// SuggestionChips, Slider, RadioButton, computed values, dynamic styling
// State for tracking votes
const votesState = form.state<string[]>([]);
const maxVotes = 3;
// ============================================
// HEADER
// ============================================
form.addRow(row => {
row.addTextPanel('header', {
label: 'Help Us Build What Matters',
computedValue: () => 'Vote on the features you want most. Your input directly shapes our product roadmap.',
customStyles: {
backgroundColor: '#7c3aed',
color: 'white',
padding: '28px',
borderRadius: '12px',
textAlign: 'center',
fontSize: '15px'
}
});
});
// ============================================
// SECTION 1: Feature Voting
// ============================================
const votingSection = form.addSubform('voting', {
title: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return `Select Your Top Features (${votes.length}/${maxVotes})`;
},
customStyles: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
if (votes.length === maxVotes) {
return { backgroundColor: '#ecfdf5', padding: '20px', borderRadius: '10px', border: '2px solid #10b981' };
}
return { backgroundColor: '#faf5ff', padding: '20px', borderRadius: '10px' };
}
});
votingSection.addRow(row => {
row.addTextPanel('votingInstructions', {
computedValue: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
if (votes.length === 0) return `Choose up to ${maxVotes} features that would help you the most.`;
if (votes.length < maxVotes) return `${maxVotes - votes.length} vote${maxVotes - votes.length > 1 ? 's' : ''} remaining.`;
return `✓ All ${maxVotes} votes cast! You can change your selections below.`;
},
customStyles: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
if (votes.length === maxVotes) return { color: '#10b981', fontWeight: '500' };
return { color: '#6b7280', fontStyle: 'italic' };
}
});
});
votingSection.addRow(row => {
row.addCheckboxList('featureVotes', {
label: 'Available features to vote on:',
options: [
{ id: 'dark-mode', name: '🌙 Dark Mode - Full dark theme for the application' },
{ id: 'mobile-app', name: '📱 Mobile App - Native iOS and Android applications' },
{ id: 'api-access', name: '🔌 API Access - Public API for integrations' },
{ id: 'collaboration', name: '👥 Real-time Collaboration - Work together with team' },
{ id: 'templates', name: '📋 Template Library - Pre-built templates and examples' },
{ id: 'analytics', name: '📊 Advanced Analytics - Detailed reports and insights' },
{ id: 'integrations', name: '🔗 More Integrations - Connect with popular tools' },
{ id: 'ai-features', name: '🤖 AI-Powered Features - Smart automation and suggestions' },
{ id: 'offline-mode', name: '📴 Offline Mode - Work without internet connection' },
{ id: 'export-options', name: '📤 Export Options - More formats and customization' }
],
orientation: 'vertical',
max: maxVotes
});
});
// ============================================
// SECTION 2: Priority Ranking Matrix
// ============================================
const prioritySection = form.addSubform('priority', {
title: 'Rate Feature Importance',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
prioritySection.addRow(row => {
row.addTextPanel('priorityIntro', {
computedValue: () => 'Rate how important each of your selected features is to you:',
customStyles: { color: '#6b7280', marginBottom: '12px' }
});
});
prioritySection.addRow(row => {
row.addMatrixQuestion('featureImportance', {
label: '',
rows: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
const featureLabels: Record<string, string> = {
'dark-mode': 'Dark Mode',
'mobile-app': 'Mobile App',
'api-access': 'API Access',
'collaboration': 'Real-time Collaboration',
'templates': 'Template Library',
'analytics': 'Advanced Analytics',
'integrations': 'More Integrations',
'ai-features': 'AI-Powered Features',
'offline-mode': 'Offline Mode',
'export-options': 'Export Options'
};
return votes.map(v => ({
id: v,
label: featureLabels[v] || v,
isRequired: true
}));
},
columns: [
{ id: 'nice', label: 'Nice to Have' },
{ id: 'important', label: 'Important' },
{ id: 'critical', label: 'Critical' }
],
striped: true,
fullWidth: true
});
});
// ============================================
// SECTION 3: Use Case Details
// ============================================
const useCaseSection = form.addSubform('useCase', {
title: 'Your Use Case',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
},
customStyles: { backgroundColor: '#f5f3ff', padding: '20px', borderRadius: '10px' }
});
useCaseSection.addRow(row => {
row.addRadioButton('userRole', {
label: 'What best describes your role?',
options: [
{ id: 'individual', name: 'Individual User' },
{ id: 'team-lead', name: 'Team Lead / Manager' },
{ id: 'developer', name: 'Developer / Technical' },
{ id: 'designer', name: 'Designer / Creative' },
{ id: 'business', name: 'Business / Strategy' },
{ id: 'other', name: 'Other' }
],
orientation: 'horizontal'
}, '1fr');
row.addRadioButton('teamSize', {
label: 'Team size',
options: [
{ id: 'solo', name: 'Just me' },
{ id: 'small', name: '2-10' },
{ id: 'medium', name: '11-50' },
{ id: 'large', name: '50+' }
],
orientation: 'horizontal'
}, '1fr');
});
useCaseSection.addRow(row => {
row.addSlider('usageFrequency', {
label: 'How often do you use our product?',
min: 1,
max: 5,
step: 1,
showValue: false,
defaultValue: 3
}, '1fr');
row.addTextPanel('usageLabel', {
computedValue: () => {
const freq = useCaseSection.slider('usageFrequency')?.value();
const labels: Record<number, string> = {
1: 'Rarely (monthly)',
2: 'Occasionally (weekly)',
3: 'Regularly (few times/week)',
4: 'Frequently (daily)',
5: 'Constantly (multiple times/day)'
};
return labels[freq ?? 3] || '';
},
customStyles: { fontSize: '14px', color: '#7c3aed', fontWeight: '500' }
}, '1fr');
});
// ============================================
// SECTION 4: Impact Assessment
// ============================================
const impactSection = form.addSubform('impact', {
title: 'Potential Impact',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
impactSection.addRow(row => {
row.addRatingScale('productivityImpact', {
label: 'How much would your top feature improve your productivity?',
preset: 'likert-5',
lowLabel: 'Minimal impact',
highLabel: 'Game changer',
alignment: 'center',
size: 'md'
});
});
impactSection.addRow(row => {
row.addSuggestionChips('benefitAreas', {
label: 'Which areas would benefit most?',
suggestions: [
{ id: 'speed', name: 'Work faster' },
{ id: 'quality', name: 'Better output' },
{ id: 'collaborate', name: 'Team collaboration' },
{ id: 'organize', name: 'Stay organized' },
{ id: 'automate', name: 'Automate tasks' },
{ id: 'insights', name: 'Get insights' }
],
alignment: 'center',
max: 3
});
});
// ============================================
// SECTION 5: Willingness to Pay
// ============================================
const paySection = form.addSubform('pay', {
title: 'Value Assessment',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
},
customStyles: { backgroundColor: '#fefce8', padding: '20px', borderRadius: '10px' }
});
paySection.addRow(row => {
row.addRadioButton('willingToPay', {
label: 'Would you be willing to pay more for your top voted feature?',
options: [
{ id: 'yes-upgrade', name: 'Yes, I\'d upgrade my plan for it' },
{ id: 'yes-addon', name: 'Yes, as a paid add-on' },
{ id: 'included', name: 'Only if included in current plan' },
{ id: 'switch', name: 'I\'d consider switching from a competitor for it' }
],
orientation: 'vertical'
});
});
paySection.addRow(row => {
row.addStarRating('satisfactionWithRoadmap', {
label: 'How satisfied are you with our product direction overall?',
maxStars: 5,
size: 'lg',
alignment: 'center',
filledColor: '#eab308',
showConfettiOnMax: true
});
});
// ============================================
// SECTION 6: Feature Request
// ============================================
const requestSection = form.addSubform('request', {
title: 'Missing Something?',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
requestSection.addRow(row => {
row.addTextarea('newFeatureIdea', {
label: 'Is there a feature you want that\'s not on the list?',
placeholder: 'Describe the feature you wish we would build...',
rows: 3,
autoExpand: true
});
});
requestSection.addRow(row => {
row.addTextarea('useCaseDescription', {
label: 'Tell us how you would use your top voted feature',
placeholder: 'Describe a specific scenario or workflow...',
rows: 3,
autoExpand: true
});
});
// ============================================
// SECTION 7: Summary
// ============================================
const summarySection = form.addSubform('summary', {
title: 'Your Votes Summary',
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
summarySection.addRow(row => {
row.addTextPanel('summaryContent', {
computedValue: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
const importance = prioritySection.matrixQuestion('featureImportance')?.value() || {};
const productivity = impactSection.ratingScale('productivityImpact')?.value();
const benefits = impactSection.suggestionChips('benefitAreas')?.value() || [];
const payPref = paySection.radioButton('willingToPay')?.value();
const satisfaction = paySection.starRating('satisfactionWithRoadmap')?.value();
if (votes.length === 0) return '';
const featureLabels: Record<string, string> = {
'dark-mode': '🌙 Dark Mode',
'mobile-app': '📱 Mobile App',
'api-access': '🔌 API Access',
'collaboration': '👥 Collaboration',
'templates': '📋 Templates',
'analytics': '📊 Analytics',
'integrations': '🔗 Integrations',
'ai-features': '🤖 AI Features',
'offline-mode': '📴 Offline Mode',
'export-options': '📤 Export Options'
};
const importanceLabels: Record<string, string> = {
'nice': '○', 'important': '◐', 'critical': '●'
};
let summary = '🗳️ Feature Voting Summary\n';
summary += `${'═'.repeat(30)}\n\n`;
summary += `📊 Your Votes (${votes.length}/${maxVotes}):\n`;
summary += `${'─'.repeat(25)}\n`;
votes.forEach(v => {
const imp = importance[v] as string | undefined;
const impSymbol = imp ? importanceLabels[imp] || '' : '';
summary += `${featureLabels[v] || v} ${impSymbol}\n`;
});
summary += `\n○ Nice to Have ◐ Important ● Critical\n`;
if (productivity !== null && productivity !== undefined) {
summary += `\n⚡ Productivity Impact: ${productivity}/5`;
}
if (benefits.length > 0) {
summary += `\n🎯 Benefit Areas: ${benefits.length} selected`;
}
if (payPref) {
const payLabels: Record<string, string> = {
'yes-upgrade': 'Would upgrade plan',
'yes-addon': 'Would pay as add-on',
'included': 'If included only',
'switch': 'Would switch from competitor'
};
summary += `\n💰 Payment: ${payLabels[payPref] || payPref}`;
}
if (satisfaction !== null && satisfaction !== undefined) {
summary += `\n\n⭐ Roadmap Satisfaction: ${'★'.repeat(satisfaction)}${'☆'.repeat(5 - satisfaction)}`;
}
return summary;
},
customStyles: {
padding: '20px',
borderRadius: '10px',
backgroundColor: '#f5f3ff',
whiteSpace: 'pre-wrap',
fontFamily: 'monospace',
fontSize: '14px',
borderLeft: '4px solid #7c3aed'
}
});
});
// ============================================
// FORM CONFIGURATION
// ============================================
form.configureSubmitButton({
label: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
if (votes.length === 0) return 'Please select at least one feature';
return `Submit ${votes.length} Vote${votes.length > 1 ? 's' : ''}`;
},
isVisible: () => {
const votes = votingSection.checkboxList('featureVotes')?.value() || [];
return votes.length > 0;
}
});
form.configureCompletionScreen({
type: 'text',
title: 'Thank you for voting!',
message: 'Your votes help us prioritize what to build next. We review all feature votes monthly and share updates on our roadmap. Watch for announcements about features you voted for!'
});
}