From 7eafb03db60c773fd5a90043e6b88d35b0c39be6 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 4 Feb 2026 18:32:02 +0000 Subject: [PATCH 1/2] add Nova AI chat interface Creates a modern AI chat page similar to Grok with: - Clean dark-themed chat interface - Message bubbles for user/AI conversations - Typing indicator animation - Welcome screen with capabilities - Suggestion chips for quick prompts - Responsive design for mobile https://claude.ai/code/session_01U1LSbfDLcfwKakJQjtASFU --- docusaurus.config.js | 15 +- src/pages/ai.js | 263 +++++++++++++++++++++ src/pages/ai.module.css | 504 ++++++++++++++++++++++++++++++++++++++++ static/img/nova-ai.svg | 12 + 4 files changed, 789 insertions(+), 5 deletions(-) create mode 100644 src/pages/ai.js create mode 100644 src/pages/ai.module.css create mode 100644 static/img/nova-ai.svg diff --git a/docusaurus.config.js b/docusaurus.config.js index 0f17184..ad955b3 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -20,6 +20,11 @@ module.exports = { src: 'img/logo.svg', }, items: [ + { + to: 'ai', + label: 'Nova AI', + position: 'left', + }, { to: 'docs/', activeBasePath: 'docs', @@ -42,8 +47,12 @@ module.exports = { style: 'dark', links: [ { - title: 'Docs', + title: 'Products', items: [ + { + label: 'Nova AI', + to: 'ai', + }, { label: 'The Basics', to: 'docs/', @@ -52,10 +61,6 @@ module.exports = { label: 'Custom Domains', to: 'docs/custom-domains', }, - { - label: 'Command Line Interface', - to: 'docs/cli', - }, ], }, { diff --git a/src/pages/ai.js b/src/pages/ai.js new file mode 100644 index 0000000..72fdd86 --- /dev/null +++ b/src/pages/ai.js @@ -0,0 +1,263 @@ +import React, { useState, useRef, useEffect } from 'react'; +import Layout from '@theme/Layout'; +import styles from './ai.module.css'; + +const DEMO_RESPONSES = [ + "That's a great question! Let me think about that for a moment...\n\nBased on my analysis, I'd say the key factors to consider here are context, clarity, and creativity. Would you like me to elaborate on any of these?", + "I'm here to help! From what you've described, there are several approaches we could take:\n\n1. Start with the fundamentals\n2. Build incrementally\n3. Test and iterate\n\nWhich direction interests you most?", + "Interesting perspective! I appreciate you sharing that.\n\nHere's my take: the best solutions often come from combining different viewpoints. Let me know if you'd like to explore this further.", + "I've analyzed your request and here's what I found:\n\n**Key Insights:**\n- The core concept is solid\n- There's room for optimization\n- Consider edge cases\n\nWould you like me to dive deeper into any of these areas?", + "Great to chat with you! I'm designed to assist with a wide range of topics.\n\nFeel free to ask me about:\n- Technical questions\n- Creative projects\n- Problem-solving\n- General knowledge\n\nWhat's on your mind?", +]; + +function formatTime(date) { + return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }); +} + +function Message({ message, isUser }) { + return ( +
+
+ {isUser ? ( + + + + ) : ( + + + + )} +
+
+
+ {isUser ? 'You' : 'Nova AI'} + {formatTime(message.timestamp)} +
+
+ {message.text.split('\n').map((line, i) => ( + + {line.startsWith('**') && line.endsWith('**') ? ( + {line.slice(2, -2)} + ) : line.startsWith('- ') ? ( +
{line}
+ ) : line.match(/^\d+\./) ? ( +
{line}
+ ) : ( + line + )} + {i < message.text.split('\n').length - 1 &&
} +
+ ))} +
+
+
+ ); +} + +function TypingIndicator() { + return ( +
+
+ + + +
+
+
+ + + +
+
+
+ ); +} + +function SuggestionChip({ text, onClick }) { + return ( + + ); +} + +function AI() { + const [messages, setMessages] = useState([]); + const [inputValue, setInputValue] = useState(''); + const [isTyping, setIsTyping] = useState(false); + const messagesEndRef = useRef(null); + const inputRef = useRef(null); + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); + }; + + useEffect(() => { + scrollToBottom(); + }, [messages, isTyping]); + + const handleSend = async (text = inputValue) => { + if (!text.trim()) return; + + const userMessage = { + id: Date.now(), + text: text.trim(), + isUser: true, + timestamp: new Date(), + }; + + setMessages(prev => [...prev, userMessage]); + setInputValue(''); + setIsTyping(true); + + // Simulate AI thinking time + await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 1500)); + + const aiResponse = { + id: Date.now() + 1, + text: DEMO_RESPONSES[Math.floor(Math.random() * DEMO_RESPONSES.length)], + isUser: false, + timestamp: new Date(), + }; + + setIsTyping(false); + setMessages(prev => [...prev, aiResponse]); + }; + + const handleKeyPress = (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + handleSend(); + } + }; + + const suggestions = [ + "What can you help me with?", + "Tell me something interesting", + "How does AI work?", + "Help me brainstorm ideas", + ]; + + return ( + +
+
+ {/* Header */} +
+
+
+
+ + + +
+
+

Nova AI

+ + + Online + +
+
+
+ +
+
+
+ + {/* Messages Area */} +
+ {messages.length === 0 ? ( +
+
+ + + +
+

Welcome to Nova AI

+

Your intelligent assistant powered by advanced AI. Ask me anything!

+
+
+ + + + Creative Ideas +
+
+ + + + Knowledge Base +
+
+ + + + Code Help +
+
+ + + + Conversations +
+
+
+

Try asking:

+
+ {suggestions.map((suggestion, idx) => ( + + ))} +
+
+
+ ) : ( +
+ {messages.map((message) => ( + + ))} + {isTyping && } +
+
+ )} +
+ + {/* Input Area */} +
+
+