Add comprehensive mobile responsive design for all IDE views

- Add mobile navigation menu with hamburger toggle
- Add slide-out chat sidebar for mobile (chat.z.ai style)
- Optimize chat view for mobile with:
  - Collapsible sidebar with overlay
  - Touch-friendly input controls (44px min)
  - Responsive message bubbles
  - Hidden scrollbars for cleaner UI
  - Proper font sizing and spacing
- Add mobile responsive styles for:
  - Sessions view (stacked layout)
  - Projects view (single column grid)
  - Dashboard view (single column)
  - Files view (vertical sidebar)
  - Terminal view (compact tabs)
- Add extra small device support (480px breakpoint)
- Add touch-friendly target sizing for touch devices

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
uroma
2026-01-20 20:04:42 +00:00
Unverified
parent ed622ecbe2
commit c244e118f3
2 changed files with 1032 additions and 351 deletions

View File

@@ -1445,3 +1445,620 @@ body {
grid-template-columns: 1fr; grid-template-columns: 1fr;
} }
} }
/* ============================================
Mobile Responsive Design (chat.z.ai style)
============================================ */
/* Navigation Mobile */
@media (max-width: 768px) {
.navbar {
padding: 0.75rem 1rem;
flex-wrap: wrap;
}
.nav-brand h1 {
font-size: 1rem;
}
.nav-menu {
display: none;
position: absolute;
top: 60px;
left: 0;
right: 0;
background: var(--bg-secondary);
border-bottom: 1px solid var(--border);
flex-direction: column;
padding: 1rem;
gap: 0.25rem;
z-index: 100;
}
.nav-menu.active {
display: flex;
}
.nav-item {
width: 100%;
text-align: left;
padding: 0.75rem 1rem;
}
.nav-user {
display: none;
}
/* Mobile Menu Toggle */
.mobile-menu-toggle {
display: block;
background: none;
border: none;
color: var(--text-primary);
font-size: 1.5rem;
cursor: pointer;
padding: 0.5rem;
}
}
@media (min-width: 769px) {
.mobile-menu-toggle {
display: none;
}
}
/* Chat Mobile - Similar to chat.z.ai */
@media (max-width: 768px) {
/* Chat Layout */
.chat-layout {
position: relative;
}
.chat-sidebar {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: var(--bg-secondary);
z-index: 1000;
transform: translateX(-100%);
transition: transform 0.3s ease;
}
.chat-sidebar.active {
transform: translateX(0);
}
.chat-sidebar-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 999;
}
.chat-sidebar-overlay.active {
display: block;
}
/* Chat Header - Add menu toggle */
.chat-header {
padding: 0.75rem 1rem;
flex-wrap: wrap;
gap: 0.5rem;
}
.chat-sidebar-toggle {
display: flex;
align-items: center;
justify-content: center;
width: 36px;
height: 36px;
background: var(--bg-tertiary);
border: 1px solid var(--border);
border-radius: 6px;
color: var(--text-primary);
cursor: pointer;
font-size: 1.2rem;
}
.chat-session-info h2 {
font-size: 1rem;
}
.chat-actions {
flex-wrap: wrap;
}
.chat-actions .btn-sm {
padding: 0.5rem 0.75rem;
font-size: 0.8rem;
}
/* Chat Messages */
.chat-messages {
padding: 1rem;
}
.chat-message {
margin-bottom: 1rem;
gap: 0.75rem;
}
.chat-message-avatar {
width: 32px;
height: 32px;
font-size: 1rem;
}
.chat-message-content {
max-width: 85%;
}
.chat-message-bubble {
padding: 0.75rem;
font-size: 0.9rem;
}
/* Chat Input */
.chat-input-container {
padding: 0.75rem 1rem;
}
.chat-input-wrapper {
gap: 0.5rem;
}
.chat-input {
padding: 0.6rem;
font-size: 0.9rem;
max-height: 120px;
}
.btn-icon {
width: 36px;
height: 36px;
font-size: 1rem;
}
.chat-input-info {
font-size: 0.75rem;
}
/* Welcome Section */
.chat-welcome {
padding: 1rem;
}
.chat-welcome h2 {
font-size: 1.25rem;
}
.chat-welcome p {
font-size: 0.9rem;
}
.chat-tips, .chat-connection-info {
padding: 1rem;
font-size: 0.85rem;
}
.chat-tips code, .chat-connection-info code {
font-size: 0.8rem;
}
/* Quick Actions */
.quick-actions {
padding: 1rem;
margin: 1rem 0;
}
.quick-actions-grid {
grid-template-columns: 1fr;
gap: 0.5rem;
}
.quick-action-btn {
padding: 0.75rem 1rem;
font-size: 0.9rem;
}
.action-icon {
font-size: 1.25rem;
}
/* Code blocks in messages */
.chat-message-bubble pre {
padding: 0.75rem;
font-size: 0.85rem;
overflow-x: auto;
}
.chat-message-bubble code {
font-size: 0.85rem;
}
}
/* Extra small devices */
@media (max-width: 480px) {
.navbar {
padding: 0.5rem 0.75rem;
}
.nav-brand h1 {
font-size: 0.9rem;
}
.chat-header {
padding: 0.5rem 0.75rem;
}
.chat-session-info h2 {
font-size: 0.9rem;
}
.chat-messages {
padding: 0.75rem;
}
.chat-message-avatar {
width: 28px;
height: 28px;
font-size: 0.9rem;
}
.chat-message-content {
max-width: 80%;
}
.chat-message-bubble {
padding: 0.6rem;
font-size: 0.85rem;
}
.chat-input-container {
padding: 0.5rem 0.75rem;
}
.chat-input {
padding: 0.5rem;
font-size: 0.85rem;
}
.btn-icon {
width: 32px;
height: 32px;
font-size: 0.9rem;
}
.sidebar-header {
padding: 1rem;
}
.sidebar-header h2 {
font-size: 1rem;
}
}
/* Touch-friendly targets for mobile */
@media (hover: none) and (pointer: coarse) {
.nav-item,
.btn-primary,
.btn-secondary,
.btn-icon,
.chat-sidebar-toggle,
.chat-session-item,
.quick-action-btn {
min-height: 44px;
min-width: 44px;
}
.chat-input {
min-height: 44px;
}
}
/* Hide scrollbar but keep functionality */
@media (max-width: 768px) {
.chat-messages::-webkit-scrollbar,
.chat-history-list::-webkit-scrollbar,
.sessions-list::-webkit-scrollbar {
width: 0px;
background: transparent;
}
}
/* ============================================
Sessions View Mobile Responsive
============================================ */
@media (max-width: 768px) {
.sessions-layout {
flex-direction: column;
}
.sessions-sidebar {
width: 100%;
max-height: 40vh;
border-right: none;
border-bottom: 1px solid var(--border);
}
.sidebar-header {
padding: 1rem;
}
.sidebar-header h2 {
font-size: 1rem;
}
.sessions-list {
padding: 0.75rem;
}
.session-item {
padding: 0.75rem;
margin-bottom: 0.5rem;
}
.session-header {
flex-direction: column;
align-items: flex-start;
gap: 0.5rem;
}
.session-info {
width: 100%;
}
.session-time {
font-size: 0.75rem;
}
.session-meta {
font-size: 0.75rem;
gap: 0.5rem;
}
.session-path {
word-break: break-all;
}
.sessions-main {
flex: 1;
}
.session-detail {
padding: 1rem;
}
.session-detail-card {
border-radius: 8px;
}
.session-detail-header {
flex-direction: column;
gap: 1rem;
}
.session-title {
width: 100%;
}
.session-title h2 {
font-size: 1rem;
}
.session-detail-actions {
width: 100%;
flex-direction: column;
}
.session-detail-actions button {
width: 100%;
margin-bottom: 0.5rem;
}
.session-detail-meta {
grid-template-columns: 1fr;
gap: 0.5rem;
}
.meta-row {
font-size: 0.85rem;
}
.output-scroll-area {
max-height: 200px;
}
.output-entry {
padding: 0.5rem;
}
.output-header {
flex-wrap: wrap;
gap: 0.25rem;
}
}
/* ============================================
Projects View Mobile Responsive
============================================ */
@media (max-width: 768px) {
.projects-header {
padding: 1rem;
flex-wrap: wrap;
gap: 0.5rem;
}
.projects-header h2 {
font-size: 1.1rem;
}
.projects-grid {
grid-template-columns: 1fr;
padding: 0 1rem 1rem 1rem;
gap: 1rem;
}
.project-card {
padding: 1rem;
}
.project-card h3 {
font-size: 1rem;
}
.project-meta {
font-size: 0.8rem;
}
.project-description {
font-size: 0.85rem;
}
}
/* ============================================
Dashboard View Mobile Responsive
============================================ */
@media (max-width: 768px) {
.dashboard-grid {
grid-template-columns: 1fr;
padding: 1rem;
gap: 1rem;
}
.stat-card {
padding: 1rem;
}
.stat-card h3 {
font-size: 0.85rem;
}
.stat-value {
font-size: 2rem;
}
.panel-header {
padding: 0.75rem 1rem;
flex-wrap: wrap;
gap: 0.5rem;
}
.panel-header h2 {
font-size: 1rem;
}
.panel-content {
padding: 1rem;
}
}
/* ============================================
Files View Mobile Responsive
============================================ */
@media (max-width: 768px) {
.files-layout {
flex-direction: column;
}
.files-sidebar {
width: 100%;
max-height: 40vh;
border-right: none;
border-bottom: 1px solid var(--border);
}
.search-box {
padding: 0.75rem;
}
.file-tree {
padding: 0.75rem;
}
.tree-item {
padding: 0.5rem 0.75rem;
font-size: 0.9rem;
}
.file-editor {
padding: 1rem;
}
.file-header {
flex-wrap: wrap;
gap: 0.5rem;
}
.file-header h2 {
font-size: 1rem;
}
.file-actions .btn-sm {
padding: 0.5rem 0.75rem;
font-size: 0.8rem;
}
.code-view {
padding: 0.75rem;
}
.code-view pre {
padding: 0.75rem;
font-size: 0.8rem;
}
.view-toggle {
padding: 0.5rem;
gap: 0.25rem;
}
.toggle-btn {
padding: 0.5rem 0.75rem;
font-size: 0.8rem;
}
}
/* ============================================
Terminal View Mobile Responsive
============================================ */
@media (max-width: 768px) {
.terminal-container {
padding: 1rem;
}
.terminal-header {
padding: 0.75rem;
flex-wrap: wrap;
gap: 0.5rem;
}
.terminal-header h2 {
font-size: 1rem;
}
.terminal-tabs {
flex-wrap: wrap;
gap: 0.25rem;
}
.terminal-tab {
padding: 0.5rem 0.75rem;
font-size: 0.8rem;
}
.terminal-wrapper {
height: 400px;
}
}

