Add close button functionality to project tabs in Claude IDE
Fix missing 'x' close buttons on project tabs (Level 1). Session tabs ( Level 2) already had close buttons implemented. Changes: - project-manager.js: Added close button element to renderProjectTab() - Added closeProject() method with confirmation dialog - Added getSessionName() helper for session name display - Auto-switches to next project when active project is closed - project-tabs.css: Added .tab-close styling for project tabs - Close button shows on hover, red highlight on hover - Mobile responsive: always visible on small screens The close button removes project tab from view but sessions remain accessible via API/reload. Confirmation shows session count and list for non-empty projects. Resolves: https://rommark.dev/claude/ide/session/session-1769083280612-mdof554ot Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -189,6 +189,7 @@ class ProjectManager {
|
||||
<span class="tab-icon">📁</span>
|
||||
<span class="tab-label">${escapeHtml(project.name)}</span>
|
||||
${sessionCount > 0 ? `<span class="tab-count">${sessionCount}</span>` : ''}
|
||||
<span class="tab-close" onclick="event.stopPropagation(); window.projectManager.closeProject('${project.id}')">×</span>
|
||||
</button>
|
||||
`;
|
||||
}
|
||||
@@ -411,6 +412,84 @@ class ProjectManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a project (with confirmation)
|
||||
*/
|
||||
async closeProject(projectId) {
|
||||
const projectKey = projectId.replace('project-', '');
|
||||
const project = this.projects.get(projectKey);
|
||||
if (!project) return;
|
||||
|
||||
// Check if project has sessions
|
||||
if (project.sessions.length > 0) {
|
||||
const sessionList = project.sessions.map(s => this.getSessionName(s)).join(', ');
|
||||
if (!confirm(`Close project "${project.name}"?\n\nThis project contains ${project.sessions.length} session(s):\n${sessionList}\n\nThe sessions will remain accessible but the project tab will be removed.`)) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (!confirm(`Close project "${project.name}"?`)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
console.log('[ProjectManager] Closing project:', projectId);
|
||||
|
||||
// Remove project from map
|
||||
this.projects.delete(projectKey);
|
||||
|
||||
// If we closed the active project, switch to another
|
||||
if (this.activeProjectId === projectId) {
|
||||
const remainingProjects = Array.from(this.projects.values());
|
||||
if (remainingProjects.length > 0) {
|
||||
// Switch to the next available project
|
||||
await this.switchProject(remainingProjects[0].id);
|
||||
} else {
|
||||
// No projects left
|
||||
this.activeProjectId = null;
|
||||
if (window.sessionTabs) {
|
||||
window.sessionTabs.setSessions([]);
|
||||
window.sessionTabs.render();
|
||||
}
|
||||
// Show empty state
|
||||
const messagesContainer = document.getElementById('chat-messages');
|
||||
if (messagesContainer) {
|
||||
messagesContainer.innerHTML = `
|
||||
<div class="empty-project-state">
|
||||
<div class="empty-icon">📁</div>
|
||||
<h3>No Projects</h3>
|
||||
<p>Create a new project to get started</p>
|
||||
<button class="btn-primary" onclick="window.projectManager.createNewProject()">
|
||||
Create Project
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.renderProjectTabs();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get display name for a session
|
||||
*/
|
||||
getSessionName(session) {
|
||||
// Try to get name from metadata
|
||||
if (session.metadata) {
|
||||
if (session.metadata.project) return session.metadata.project;
|
||||
if (session.metadata.title) return session.metadata.title;
|
||||
if (session.metadata.name) return session.metadata.name;
|
||||
}
|
||||
|
||||
// Use working directory
|
||||
if (session.workingDir) {
|
||||
return session.workingDir.split('/').pop();
|
||||
}
|
||||
|
||||
// Fallback to session ID
|
||||
return session.id.substring(0, 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh all projects
|
||||
*/
|
||||
|
||||
@@ -98,6 +98,29 @@
|
||||
color: #4a9eff;
|
||||
}
|
||||
|
||||
.project-tab .tab-close {
|
||||
opacity: 0;
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.project-tab:hover .tab-close {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.project-tab .tab-close:hover {
|
||||
background: rgba(255, 107, 107, 0.2);
|
||||
color: #ff6b6b;
|
||||
}
|
||||
|
||||
/* New Project Tab */
|
||||
.project-tab-new {
|
||||
color: #51cf66;
|
||||
@@ -391,6 +414,10 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.project-tab .tab-close {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.session-tab .tab-close {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user