โ† Components/Communication

VideoCallUI

videocallui-1779379195861.tsx
'use client'
import { useState } from 'react'

const PARTICIPANTS = [
  { id: 1, name: 'You', initials: 'ME', color: '#C9A84C', muted: false, camera: true, speaking: true },
  { id: 2, name: 'Sarah Chen', initials: 'SC', color: '#6366f1', muted: false, camera: true, speaking: false },
  { id: 3, name: 'Marcus Williams', initials: 'MW', color: '#22c55e', muted: true, camera: false, speaking: false },
  { id: 4, name: 'Priya Patel', initials: 'PP', color: '#ec4899', muted: false, camera: true, speaking: false },
]

export default function VideoCallUI() {
  const [muted, setMuted] = useState(false)
  const [camera, setCamera] = useState(true)
  const [sharing, setSharing] = useState(false)
  const [hand, setHand] = useState(false)
  const [ended, setEnded] = useState(false)

  if (ended) return (
    <div style={{ background: '#0A0A0A', padding: 40, display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: 360 }}>
      <div style={{ textAlign: 'center' }}>
        <div style={{ fontSize: 48, marginBottom: 12 }}>๐Ÿ‘‹</div>
        <div style={{ color: '#F5F5F0', fontSize: 20, fontWeight: 700, marginBottom: 8 }}>Meeting ended</div>
        <div style={{ color: 'rgba(255,255,255,0.4)', fontSize: 13, marginBottom: 20 }}>Duration: 48:32</div>
        <button onClick={() => setEnded(false)} style={{ background: '#22c55e', color: '#0A0A0A', border: 'none', borderRadius: 8, padding: '10px 24px', fontWeight: 700, cursor: 'pointer', fontSize: 14 }}>Rejoin</button>
      </div>
    </div>
  )

  return (
    <div style={{ background: '#0A0A0A', padding: 20, display: 'flex', flexDirection: 'column', gap: 16, minHeight: 360 }}>
      {/* Participant grid */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 8, flex: 1 }}>
        {PARTICIPANTS.map(p => (
          <div key={p.id} style={{ position: 'relative', background: p.camera ? p.color + '15' : '#111', border: `2px solid ${p.speaking ? p.color : 'rgba(255,255,255,0.06)'}`, borderRadius: 12, minHeight: 120, display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'border-color 0.3s', overflow: 'hidden' }}>
            {!p.camera && (
              <div style={{ width: 52, height: 52, borderRadius: '50%', background: p.color, display: 'flex', alignItems: 'center', justifyContent: 'center', color: '#0A0A0A', fontWeight: 800, fontSize: 18 }}>{p.initials}</div>
            )}
            {p.camera && (
              <div style={{ inset: 0, position: 'absolute', background: `linear-gradient(135deg, ${p.color}20, transparent)`, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                <span style={{ color: 'rgba(255,255,255,0.1)', fontSize: 40 }}>๐Ÿ“น</span>
              </div>
            )}
            <div style={{ position: 'absolute', bottom: 8, left: 10, display: 'flex', alignItems: 'center', gap: 6 }}>
              <span style={{ color: '#fff', fontSize: 11, fontWeight: 600, background: 'rgba(0,0,0,0.6)', borderRadius: 4, padding: '1px 6px' }}>{p.id === 1 ? (muted ? '๐Ÿ”‡' : '') : (p.muted ? '๐Ÿ”‡' : '')}{p.name}</span>
            </div>
            {p.speaking && <div style={{ position: 'absolute', inset: -2, borderRadius: 12, border: `2px solid ${p.color}`, animation: 'pulse 1.5s infinite', pointerEvents: 'none' }} />}
          </div>
        ))}
      </div>

      {/* Controls */}
      <div style={{ display: 'flex', gap: 10, justifyContent: 'center', alignItems: 'center' }}>
        {[
          { label: muted ? '๐Ÿ”‡' : '๐ŸŽค', active: !muted, onClick: () => setMuted(m => !m), tip: muted ? 'Unmute' : 'Mute' },
          { label: camera ? '๐Ÿ“น' : '๐Ÿ“ท', active: camera, onClick: () => setCamera(c => !c), tip: camera ? 'Stop video' : 'Start video' },
          { label: '๐Ÿ–ฅ', active: sharing, onClick: () => setSharing(s => !s), tip: sharing ? 'Stop share' : 'Share screen' },
          { label: 'โœ‹', active: hand, onClick: () => setHand(h => !h), tip: hand ? 'Lower hand' : 'Raise hand' },
        ].map(btn => (
          <button key={btn.tip} onClick={btn.onClick} title={btn.tip} style={{ width: 44, height: 44, borderRadius: '50%', border: '1px solid rgba(255,255,255,0.12)', background: btn.active ? 'rgba(255,255,255,0.1)' : 'rgba(239,68,68,0.15)', cursor: 'pointer', fontSize: 18, display: 'flex', alignItems: 'center', justifyContent: 'center', transition: 'all 0.2s' }}>
            {btn.label}
          </button>
        ))}
        <button onClick={() => setEnded(true)} style={{ background: '#ef4444', border: 'none', color: '#fff', borderRadius: 22, padding: '11px 24px', cursor: 'pointer', fontWeight: 700, fontSize: 14, marginLeft: 8 }}>Leave</button>
      </div>

      <div style={{ textAlign: 'center', color: 'rgba(255,255,255,0.25)', fontSize: 12 }}>
        {PARTICIPANTS.length} participants ยท 48:32
      </div>
      <style>{`@keyframes pulse { 0%,100% { opacity:0.6 } 50% { opacity:1 } }`}</style>
    </div>
  )
}

Component info

CategoryCommunication
Frameworkreact
TierFREE
Views0
Copies0

About

Video call interface mockup with participant grid, controls bar, mute/camera/share toggles