Abmacode12's picture
import React, { useState } from 'react';
3376581 verified
class CustomSidebar extends HTMLElement {
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.render();
// Observe attribute changes
const observer = new MutationObserver(() => this.render());
observer.observe(this, { attributes: true });
}
static get observedAttributes() {
return ['collapsed', 'active-view'];
}
render() {
const collapsed = this.hasAttribute('collapsed');
const activeView = this.getAttribute('active-view') || 'home';
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
background: white;
border-right: 1px solid #e5e7eb;
transition: all 0.3s;
width: ${collapsed ? '5rem' : '18rem'};
height: 100vh;
overflow-y: auto;
flex-shrink: 0;
}
.logo {
padding: 1.5rem;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid #e5e7eb;
}
.logo-content {
display: flex;
align-items: center;
gap: 0.75rem;
}
.logo-icon {
width: 2.5rem;
height: 2.5rem;
background: linear-gradient(135deg, #3b82f6, #8b5cf6);
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
font-size: 1.125rem;
}
.logo-text h1 {
font-weight: 700;
color: #111827;
font-size: 1rem;
}
.logo-text p {
font-size: 0.75rem;
color: #6b7280;
}
.toggle-btn {
padding: 0.5rem;
border-radius: 0.5rem;
transition: all 0.2s;
}
.toggle-btn:hover {
background: #f3f4f6;
}
.new-task {
padding: 1rem;
border-bottom: 1px solid #e5e7eb;
}
.new-task-btn {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
background: #111827;
color: white;
padding: 0.75rem;
border-radius: 0.5rem;
font-weight: 600;
transition: all 0.2s;
}
.new-task-btn:hover {
background: #1f2937;
}
.search {
padding: 1rem;
border-bottom: 1px solid #e5e7eb;
}
.search-container {
position: relative;
}
.search-icon {
position: absolute;
left: 0.75rem;
top: 0.75rem;
color: #9ca3af;
}
.search-input {
width: 100%;
padding-left: 2.5rem;
padding-right: 1rem;
padding-top: 0.5rem;
padding-bottom: 0.5rem;
background: #f9fafb;
border: 1px solid #e5e7eb;
border-radius: 0.5rem;
font-size: 0.875rem;
outline: none;
}
.search-input:focus {
border-color: #3b82f6;
box-shadow: 0 0 0 2px #bfdbfe;
}
nav {
flex: 1;
padding: 1rem;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.nav-item {
width: 100%;
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem;
border-radius: 0.5rem;
transition: all 0.2s;
font-size: 0.875rem;
color: #4b5563;
}
.nav-item:hover {
background: #f3f4f6;
}
.nav-item.active {
background: #dbeafe;
color: #1d4ed8;
}
.projects {
padding: 1rem;
border-top: 1px solid #e5e7eb;
}
.projects-title {
font-weight: 600;
color: #111827;
margin-bottom: 0.75rem;
font-size: 0.875rem;
}
.project-item {
width: 100%;
text-align: left;
padding: 0.75rem;
border-radius: 0.5rem;
transition: all 0.2s;
font-size: 0.875rem;
margin-bottom: 0.5rem;
}
.project-item:hover {
background: #f3f4f6;
}
.project-item.active {
background: #d1fae5;
border-left: 4px solid #10b981;
}
.project-status {
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
display: inline-block;
margin-right: 0.5rem;
}
.project-status.active {
background: #10b981;
}
.project-status.archived {
background: #9ca3af;
}
.project-name {
font-weight: 500;
}
.project-time {
font-size: 0.75rem;
color: #6b7280;
margin-top: 0.25rem;
}
.footer {
padding: 1rem;
border-top: 1px solid #e5e7eb;
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.footer-item {
width: 100%;
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0.75rem;
border-radius: 0.5rem;
transition: all 0.2s;
font-size: 0.875rem;
color: #4b5563;
}
.footer-item:hover {
background: #f3f4f6;
}
</style>
<div class="logo">
${!collapsed ? `
<div class="logo-content">
<div class="logo-icon">RC</div>
<div class="logo-text">
<h1>Rosalinda</h1>
<p>Workspace Codage</p>
</div>
</div>
` : `
<div class="logo-icon">RC</div>
`}
<button class="toggle-btn" onclick="document.querySelector('custom-sidebar').toggleAttribute('collapsed')">
<i data-feather="${collapsed ? 'menu' : 'x'}"></i>
</button>
</div>
${!collapsed ? `
<div class="new-task">
<button class="new-task-btn">
<i data-feather="plus"></i>
<span>Nouvelle tâche</span>
</button>
</div>
<div class="search">
<div class="search-container">
<i data-feather="search" class="search-icon"></i>
<input type="text" placeholder="Rechercher..." class="search-input">
</div>
</div>
` : ''}
<nav>
${this.createNavItem('home', 'Accueil', 'home', activeView === 'home', collapsed)}
${this.createNavItem('chat', 'Chat Rosalinda', 'message-square', activeView === 'chat', collapsed)}
${this.createNavItem('projects', 'Mes Projets', 'folder', activeView === 'projects', collapsed)}
${this.createNavItem('code', 'Code Généré', 'code', activeView === 'code', collapsed)}
${this.createNavItem('library', 'Bibliothèque', 'book', activeView === 'library', collapsed)}
</nav>
${!collapsed ? `
<div class="projects">
<h3 class="projects-title">Vos Projets</h3>
${this.createProjectItem(1, 'Portfolio Pro', 'active', '2 jours', false)}
${this.createProjectItem(2, 'E-shop Mode', 'active', '5 jours', false)}
${this.createProjectItem(3, 'App SaaS', 'archived', '10 jours', false)}
</div>
<div class="footer">
<button class="footer-item">
<i data-feather="settings"></i>
${!collapsed ? '<span>Paramètres</span>' : ''}
</button>
<button class="footer-item">
<i data-feather="log-out"></i>
${!collapsed ? '<span>Déconnexion</span>' : ''}
</button>
</div>
` : ''}
`;
feather.replace();
}
createNavItem(id, label, icon, isActive, collapsed) {
return `
<button onclick="setView('${id}')" class="nav-item ${isActive ? 'active' : ''}">
<i data-feather="${icon}"></i>
${!collapsed ? `<span>${label}</span>` : ''}
</button>
`;
}
createProjectItem(id, name, status, time, isActive) {
return `
<button onclick="setSelectedProject(${id})" class="project-item ${isActive ? 'active' : ''}">
<div class="flex items-center">
<span class="project-status ${status}"></span>
<span class="project-name">${name}</span>
</div>
<p class="project-time">${time}</p>
</button>
`;
}
}
customElements.define('custom-sidebar', CustomSidebar);