+ {/* Server Selection */}
+ {servers.length > 0 && (
+
+
+ ({
+ label: server.description || server.url,
+ onClick: () => {
+ setSelectedServer(server)
+ setRequestConfig(prev => ({ ...prev, url: server.url + url }))
+ }
+ }))}
+ className="w-full"
+ />
+
+ )}
+
+ {/* URL Input */}
+
+
+ setRequestConfig(prev => ({ ...prev, url: (e.target as HTMLInputElement).value }))}
+ placeholder="ws://localhost:8080/ws or wss://api.example.com/ws"
+ className="w-full rounded-lg bg-zinc-800 border border-zinc-600 px-3 py-2 text-sm text-white placeholder-zinc-400 focus:border-sky-500 focus:outline-none font-mono"
+ disabled={connection.status === 'connected'}
+ />
+
+
+ {/* Configuration Tabs */}
+
+
+
+ {tabs.map((tab) => (
+
+ classNames(
+ 'px-4 py-3 text-sm font-medium transition border-b-2',
+ selected
+ ? 'border-sky-500 text-sky-400'
+ : 'border-transparent text-zinc-400 hover:text-zinc-300'
+ )
+ }
+ >
+ {tab.name}
+
+ ))}
+
+
+
+ {/* Headers Tab */}
+
+
+
+ β οΈ Note: WebSocket headers are only sent during the initial handshake and cannot be modified after connection.
+
+
+
+
+
+ {/* Protocols Tab */}
+
+
+
+
+
{
+ const protocols = (e.target as HTMLInputElement).value
+ .split(',')
+ .map(p => p.trim())
+ .filter(p => p.length > 0)
+ setRequestConfig(prev => ({ ...prev, protocols }))
+ }}
+ placeholder="chat, v1.0, graphql-ws"
+ className="w-full rounded-lg bg-zinc-800 border border-zinc-600 px-3 py-2 text-sm text-white placeholder-zinc-400 focus:border-sky-500 focus:outline-none"
+ disabled={connection.status === 'connected'}
+ />
+
+ Comma-separated list of WebSocket subprotocols
+
+
+
+
+
+ {/* Messages Tab */}
+
+
+ {/* Message Input */}
+
+
+
+ setMessageType('text') },
+ { label: 'Binary', onClick: () => setMessageType('binary') }
+ ]}
+ className="w-24"
+ />
+
+
+
+
+
+ {/* Message History */}
+
+
+
Message History
+
+
+
+ {messages.length === 0 ? (
+
+ No messages yet. Connect and start sending messages to see them here.
+
+ ) : (
+ messages.map((message) => (
+
+
+
+ {message.type === 'sent' ? 'SENT' :
+ message.type === 'received' ? 'RECEIVED' :
+ message.type === 'connection' ? 'CONNECTION' : 'ERROR'}
+
+
+ {new Date(message.timestamp).toLocaleTimeString()}
+
+ {message.messageType && (
+
+ ({message.messageType})
+
+ )}
+
+
+ {message.content}
+
+
+ ))
+ )}
+
+
+
+
+
+
+
+