rainbow-ai-chatter / index.html
luxopes's picture
Make design more colorful and switching between models move down to prompt field.
5a96ab4 verified
<!doctype html>
<html lang="cs">
<head>
<meta charset="utf-8">
<title>LuxAI Chat</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<link rel="stylesheet" href="style.css">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: {
50: '#f0fdfa',
100: '#ccfbf1',
500: '#10a37f',
600: '#0d9488',
700: '#0f766e',
},
dark: {
800: '#1e293b',
900: '#0f172a',
}
}
}
}
}
</script>
</head>
<body class="bg-gray-50 dark:bg-dark-900 text-gray-900 dark:text-gray-100 h-screen flex flex-col">
<!-- Header -->
<header class="bg-gradient-to-r from-purple-500 to-pink-500 dark:from-purple-700 dark:to-pink-700 h-14 px-4 flex items-center justify-between shadow-lg">
<div class="flex items-center space-x-2">
<div class="w-8 h-8 rounded-full bg-white flex items-center justify-center">
<i data-feather="cpu" class="text-purple-600 w-4 h-4"></i>
</div>
<h1 class="font-bold text-lg text-white">Rainbow AI</h1>
</div>
<button id="newChat" class="flex items-center space-x-1 bg-white/20 hover:bg-white/30 text-white border border-white/30 rounded-lg px-3 py-1.5 text-sm transition-colors backdrop-blur-sm">
<i data-feather="plus" class="w-4 h-4"></i>
<span>Nový chat</span>
</button>
</header>
<!-- Chat Area -->
<main class="flex-1 overflow-y-auto p-4 md:p-6">
<div class="max-w-3xl mx-auto space-y-4" id="chat">
<div class="text-center text-gray-500 dark:text-gray-400 mt-12">
<i data-feather="message-square" class="w-12 h-12 mx-auto mb-4 opacity-30"></i>
<p class="text-lg">Začni nový rozhovor</p>
</div>
</div>
</main>
<!-- Input Area -->
<form id="chatForm" class="bg-gradient-to-r from-blue-500/10 to-purple-500/10 dark:from-blue-700/20 dark:to-purple-700/20 border-t border-gray-200/50 dark:border-gray-700/50 px-4 py-3 backdrop-blur-sm">
<div class="max-w-3xl mx-auto">
<div class="flex items-center gap-2 mb-2">
<select id="modelSelect" class="bg-white/80 dark:bg-dark-800/80 border border-gray-200/50 dark:border-gray-700/50 rounded-lg px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-purple-500 shadow-sm">
<option value="gpt-a">GPT-A</option>
<option value="gpt2">GPT-2</option>
</select>
<div class="text-xs text-gray-500 dark:text-gray-400">Press Shift+Enter for new line</div>
</div>
<div class="flex items-end gap-2">
<div class="flex-1 relative">
<textarea id="input" rows="2" placeholder="Napiš zprávu…"
class="w-full bg-white/80 dark:bg-dark-700/80 border border-gray-200/50 dark:border-gray-600/50 rounded-xl px-4 py-3 pr-10 focus:outline-none focus:ring-2 focus:ring-purple-500 resize-none shadow-sm"></textarea>
<button type="submit" class="absolute right-3 bottom-3 bg-gradient-to-r from-purple-500 to-pink-500 text-white p-1 rounded-full hover:opacity-90 transition-opacity shadow-md">
<i data-feather="arrow-up" class="w-5 h-5"></i>
</button>
</div>
</div>
</div>
</form>
<script>
// Rainbow color animation for empty state icon
function animateRainbowIcon() {
const icon = document.querySelector('.empty i');
if (icon) {
let hue = 0;
setInterval(() => {
hue = (hue + 1) % 360;
icon.style.color = `hsl(${hue}, 100%, 70%)`;
}, 50);
}
}
const MODELS = {
"gpt-a": {
name: "GPT-A",
url: "https://luxopes-gpt-a.hf.space/generate"
},
"gpt2": {
name: "GPT-2",
url: "https://luxopes-gpt2-backend.hf.space/generate"
}
};
let currentModel = "gpt-a";
const chat = document.getElementById("chat");
const input = document.getElementById("input");
const form = document.getElementById("chatForm");
function appendMessage(text, cls, model=null) {
const div = document.createElement("div");
div.className = cls === "user"
? "bg-gradient-to-r from-purple-500 to-pink-500 text-white px-5 py-4 rounded-xl rounded-tr-none max-w-[85%] ml-auto shadow-lg"
: "bg-white/90 dark:bg-dark-700/90 border border-gray-200/50 dark:border-gray-600/50 px-5 py-4 rounded-xl rounded-tl-none max-w-[85%] shadow-lg backdrop-blur-sm";
if (model) {
const modelIndicator = document.createElement("div");
modelIndicator.className = "text-xs text-gray-500 dark:text-gray-400 mb-1";
modelIndicator.textContent = model;
div.appendChild(modelIndicator);
}
const content = document.createElement("div");
content.className = cls === "user" ? "text-white" : "text-gray-800 dark:text-gray-100";
content.textContent = text;
div.appendChild(content);
chat.appendChild(div);
chat.scrollTop = chat.scrollHeight;
document.querySelector(".empty")?.remove();
return div;
}
form.addEventListener("submit", async e => {
e.preventDefault();
const msg = input.value.trim();
if (!msg) return;
appendMessage(msg, "user");
input.value = "";
input.disabled = true;
const bot = appendMessage(
`${MODELS[currentModel].name} přemýšlí…`,
"bot",
MODELS[currentModel].name
);
bot.classList.add("opacity-80");
try {
const res = await fetch(MODELS[currentModel].url, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ user_input: msg, model: currentModel })
});
const data = await res.json();
bot.classList.remove("opacity-80");
bot.lastChild.textContent = data.response || "Chyba odpovědi";
} catch (e) {
bot.classList.remove("opacity-80");
bot.lastChild.textContent = "Chyba připojení";
}
input.disabled = false;
input.focus();
});
document.getElementById("modelSelect").onchange = e => {
currentModel = e.target.value;
appendMessage(`Přepnuto na ${MODELS[currentModel].name}`, "bot", "System");
};
document.getElementById("newChat").onclick = () => {
chat.innerHTML = `
<div class="text-center text-gray-500 dark:text-gray-400 mt-12">
<i data-feather="message-square" class="w-12 h-12 mx-auto mb-4 opacity-30"></i>
<p class="text-lg">Začni nový rozhovor</p>
</div>
`;
feather.replace();
input.focus();
};
input.addEventListener("keydown", e => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
form.requestSubmit();
}
});
feather.replace();
animateRainbowIcon();
</script>
<script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
</body>
</html>