View File

@@ -17,9 +17,10 @@
<!-- Navigation --> <!-- Navigation -->
<nav class="navbar"> <nav class="navbar">
<div class="nav-brand"> <div class="nav-brand">
<button class="mobile-menu-toggle" id="mobile-menu-toggle" aria-label="Toggle menu"></button>
<h1>Claude Code IDE</h1> <h1>Claude Code IDE</h1>
</div> </div>
<div class="nav-menu"> <div class="nav-menu" id="nav-menu">
<button class="nav-item active" data-view="dashboard">Dashboard</button> <button class="nav-item active" data-view="dashboard">Dashboard</button>
<button class="nav-item" data-view="chat">💬 Chat</button> <button class="nav-item" data-view="chat">💬 Chat</button>
<button class="nav-item" data-view="sessions">Sessions</button> <button class="nav-item" data-view="sessions">Sessions</button>
@@ -117,7 +118,8 @@
<!-- Chat View --> <!-- Chat View -->
<div id="chat-view" class="view"> <div id="chat-view" class="view">
<div class="chat-layout"> <div class="chat-layout">
<div class="chat-sidebar"> <div class="chat-sidebar-overlay" id="chat-sidebar-overlay"></div>
<div class="chat-sidebar" id="chat-sidebar">
<div class="sidebar-header"> <div class="sidebar-header">
<h2>Chat</h2> <h2>Chat</h2>
<button class="btn-primary" onclick="startNewChat()">+ New</button> <button class="btn-primary" onclick="startNewChat()">+ New</button>
@@ -128,6 +130,7 @@
</div> </div>
<div class="chat-main"> <div class="chat-main">
<div class="chat-header" id="chat-header"> <div class="chat-header" id="chat-header">
<button class="chat-sidebar-toggle" id="chat-sidebar-toggle" aria-label="Toggle chat history"></button>
<div class="chat-session-info"> <div class="chat-session-info">
<h2 id="chat-title">New Chat</h2> <h2 id="chat-title">New Chat</h2>
<span class="chat-session-id" id="current-session-id"></span> <span class="chat-session-id" id="current-session-id"></span>
@@ -370,5 +373,66 @@
// Initialize on page load // Initialize on page load
document.addEventListener('DOMContentLoaded', initDebugPanel); document.addEventListener('DOMContentLoaded', initDebugPanel);
</script> </script>
<!-- Mobile Menu and Sidebar Toggle Script -->
<script>
// Mobile Navigation Menu Toggle
const mobileMenuToggle = document.getElementById('mobile-menu-toggle');
const navMenu = document.getElementById('nav-menu');
if (mobileMenuToggle) {
mobileMenuToggle.addEventListener('click', () => {
navMenu.classList.toggle('active');
});
}
// Close menu when clicking outside
document.addEventListener('click', (e) => {
if (!e.target.closest('.navbar')) {
navMenu?.classList.remove('active');
}
});
// Close menu when clicking a nav item
document.querySelectorAll('.nav-item').forEach(item => {
item.addEventListener('click', () => {
navMenu?.classList.remove('active');
});
});
// Chat Sidebar Toggle
const chatSidebarToggle = document.getElementById('chat-sidebar-toggle');
const chatSidebar = document.getElementById('chat-sidebar');
const chatSidebarOverlay = document.getElementById('chat-sidebar-overlay');
function toggleChatSidebar() {
if (!chatSidebar || !chatSidebarOverlay) return;
chatSidebar.classList.toggle('active');
chatSidebarOverlay.classList.toggle('active');
}
function closeChatSidebar() {
if (!chatSidebar || !chatSidebarOverlay) return;
chatSidebar.classList.remove('active');
chatSidebarOverlay.classList.remove('active');
}
if (chatSidebarToggle) {
chatSidebarToggle.addEventListener('click', toggleChatSidebar);
}
if (chatSidebarOverlay) {
chatSidebarOverlay.addEventListener('click', closeChatSidebar);
}
// Close sidebar when switching to a different view
const originalSwitchView = window.switchView;
if (typeof originalSwitchView === 'function') {
window.switchView = function(viewName) {
closeChatSidebar();
return originalSwitchView.call(this, viewName);
};
}
</script>
</body> </body>
</html> </html>