Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Nexus AI - Modern Chat Interface</title> | |
| <!-- Importing Remix Icons for modern iconography --> | |
| <script src="https://unpkg.com/@remixicon/remixicon@2.9.0/icons/remixicon.js"></script> | |
| <!-- Google Fonts: Inter for clean UI --> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <style> | |
| /* --- CSS VARIABLES & RESET --- */ | |
| :root { | |
| --bg-dark: #0f0f13; | |
| --bg-panel: #1a1a24; | |
| --bg-input: #252530; | |
| --primary: #6c5ce7; | |
| --primary-glow: #6c5ce7aa; | |
| --accent: #00cec9; | |
| --text-main: #ffffff; | |
| --text-muted: #a0a0b0; | |
| --border: rgba(255, 255, 255, 0.1); | |
| --glass: rgba(255, 255, 255, 0.05); | |
| --glass-border: rgba(255, 255, 255, 0.08); | |
| --shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.37); | |
| --transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1); | |
| } | |
| * { | |
| box-sizing: border-box; | |
| margin: 0; | |
| padding: 0; | |
| font-family: 'Inter', sans-serif; | |
| } | |
| body { | |
| background-color: var(--bg-dark); | |
| color: var(--text-main); | |
| height: 100vh; | |
| overflow: hidden; | |
| display: flex; | |
| /* Animated Background Gradient */ | |
| background: radial-gradient(circle at 50% 50%, #1a1a2e 0%, #0f0f13 100%); | |
| } | |
| /* --- LAYOUT --- */ | |
| .app-container { | |
| display: flex; | |
| width: 100%; | |
| height: 100%; | |
| position: relative; | |
| } | |
| /* --- SIDEBAR --- */ | |
| .sidebar { | |
| width: 280px; | |
| background: var(--bg-panel); | |
| border-right: 1px solid var(--border); | |
| display: flex; | |
| flex-direction: column; | |
| padding: 20px; | |
| transition: var(--transition); | |
| z-index: 10; | |
| } | |
| .brand { | |
| font-size: 1.2rem; | |
| font-weight: 700; | |
| color: var(--text-main); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| margin-bottom: 30px; | |
| letter-spacing: -0.5px; | |
| } | |
| .brand i { | |
| color: var(--primary); | |
| font-size: 1.5rem; | |
| } | |
| .new-chat-btn { | |
| background: linear-gradient(135deg, var(--primary), #8e44ad); | |
| color: white; | |
| border: none; | |
| padding: 12px; | |
| border-radius: 8px; | |
| font-weight: 600; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| gap: 8px; | |
| transition: var(--transition); | |
| box-shadow: 0 4px 15px rgba(108, 118, 232, 0.4); | |
| } | |
| .new-chat-btn:hover { | |
| transform: translateY(-2px); | |
| box-shadow: 0 6px 20px rgba(108, 118, 232, 0.6); | |
| } | |
| .history-label { | |
| color: var(--text-muted); | |
| font-size: 0.85rem; | |
| margin-top: 25px; | |
| margin-bottom: 10px; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| } | |
| .history-list { | |
| flex-grow: 1; | |
| overflow-y: auto; | |
| } | |
| .history-item { | |
| padding: 10px; | |
| border-radius: 6px; | |
| color: var(--text-muted); | |
| cursor: pointer; | |
| transition: var(--transition); | |
| display: flex; | |
| align-items: center; | |
| gap: 10px; | |
| font-size: 0.9rem; | |
| white-space: nowrap; | |
| overflow: hidden; | |
| text-overflow: ellipsis; | |
| } | |
| .history-item:hover { | |
| background: var(--glass); | |
| color: var(--text-main); | |
| } | |
| /* --- MAIN CHAT AREA --- */ | |
| .chat-area { | |
| flex-grow: 1; | |
| display: flex; | |
| flex-direction: column; | |
| position: relative; | |
| background: transparent; | |
| } | |
| /* Header */ | |
| .chat-header { | |
| padding: 20px; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| border-bottom: 1px solid var(--border); | |
| background: rgba(15, 15, 19, 0.8); | |
| backdrop-filter: blur(10px); | |
| } | |
| .chat-title { | |
| font-weight: 600; | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| } | |
| .status-dot { | |
| width: 8px; | |
| height: 8px; | |
| background: var(--accent); | |
| border-radius: 50%; | |
| box-shadow: 0 0 10px var(--accent); | |
| animation: pulse 2s infinite; | |
| } | |
| /* Messages Container */ | |
| .messages-container { | |
| flex-grow: 1; | |
| padding: 20px 40px; | |
| overflow-y: auto; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 20px; | |
| scroll-behavior: smooth; | |
| } | |
| /* Message Bubbles */ | |
| .message { | |
| display: flex; | |
| gap: 15px; | |
| max-width: 800px; | |
| animation: slideIn 0.4s ease forwards; | |
| opacity: 0; | |
| transform: translateY(10px); | |
| } | |
| @keyframes slideIn { | |
| to { opacity: 1; transform: translateY(0); } | |
| } | |
| @keyframes pulse { | |
| 0% { opacity: 1; } | |
| 50% { opacity: 0.5; } | |
| 100% { opacity: 1; } | |
| } | |
| .message.user { | |
| flex-direction: row-reverse; | |
| } | |
| .avatar { | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 12px; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-size: 1.2rem; | |
| flex-shrink: 0; | |
| } | |
| .avatar.bot { | |
| background: linear-gradient(135deg, #2d343f, #1a1a24); | |
| border: 1px solid var(--border); | |
| color: var(--primary); | |
| } | |
| .avatar.user { | |
| background: var(--primary); | |
| color: white; | |
| box-shadow: 0 4px 10px rgba(108, 118, 232, 0.3); | |
| } | |
| .message-content { | |
| background: var(--bg-panel); | |
| padding: 15px 20px; | |
| border-radius: 12px; | |
| border: 1px solid var(--border); | |
| line-height: 1.6; | |
| font-size: 0.95rem; | |
| position: relative; | |
| max-width: 70%; | |
| } | |
| .message.user .message-content { | |
| background: rgba(108, 118, 232, 0.1); | |
| border: 1px solid rgba(108, 118, 232, 0.2); | |
| color: #e0e0ff; | |
| } | |
| /* Input Area */ | |
| .input-area { | |
| padding: 20px 40px; | |
| background: rgba(15, 15, 19, 0.9); | |
| backdrop-filter: blur(10px); | |
| border-top: 1px solid var(--border); | |
| display: flex; | |
| align-items: center; | |
| gap: 15px; | |
| } | |
| .input-wrapper { | |
| flex-grow: 1; | |
| position: relative; | |
| background: var(--bg-input); | |
| border-radius: 14px; | |
| border: 1px solid var(--border); | |
| transition: var(--transition); | |
| display: flex; | |
| align-items: center; | |
| padding: 5px; | |
| } | |
| .input-wrapper:focus-within { | |
| border-color: var(--primary); | |
| box-shadow: 0 0 15px rgba(108, 118, 232, 0.15); | |
| } | |
| #chat-input { | |
| width: 100%; | |
| background: transparent; | |
| border: none; | |
| padding: 12px 15px; | |
| color: var(--text-main); | |
| font-size: 1rem; | |
| outline: none; | |
| } | |
| .send-btn { | |
| background: var(--primary); | |
| color: white; | |
| border: none; | |
| width: 40px; | |
| height: 40px; | |
| border-radius: 10px; | |
| cursor: pointer; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| transition: var(--transition); | |
| } | |
| .send-btn:hover { | |
| background: #7d69f0; | |
| transform: scale(1.05); | |
| } | |
| .send-btn:disabled { | |
| background: var(--bg-input); | |
| color: var(--text-muted); | |
| cursor: not-allowed; | |
| transform: none; | |
| } | |
| /* Typing Indicator */ | |
| .typing-indicator { | |
| display: flex; | |
| gap: 4px; | |
| padding: 5px 0; | |
| } | |
| .dot { | |
| width: 6px; | |
| height: 6px; | |
| background: var(--text-muted); | |
| border-radius: 50%; | |
| animation: typing 1.4s infinite ease-in-out both; | |
| } | |
| .dot:nth-child(1) { animation-delay: -0.32s; } | |
| .dot:nth-child(2) { animation-delay: -0.16s; } | |
| @keyframes typing { | |
| 0%, 80%, 100% { transform: scale(0); } | |
| 40% { transform: scale(1); } | |
| } | |
| /* --- RESPONSIVE --- */ | |
| .mobile-menu-btn { | |
| display: none; | |
| background: none; | |
| border: none; | |
| color: var(--text-main); | |
| cursor: pointer; | |
| font-size: 1.5rem; | |
| } | |
| @media (max-width: 768px) { | |
| .sidebar { | |
| position: absolute; | |
| left: -280px; | |
| height: 100%; | |
| box-shadow: 10px 0 30px rgba(0,0,0,0.5); | |
| } | |
| .sidebar.active { | |
| left: 0; | |
| } | |
| .mobile-menu-btn { | |
| display: block; | |
| } | |
| .messages-container { | |
| padding: 15px; | |
| } | |
| .input-area { | |
| padding: 15px; | |
| } | |
| .message-content { | |
| max-width: 85%; | |
| } | |
| } | |
| /* --- ANYCODER LINK --- */ | |
| .anycoder-badge { | |
| margin-top: auto; | |
| border-top: 1px solid var(--border); | |
| padding-top: 15px; | |
| } | |
| .anycoder-link { | |
| display: flex; | |
| align-items: center; | |
| gap: 8px; | |
| text-decoration: none; | |
| color: var(--text-muted); | |
| font-size: 0.85rem; | |
| transition: var(--transition); | |
| padding: 8px; | |
| border-radius: 6px; | |
| } | |
| .anycoder-link:hover { | |
| color: var(--primary); | |
| background: var(--glass); | |
| } | |
| /* Scrollbar Styling */ | |
| ::-webkit-scrollbar { | |
| width: 8px; | |
| } | |
| ::-webkit-scrollbar-track { | |
| background: transparent; | |
| } | |
| ::-webkit-scrollbar-thumb { | |
| background: var(--bg-input); | |
| border-radius: 4px; | |
| } | |
| ::-webkit-scrollbar-thumb:hover { | |
| background: var(--primary); | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="app-container"> | |
| <!-- Sidebar --> | |
| <aside class="sidebar" id="sidebar"> | |
| <div class="brand"> | |
| <i class="ri-robot-2-fill"></i> | |
| Nexus AI | |
| </div> | |
| <button class="new-chat-btn" onclick="resetChat()"> | |
| <i class="ri-add-line"></i> New Chat | |
| </button> | |
| <div class="history-label">Recent Conversations</div> | |
| <div class="history-list"> | |
| <div class="history-item"> | |
| <i class="ri-message-3-line"></i> | |
| <span>Project Alpha Ideas</span> | |
| </div> | |
| <div class="history-item"> | |
| <i class="ri-message-3-line"></i> | |
| <span>Coding Help: React</span> | |
| </div> | |
| <div class="history-item"> | |
| <i class="ri-message-3-line"></i> | |
| <span>Daily Standup Summary</span> | |
| </div> | |
| </div> | |
| <div class="anycoder-badge"> | |
| <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" class="anycoder-link"> | |
| <i class="ri-code-s-slash-line"></i> | |
| Built with anycoder | |
| </a> | |
| </div> | |
| </aside> | |
| <!-- Main Chat --> | |
| <main class="chat-area"> | |
| <div class="chat-header"> | |
| <div style="display: flex; align-items: center; gap: 10px;"> | |
| <button class="mobile-menu-btn" onclick="toggleSidebar()"> | |
| <i class="ri-menu-line"></i> | |
| </button> | |
| <div class="chat-title"> | |
| <div class="status-dot"></div> | |
| Nexus Core v2.0 | |
| </div> | |
| </div> | |
| <div style="color: var(--text-muted); font-size: 0.9rem;"> | |
| <i class="ri-settings-4-line"></i> | |
| </div> | |
| </div> | |
| <div class="messages-container" id="messages"> | |
| <!-- Welcome Message --> | |
| <div class="message bot"> | |
| <div class="avatar bot"> | |
| <i class="ri-robot-2-fill"></i> | |
| </div> | |
| <div class="message-content"> | |
| Hello! I'm Nexus. I can help you with coding, creative writing, or general analysis. How can I assist you today? | |
| </div> | |
| </div> | |
| </div> | |
| <div class="input-area"> | |
| <div class="input-wrapper"> | |
| <input type="text" id="chat-input" placeholder="Type your message..." autocomplete="off"> | |
| </div> | |
| <button class="send-btn" id="send-btn" onclick="sendMessage()"> | |
| <i class="ri-arrow-right-line"></i> | |
| </button> | |
| </div> | |
| </main> | |
| </div> | |
| <script> | |
| const messagesContainer = document.getElementById('messages'); | |
| const chatInput = document.getElementById('chat-input'); | |
| const sendBtn = document.getElementById('send-btn'); | |
| const sidebar = document.getElementById('sidebar'); | |
| // Toggle Sidebar on Mobile | |
| function toggleSidebar() { | |
| sidebar.classList.toggle('active'); | |
| } | |
| // Reset Chat | |
| function resetChat() { | |
| messagesContainer.innerHTML = ''; | |
| // Add initial message again | |
| addMessage("Hello! I'm Nexus. Ready to work.", 'bot'); | |
| if(window.innerWidth <= 768) sidebar.classList.remove('active'); | |
| } | |
| // Add Message to UI | |
| function addMessage(text, type) { | |
| const msgDiv = document.createElement('div'); | |
| msgDiv.classList.add('message', type); | |
| const avatarDiv = document.createElement('div'); | |
| avatarDiv.classList.add('avatar', type); | |
| if(type === 'bot') { | |
| avatarDiv.innerHTML = '<i class="ri-robot-2-fill"></i>'; | |
| } else { | |
| avatarDiv.innerHTML = '<i class="ri-user-smile-line"></i>'; | |
| } | |
| const contentDiv = document.createElement('div'); | |
| contentDiv.classList.add('message-content'); | |
| contentDiv.textContent = text; | |
| msgDiv.appendChild(avatarDiv); | |
| msgDiv.appendChild(contentDiv); | |
| messagesContainer.appendChild(msgDiv); | |
| // Auto scroll to bottom | |
| messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
| } | |
| // Show Typing Indicator | |
| function showTypingIndicator() { | |
| const id = 'typing-' + Date.now(); | |
| const msgDiv = document.createElement('div'); | |
| msgDiv.classList.add('message', 'bot'); | |
| msgDiv.id = id; | |
| const avatarDiv = document.createElement('div'); | |
| avatarDiv.classList.add('avatar', 'bot'); | |
| avatarDiv.innerHTML = '<i class="ri-robot-2-fill"></i>'; | |
| const contentDiv = document.createElement('div'); | |
| contentDiv.classList.add('message-content'); | |
| contentDiv.style.padding = '10px 20px'; // smaller padding for dots | |
| const dots = ` | |
| <div class="typing-indicator"> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| <div class="dot"></div> | |
| </div> | |
| `; | |
| contentDiv.innerHTML = dots; | |
| msgDiv.appendChild(avatarDiv); | |
| msgDiv.appendChild(contentDiv); | |
| messagesContainer.appendChild(msgDiv); | |
| messagesContainer.scrollTop = messagesContainer.scrollHeight; | |
| return id; | |
| } | |
| // Remove Typing Indicator | |
| function removeTypingIndicator(id) { | |
| const element = document.getElementById(id); | |
| if(element) element.remove(); | |
| } | |
| // Mock AI Response Logic | |
| function getBotResponse(input) { | |
| const lowerInput = input.toLowerCase(); | |
| if(lowerInput.includes('hello') || lowerInput.includes('hi')) return "Greetings! How are you doing today?"; | |
| if(lowerInput.includes('code') || lowerInput.includes('html')) return "I can certainly help with code. Here is a snippet:\n\nconst hello = 'world';\nconsole.log(hello);"; | |
| if(lowerInput.includes('anycoder')) return "Built with anycoder is a great tool! It helps generate code efficiently."; | |
| if(lowerInput.includes('weather')) return "I don't have real-time access to weather data, but it looks sunny in the digital world!"; | |
| if(lowerInput.includes('thanks')) return "You're welcome! Feel free to ask anything else."; | |
| return "That's interesting! Tell me more about that, or ask me to generate some code."; | |
| } | |
| // Handle Send | |
| function sendMessage() { | |
| const text = chatInput.value.trim(); | |
| if(!text) return; | |
| // Add User Message | |
| addMessage(text, 'user'); | |
| chatInput.value = ''; | |
| // Disable button temporarily | |
| sendBtn.disabled = true; | |
| // Simulate AI Delay | |
| const typingId = showTypingIndicator(); | |
| setTimeout(() => { | |
| removeTypingIndicator(typingId); | |
| const response = getBotResponse(text); | |
| addMessage(response, 'bot'); | |
| sendBtn.disabled = false; | |
| }, 1500 + Math.random() * 1000); // Random delay between 1.5s and 2.5s | |
| } | |
| // Enter key to send | |
| chatInput.addEventListener('keypress', (e) => { | |
| if(e.key === 'Enter') { | |
| sendMessage(); | |
| } | |
| }); | |
| </script> | |
| </body> | |
| </html> |