Spaces:
Build error
Build error
import streamlit as st | |
import streamlit.components.v1 as components | |
# Set page config | |
st.set_page_config( | |
page_title="Perplexity AI Clone", | |
page_icon="π", | |
layout="wide", | |
initial_sidebar_state="collapsed" | |
) | |
# Custom CSS for dark theme and styling | |
st.markdown(""" | |
<style> | |
/* Hide Streamlit default elements */ | |
.stDeployButton {display: none;} | |
header[data-testid="stHeader"] {display: none;} | |
.stMainBlockContainer {padding-top: 0rem;} | |
/* Dark theme background */ | |
.stApp { | |
background-color: #1a1a1a; | |
color: white; | |
} | |
/* Main container styling */ | |
.main-container { | |
background-color: #1a1a1a; | |
min-height: 100vh; | |
display: flex; | |
flex-direction: column; | |
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; | |
} | |
/* Header styling */ | |
.header { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
padding: 1rem 2rem; | |
background-color: #1a1a1a; | |
border-bottom: 1px solid #333; | |
} | |
.logo { | |
display: flex; | |
align-items: center; | |
font-size: 1.2rem; | |
font-weight: 600; | |
color: white; | |
} | |
.logo-icon { | |
width: 24px; | |
height: 24px; | |
margin-right: 8px; | |
background: linear-gradient(45deg, #00d4ff, #00a8cc); | |
border-radius: 4px; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
} | |
.get-app-btn { | |
background-color: #00d4ff; | |
color: #1a1a1a; | |
padding: 8px 16px; | |
border-radius: 20px; | |
border: none; | |
font-weight: 600; | |
cursor: pointer; | |
font-size: 14px; | |
} | |
/* Center content */ | |
.center-content { | |
flex: 1; | |
display: flex; | |
flex-direction: column; | |
justify-content: center; | |
align-items: center; | |
max-width: 800px; | |
margin: 0 auto; | |
padding: 2rem; | |
} | |
/* Main heading */ | |
.main-heading { | |
font-size: 3.5rem; | |
font-weight: 400; | |
text-align: center; | |
margin-bottom: 3rem; | |
color: white; | |
line-height: 1.2; | |
} | |
/* Chat input container */ | |
.chat-container { | |
width: 100%; | |
max-width: 700px; | |
position: relative; | |
margin-bottom: 2rem; | |
} | |
/* Custom input styling */ | |
.chat-input-wrapper { | |
position: relative; | |
background-color: #2d2d2d; | |
border-radius: 12px; | |
border: 1px solid #404040; | |
overflow: hidden; | |
} | |
.chat-input { | |
width: 100%; | |
padding: 16px 120px 16px 20px; | |
background: transparent; | |
border: none; | |
outline: none; | |
color: white; | |
font-size: 16px; | |
font-family: inherit; | |
resize: none; | |
min-height: 24px; | |
max-height: 200px; | |
} | |
.chat-input::placeholder { | |
color: #888; | |
} | |
/* Button container */ | |
.button-container { | |
position: absolute; | |
right: 8px; | |
top: 50%; | |
transform: translateY(-50%); | |
display: flex; | |
align-items: center; | |
gap: 4px; | |
} | |
/* Individual buttons */ | |
.action-btn { | |
width: 32px; | |
height: 32px; | |
background: transparent; | |
border: none; | |
border-radius: 6px; | |
cursor: pointer; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
color: #888; | |
transition: all 0.2s ease; | |
} | |
.action-btn:hover { | |
background-color: #404040; | |
color: white; | |
} | |
.search-btn { | |
background-color: #00d4ff; | |
color: #1a1a1a; | |
border-radius: 6px; | |
margin-right: 4px; | |
} | |
.search-btn:hover { | |
background-color: #00b8e6; | |
} | |
/* Bottom navigation placeholder */ | |
.bottom-nav { | |
position: fixed; | |
bottom: 0; | |
left: 50%; | |
transform: translateX(-50%); | |
background-color: #1a1a1a; | |
padding: 1rem; | |
display: flex; | |
gap: 2rem; | |
border-top: 1px solid #333; | |
width: 200px; | |
justify-content: center; | |
} | |
.nav-item { | |
width: 24px; | |
height: 24px; | |
background-color: #333; | |
border-radius: 4px; | |
cursor: pointer; | |
} | |
/* Responsive design */ | |
@media (max-width: 768px) { | |
.main-heading { | |
font-size: 2.5rem; | |
} | |
.header { | |
padding: 1rem; | |
} | |
.center-content { | |
padding: 1rem; | |
} | |
} | |
</style> | |
""", unsafe_allow_html=True) | |
# Main HTML structure | |
st.markdown(""" | |
<div class="main-container"> | |
<div class="header"> | |
<div class="logo"> | |
<div class="logo-icon">β‘</div> | |
perplexity | |
</div> | |
<button class="get-app-btn">π± Get App</button> | |
</div> | |
<div class="center-content"> | |
<h1 class="main-heading">What do you want to know?</h1> | |
<div class="chat-container"> | |
<div class="chat-input-wrapper"> | |
<textarea | |
class="chat-input" | |
placeholder="Ask anything..." | |
rows="1" | |
id="chatInput" | |
></textarea> | |
<div class="button-container"> | |
<button class="action-btn search-btn" title="Search"> | |
π | |
</button> | |
<button class="action-btn" title="Image"> | |
πΌοΈ | |
</button> | |
<button class="action-btn" title="Globe"> | |
π | |
</button> | |
<button class="action-btn" title="Attachment"> | |
π | |
</button> | |
<button class="action-btn" title="Voice"> | |
π€ | |
</button> | |
<button class="action-btn" title="Send"> | |
β€ | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="bottom-nav"> | |
<div class="nav-item"></div> | |
<div class="nav-item"></div> | |
<div class="nav-item"></div> | |
</div> | |
</div> | |
""", unsafe_allow_html=True) | |
# JavaScript for interactive functionality | |
components.html(""" | |
<script> | |
document.addEventListener('DOMContentLoaded', function() { | |
const chatInput = document.getElementById('chatInput'); | |
const buttons = document.querySelectorAll('.action-btn'); | |
// Auto-resize textarea | |
chatInput.addEventListener('input', function() { | |
this.style.height = 'auto'; | |
this.style.height = Math.min(this.scrollHeight, 200) + 'px'; | |
}); | |
// Button click handlers | |
buttons.forEach(button => { | |
button.addEventListener('click', function() { | |
const title = this.getAttribute('title'); | |
console.log(`${title} button clicked`); | |
// Add visual feedback | |
this.style.transform = 'scale(0.95)'; | |
setTimeout(() => { | |
this.style.transform = 'scale(1)'; | |
}, 100); | |
// Handle specific button actions | |
if (title === 'Send' && chatInput.value.trim()) { | |
console.log('Sending message:', chatInput.value); | |
// Here you would typically send the message | |
chatInput.value = ''; | |
chatInput.style.height = 'auto'; | |
} | |
}); | |
}); | |
// Enter key to send | |
chatInput.addEventListener('keydown', function(e) { | |
if (e.key === 'Enter' && !e.shiftKey) { | |
e.preventDefault(); | |
if (this.value.trim()) { | |
console.log('Sending message:', this.value); | |
// Here you would typically send the message | |
this.value = ''; | |
this.style.height = 'auto'; | |
} | |
} | |
}); | |
// Focus on input when page loads | |
chatInput.focus(); | |
}); | |
</script> | |
""", height=0) | |
# Session state for chat history | |
if 'messages' not in st.session_state: | |
st.session_state.messages = [] | |
# Handle form submission (alternative method using Streamlit) | |
with st.form(key='chat_form', clear_on_submit=True): | |
user_input = st.text_input("", placeholder="Ask anything...", label_visibility="hidden", key="user_input") | |
submit_button = st.form_submit_button("Send", use_container_width=False) | |
if submit_button and user_input: | |
st.session_state.messages.append({"role": "user", "content": user_input}) | |
# Here you would add your AI response logic | |
st.session_state.messages.append({"role": "assistant", "content": f"You asked: {user_input}"}) | |
# Display chat history (if any messages exist) | |
if st.session_state.messages: | |
st.markdown("### Chat History") | |
for message in st.session_state.messages: | |
if message["role"] == "user": | |
st.markdown(f"**You:** {message['content']}") | |
else: | |
st.markdown(f"**Assistant:** {message['content']}") |