← Components/Feedback

RatingWidget

ratingwidget-1779378817747.tsx
'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, setFeedback] = useState('')

  const LABELS = ['', 'Poor', 'Fair', 'Good', 'Great', 'Excellent']
  const active = hovered || selected

  function submit() {
    if (!selected) return
    setSubmitted(true)
  }

  if (submitted) return (
    <div style={{ padding: 40, background: '#0A0A0A', display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 220 }}>
      <div style={{ textAlign: 'center', animation: 'popIn 0.4s ease' }}>
        <div style={{ fontSize: 48, marginBottom: 12 }}>🎉</div>
        <div style={{ color: '#F5F5F0', fontSize: 18, fontWeight: 700, marginBottom: 6 }}>Thanks for your feedback!</div>
        <div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 13 }}>You rated this {selected}/5 stars</div>
        <button onClick={() => { setSubmitted(false); setSelected(0); setFeedback('') }} style={{ marginTop: 16, 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 }}>Rate again</button>
      </div>
      <style>{`@keyframes popIn { from { opacity:0; transform:scale(0.8) } to { opacity:1; transform:scale(1) } }`}</style>
    </div>
  )

  return (
    <div style={{ padding: 40, background: '#0A0A0A', display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 24, minHeight: 260 }}>
      <div style={{ textAlign: 'center' }}>
        <div style={{ color: '#F5F5F0', fontSize: 18, fontWeight: 700, marginBottom: 6 }}>Rate this component</div>
        <div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 13 }}>Your feedback helps us improve Empire UI</div>
      </div>

      <div style={{ display: 'flex', gap: 8 }}>
        {[1, 2, 3, 4, 5].map(n => (
          <button key={n}
            onMouseEnter={() => setHovered(n)}
            onMouseLeave={() => setHovered(0)}
            onClick={() => setSelected(n)}
            style={{ background: 'none', border: 'none', cursor: 'pointer', padding: 4, transition: 'transform 0.15s' }}>
            <svg width="32" height="32" viewBox="0 0 32 32">
              <polygon points="16,3 19.9,12.3 30,13.1 22.4,19.7 24.7,29.5 16,24.3 7.3,29.5 9.6,19.7 2,13.1 12.1,12.3"
                fill={n <= active ? '#C9A84C' : 'none'}
                stroke={n <= active ? '#C9A84C' : 'rgba(255,255,255,0.2)'}
                strokeWidth="1.5"
                style={{ transition: 'all 0.15s', filter: n <= active ? 'drop-shadow(0 0 6px rgba(201,168,76,0.5))' : 'none' }}
              />
            </svg>
          </button>
        ))}
      </div>

      <div style={{ height: 20, color: active ? '#C9A84C' : 'transparent', fontSize: 14, fontWeight: 600, transition: 'color 0.2s' }}>
        {LABELS[active]}
      </div>

      {selected > 0 && (
        <div style={{ width: 300, animation: 'fadeIn 0.3s ease' }}>
          <textarea value={feedback} onChange={e => setFeedback(e.target.value)} placeholder="Tell us more (optional)..."
            style={{ width: '100%', boxSizing: 'border-box', background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: 10, color: '#F5F5F0', fontSize: 13, padding: '10px 14px', resize: 'none', height: 72, outline: 'none' }} />
          <button onClick={submit} style={{ marginTop: 10, width: '100%', background: '#C9A84C', color: '#0A0A0A', border: 'none', borderRadius: 8, padding: '11px', fontWeight: 700, cursor: 'pointer', fontSize: 14 }}>
            Submit rating
          </button>
        </div>
      )}
      <style>{`@keyframes fadeIn { from { opacity:0; transform:translateY(6px) } to { opacity:1; transform:translateY(0) } }`}</style>
    </div>
  )
}

Component info

CategoryFeedback
Frameworkreact
TierFREE
Views0
Copies0

About

Star rating widget with hover preview, fractional display, label scale, and animated feedback

More from Feedback

'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 
NPSWidget
Feedback