โ† Components/Feedback

NPSWidget

npswidget-1779379671575.tsx
'use client'
import { useState } from 'react'

const REASONS: Record<string, string[]> = {
  low: ['Too expensive', 'Hard to find components', 'Quality issues', 'Missing components', 'Poor documentation'],
  mid: ['Good but missing features', 'Would recommend with caveats', 'Price could be better', 'More components needed'],
  high: ['Amazing quality', 'MCP is incredible', 'Saves hours of work', 'Best UI library I found', 'Recommend to everyone'],
}

export default function NPSWidget() {
  const [score, setScore] = useState<number | null>(null)
  const [reason, setReason] = useState<string | null>(null)
  const [submitted, setSubmitted] = useState(false)

  const bucket = score === null ? null : score <= 6 ? 'low' : score <= 8 ? 'mid' : 'high'
  const label = bucket === 'high' ? 'Promoter ๐ŸŽ‰' : bucket === 'mid' ? 'Passive ๐Ÿ˜' : 'Detractor ๐Ÿ˜•'
  const labelColor = bucket === 'high' ? '#22c55e' : bucket === 'mid' ? '#f59e0b' : '#ef4444'

  if (submitted) return (
    <div style={{ padding: 40, background: '#0A0A0A', display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 280 }}>
      <div style={{ textAlign: 'center' }}>
        <div style={{ fontSize: 48, marginBottom: 16 }}>{bucket === 'high' ? '๐Ÿš€' : bucket === 'mid' ? '๐Ÿ‘' : '๐Ÿ’ช'}</div>
        <div style={{ color: '#F5F5F0', fontSize: 18, fontWeight: 700, marginBottom: 8 }}>Thanks for your feedback!</div>
        <div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 13, marginBottom: 20 }}>Your score: <strong style={{ color: labelColor }}>{score}/10 โ€” {label}</strong></div>
        <button onClick={() => { setScore(null); setReason(null); setSubmitted(false) }} style={{ background: 'rgba(255,255,255,0.06)', border: '1px solid rgba(255,255,255,0.1)', color: '#F5F5F0', borderRadius: 8, padding: '8px 16px', cursor: 'pointer', fontSize: 13 }}>Submit another</button>
      </div>
    </div>
  )

  return (
    <div style={{ background: '#0A0A0A', padding: 32, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 28, minHeight: 280 }}>
      <div style={{ textAlign: 'center' }}>
        <div style={{ color: '#F5F5F0', fontSize: 17, fontWeight: 700, marginBottom: 6 }}>How likely are you to recommend Empire UI?</div>
        <div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 13 }}>0 = Not at all ยท 10 = Extremely likely</div>
      </div>

      <div style={{ display: 'flex', gap: 6 }}>
        {Array.from({ length: 11 }, (_, i) => {
          const color = i <= 6 ? '#ef4444' : i <= 8 ? '#f59e0b' : '#22c55e'
          return (
            <button key={i} onClick={() => setScore(i)} style={{
              width: 38, height: 38, borderRadius: 8, border: '1px solid',
              borderColor: score === i ? color : 'rgba(255,255,255,0.1)',
              background: score === i ? color + '20' : 'rgba(255,255,255,0.04)',
              color: score === i ? color : 'rgba(255,255,255,0.5)', fontWeight: score === i ? 800 : 400,
              cursor: 'pointer', fontSize: 14, transition: 'all 0.15s',
            }}>{i}</button>
          )
        })}
      </div>

      {score !== null && (
        <div style={{ width: '100%', maxWidth: 440, animation: 'fadeIn 0.3s ease' }}>
          <div style={{ color: labelColor, fontSize: 13, fontWeight: 700, marginBottom: 12, textAlign: 'center' }}>{label}</div>
          <div style={{ color: 'rgba(255,255,255,0.5)', fontSize: 13, marginBottom: 10 }}>What's the main reason for your score?</div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, marginBottom: 20 }}>
            {(REASONS[bucket!] || []).map(r => (
              <button key={r} onClick={() => setReason(r)} style={{ background: reason === r ? 'rgba(201,168,76,0.12)' : 'rgba(255,255,255,0.04)', border: '1px solid', borderColor: reason === r ? 'rgba(201,168,76,0.3)' : 'rgba(255,255,255,0.08)', color: reason === r ? '#C9A84C' : 'rgba(255,255,255,0.5)', borderRadius: 20, padding: '5px 12px', cursor: 'pointer', fontSize: 12 }}>{r}</button>
            ))}
          </div>
          <button onClick={() => setSubmitted(true)} style={{ width: '100%', background: '#C9A84C', color: '#0A0A0A', border: 'none', borderRadius: 10, padding: '12px', fontWeight: 700, cursor: 'pointer', fontSize: 14 }}>Submit feedback</button>
        </div>
      )}
      <style>{`@keyframes fadeIn { from { opacity:0; transform:translateY(8px) } to { opacity:1; transform:translateY(0) } }`}</style>
    </div>
  )
}

Component info

CategoryFeedback
Frameworkreact
TierFREE
Views0
Copies0

About

Net Promoter Score widget with 0-10 scale, follow-up reason selector, and response analytics

More from Feedback

'use client'
import { useState } from 'react'

export default function RatingWidget() {
  const [hovered, setHovered] = useState(0)
  const [selected, setSelected] = useState(0)
  const [submitted, setSubmitted] = useState(false)
  const [feedback, s
RatingWidget
Feedback