herrkobold's picture
the buttons need to be visible always for any selected message
9fa6281 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vaporwave LLM Chat</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
vaporPink: '#ff6ad5',
vaporTeal: '#00ffcc',
vaporPurple: '#9d00ff',
},
fontFamily: {
sans: ['Courier New', 'monospace'],
},
backgroundImage: {
'vapor-bg': "url('http://static.photos/abstract/1200x630/42')",
}
}
}
}
</script>
<style>
@keyframes scanline {
0% { transform: translateY(-100%); }
100% { transform: translateY(100%); }
}
.scanlines {
position: relative;
overflow: hidden;
}
.scanlines::after {
content: "";
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: linear-gradient(
to bottom,
rgba(255,255,255,0) 0%,
rgba(255,255,255,0.05) 50%,
rgba(255,255,255,0) 100%
);
background-size: 100% 4px;
animation: scanline 5s linear infinite;
pointer-events: none;
}
</style>
</head>
<body class="bg-black text-white font-sans scanlines">
<div class="min-h-screen flex flex-col" style="background: linear-gradient(135deg, #000000 0%, #1e0033 100%)">
<div class="container mx-auto px-4 py-8 flex-1 flex flex-col">
<header class="mb-8 text-center">
<h1 class="text-5xl font-bold text-transparent bg-clip-text bg-gradient-to-r from-vaporTeal to-vaporPink mb-2">
MACINTOSH PLUS
</h1>
<p class="text-vaporTeal">LLM CHAT INTERFACE</p>
</header>
<div class="flex-1 flex flex-col bg-black bg-opacity-70 border-2 border-vaporPurple rounded-lg p-4 mb-6">
<div id="chat-container" class="flex-1 overflow-y-auto mb-4 font-mono text-sm">
<div class="text-vaporTeal">SYSTEM: Ready for input</div>
</div>
<div class="flex items-center border-t-2 border-vaporPink pt-4">
<input
id="api-key"
type="password"
placeholder="Enter API Key..."
class="flex-1 bg-black border-2 border-vaporTeal text-white px-4 py-2 mr-2 focus:outline-none focus:border-vaporPink"
>
<input
id="user-input"
type="text"
placeholder="Type your message..."
class="flex-1 bg-black border-2 border-vaporTeal text-white px-4 py-2 mr-2 focus:outline-none focus:border-vaporPink"
>
<button
id="send-btn"
class="bg-vaporPurple hover:bg-vaporPink text-white font-bold py-2 px-6 transition-all duration-300"
>
SEND
</button>
</div>
</div>
<div class="text-center text-vaporTeal text-xs">
<p>Floral Shoppe aesthetic interface for LLM communication</p>
<p class="text-vaporPink mt-1">Using OpenAI GPT-3.5 Turbo API</p>
</div>
</div>
</div>
<script>
let selectedMessageId = null;
const messages = [];
function renderMessages() {
const chatContainer = document.getElementById('chat-container');
chatContainer.innerHTML = '';
messages.forEach((msg, idx) => {
const msgDiv = document.createElement('div');
msgDiv.id = `msg-${idx}`;
msgDiv.className = `mb-2 ${msg.role === 'user' ? 'text-vaporPink' : 'text-vaporTeal'} relative group`;
const msgContent = document.createElement('div');
msgContent.textContent = `${msg.role === 'user' ? 'YOU:' : 'AI:'} ${msg.content}`;
msgDiv.appendChild(msgContent);
if (msg.role !== 'system') {
const btnContainer = document.createElement('div');
btnContainer.className = 'absolute right-0 top-0 opacity-100 flex gap-1 bg-black bg-opacity-70 p-1 rounded';
const branchBtn = document.createElement('button');
branchBtn.className = 'bg-vaporPurple hover:bg-vaporPink text-white text-xs px-2 py-1';
branchBtn.textContent = 'Branch';
branchBtn.addEventListener('click', (e) => {
e.stopPropagation();
document.getElementById('user-input').value = msg.content;
});
const editBtn = document.createElement('button');
editBtn.className = 'bg-vaporPurple hover:bg-vaporPink text-white text-xs px-2 py-1';
editBtn.textContent = 'Edit';
editBtn.addEventListener('click', (e) => {
e.stopPropagation();
const newContent = prompt('Edit message:', msg.content);
if (newContent !== null) {
msg.content = newContent;
renderMessages();
}
});
const deleteBtn = document.createElement('button');
deleteBtn.className = 'bg-vaporPurple hover:bg-vaporPink text-white text-xs px-2 py-1';
deleteBtn.textContent = 'Delete';
deleteBtn.addEventListener('click', (e) => {
e.stopPropagation();
if (confirm('Delete this message?')) {
messages.splice(idx, 1);
renderMessages();
}
});
btnContainer.appendChild(branchBtn);
btnContainer.appendChild(editBtn);
btnContainer.appendChild(deleteBtn);
msgDiv.appendChild(btnContainer);
}
msgDiv.addEventListener('click', () => {
document.querySelectorAll('.selected').forEach(el => el.classList.remove('selected'));
msgDiv.classList.add('selected');
selectedMessageId = idx;
});
chatContainer.appendChild(msgDiv);
});
}
document.getElementById('send-btn').addEventListener('click', async () => {
const apiKey = document.getElementById('api-key').value;
const userInput = document.getElementById('user-input').value;
const chatContainer = document.getElementById('chat-container');
if (!apiKey || !userInput) return;
// Add user message
messages.push({ role: 'user', content: userInput });
renderMessages();
messages.push({ role: 'system', content: 'Processing...' });
renderMessages();
document.getElementById('user-input').value = '';
try {
// This would be replaced with actual API call to the LLM provider
const response = await fetch('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
model: "gpt-3.5-turbo",
messages: [{"role": "user", "content": userInput}],
temperature: 0.7
})
});
const data = await response.json();
messages.pop(); // Remove processing message
messages.push({ role: 'ai', content: data.choices[0].message.content });
renderMessages();
} catch (error) {
messages.pop(); // Remove processing message
messages.push({ role: 'system', content: `ERROR: ${error.message}` });
renderMessages();
}
});
// Add some initial messages
messages.push(
{ role: 'system', content: 'Ready for input' },
{ role: 'ai', content: 'Welcome to the vaporwave chat interface! Try branching, editing or deleting messages.' }
);
renderMessages();
</script>
<style>
.selected {
border-left: 3px solid #ff6ad5;
padding-left: 5px;
background-color: rgba(157, 0, 255, 0.1);
}
#chat-container div:hover {
background-color: rgba(157, 0, 255, 0.05);
}
</style>
</body>
</html>