✨ UX: busca, tags, fixar e renomear conversas
This commit is contained in:
+244
-30
@@ -74,11 +74,21 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
const historyItems = document.getElementById('historyItems');
|
||||
const btnLogout = document.getElementById('btnLogout');
|
||||
const suggestionCards = document.querySelectorAll('.suggestion-card');
|
||||
const searchInput = document.getElementById('searchInput');
|
||||
const searchClear = document.getElementById('searchClear');
|
||||
const searchResultsHeader = document.getElementById('searchResultsHeader');
|
||||
const searchResultsCount = document.getElementById('searchResultsCount');
|
||||
const searchClearAll = document.getElementById('searchClearAll');
|
||||
const sidebarTags = document.getElementById('sidebarTags');
|
||||
|
||||
// Variáveis de Estado
|
||||
let chats = JSON.parse(localStorage.getItem('camila_chats')) || [];
|
||||
// Migração: adicionar campos tags e pinned a chats antigos
|
||||
chats = chats.map(c => ({ ...c, tags: c.tags || [], pinned: c.pinned || false }));
|
||||
let currentChatId = localStorage.getItem('camila_current_chat_id') || null;
|
||||
let isGenerating = false;
|
||||
let searchQuery = '';
|
||||
let activeTag = 'all';
|
||||
|
||||
// ==========================================================================
|
||||
// CONTROLES DE INTERFACE & SIDEBAR
|
||||
@@ -115,8 +125,39 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
});
|
||||
|
||||
// Busca no histórico
|
||||
searchInput.addEventListener('input', () => {
|
||||
searchQuery = searchInput.value;
|
||||
searchClear.style.display = searchQuery ? 'flex' : 'none';
|
||||
renderHistory();
|
||||
});
|
||||
|
||||
searchClear.addEventListener('click', () => {
|
||||
searchInput.value = '';
|
||||
searchQuery = '';
|
||||
searchClear.style.display = 'none';
|
||||
renderHistory();
|
||||
});
|
||||
|
||||
searchClearAll.addEventListener('click', () => {
|
||||
searchInput.value = '';
|
||||
searchQuery = '';
|
||||
searchClear.style.display = 'none';
|
||||
renderHistory();
|
||||
});
|
||||
|
||||
// Filtro por tags
|
||||
sidebarTags.addEventListener('click', (e) => {
|
||||
const tagBtn = e.target.closest('.tag-filter');
|
||||
if (!tagBtn) return;
|
||||
document.querySelectorAll('.tag-filter').forEach(b => b.classList.remove('active'));
|
||||
tagBtn.classList.add('active');
|
||||
activeTag = tagBtn.dataset.tag;
|
||||
renderHistory();
|
||||
});
|
||||
|
||||
// ==========================================================================
|
||||
// HISTÓRICO DE CHATS (LOCALSTORAGE)
|
||||
// HISTÓRICO DE CHATS (LOCALSTORAGE) — VERSÃO COMPLETA COM PINNED, TAGS, BUSCA
|
||||
// ==========================================================================
|
||||
|
||||
const saveChats = () => {
|
||||
@@ -128,6 +169,91 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
}
|
||||
};
|
||||
|
||||
// Agrupamento por data
|
||||
const getDateGroup = (timestamp) => {
|
||||
const now = new Date();
|
||||
const date = new Date(timestamp);
|
||||
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
|
||||
const yesterday = new Date(today);
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
const weekAgo = new Date(today);
|
||||
weekAgo.setDate(weekAgo.getDate() - 7);
|
||||
const monthStart = new Date(now.getFullYear(), now.getMonth(), 1);
|
||||
|
||||
const dateOnly = new Date(date.getFullYear(), date.getMonth(), date.getDate());
|
||||
|
||||
if (dateOnly.getTime() === today.getTime()) return 'Hoje';
|
||||
if (dateOnly.getTime() === yesterday.getTime()) return 'Ontem';
|
||||
if (dateOnly >= weekAgo) return 'Esta Semana';
|
||||
if (dateOnly >= monthStart) return 'Este Mês';
|
||||
return 'Mais Antigas';
|
||||
};
|
||||
|
||||
// Filtrar chats por tag
|
||||
const filterByTag = (chatList) => {
|
||||
if (activeTag === 'all') return chatList;
|
||||
return chatList.filter(chat => chat.tags && chat.tags.includes(activeTag));
|
||||
};
|
||||
|
||||
// Filtrar chats por busca
|
||||
const filterBySearch = (chatList) => {
|
||||
if (!searchQuery.trim()) return chatList;
|
||||
const q = searchQuery.toLowerCase();
|
||||
return chatList.filter(chat => {
|
||||
if (chat.title.toLowerCase().includes(q)) return true;
|
||||
return chat.messages.some(msg => msg.content.toLowerCase().includes(q));
|
||||
});
|
||||
};
|
||||
|
||||
// Renderizar um item de chat
|
||||
const createHistoryItem = (chat) => {
|
||||
const item = document.createElement('div');
|
||||
item.className = `history-item ${chat.id === currentChatId ? 'active' : ''} ${chat.pinned ? 'pinned' : ''}`;
|
||||
item.dataset.id = chat.id;
|
||||
|
||||
const pinIcon = chat.pinned
|
||||
? `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" class="pin-icon"><path d="M16 12V4h1V2H7v2h1v8l-2 2v2h5.2v6h1.6v-6H18v-2l-2-2z"/></svg>`
|
||||
: '';
|
||||
|
||||
const tagBadges = (chat.tags || []).map(tag =>
|
||||
`<span class="history-tag-badge">${getTagEmoji(tag)}</span>`
|
||||
).join('');
|
||||
|
||||
item.innerHTML = `
|
||||
<div class="history-item-content">
|
||||
${pinIcon}
|
||||
<div class="history-item-title">${escapeHtml(chat.title)}</div>
|
||||
${tagBadges ? `<div class="history-item-tags">${tagBadges}</div>` : ''}
|
||||
</div>
|
||||
<div class="history-item-actions">
|
||||
<button class="btn-history-action btn-pin-chat" aria-label="${chat.pinned ? 'Desafixar' : 'Fixar'}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="${chat.pinned ? 'currentColor' : 'none'}" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="16.689 16.689L19.3 19.3a1 1 0 0 0 1.414-1.414l-1.066-1.066a7.5 7.5 0 1 0-1.66 1.114l1.004 1.004A1 1 0 0 0 19.3 17.886l-.707-.707a1 1 0 0 0-1.414 1.414l.707.707a1 1 0 0 0 1.414-1.414l-.707-.707a1 1 0 0 0-1.414 1.414l.707.707a1 1 0 0 0 1.414-1.414l-.811-.811a7.5 7.5 0 0 0 .11 2.12l.796.796a1 1 0 1 0 1.414-1.414l-.707-.707a1 1 0 0 0-1.414 1.414l.707.707a1 1 0 0 0 1.414-1.414l-.72-.72a7.5 7.5 0 0 0-.47-2.12 1 1 0 0 0-1.89.574l.707.707a1 1 0 0 0 1.414-1.414l-.707-.707a1 1 0 0 0-1.414 1.414l.707.707a1 1 0 0 0 1.414-1.414l-.707-.707a1 1 0 0 0-1.414 1.414l.5.5a1 1 0 1 0 1.414-1.414l-.5-.5a1 1 0 0 0-1.414 1.414l.707.707a1 1 0 0 0-1.414-1.414l-.707.707a1 1 0 0 0 1.414 1.414l.707-.707a1 1 0 0 0-1.414-1.414l-.707.707a1 1 0 0 0 1.414 1.414l.707-.707a1 1 0 0 0-1.414-1.414l-1.004 1.004a1 1 0 0 0 1.89-.574l-.796-.796a7.5 7.5 0 0 0-.11-2.12l.81.811a1 1 0 0 0-1.414-1.414l-.707.707a1 1 0 0 0 1.414 1.414l.707-.707a1 1 0 0 0-1.414-1.414l-.707.707a1 1 0 0 0 1.414 1.414l.72-.72a7.5 7.5 0 0 0 .47 2.12l-.5-.5a1 1 0 1 0-1.414 1.414l.5.5a1 1 0 0 0-1.414-1.414l-.5.5a1 1 0 0 0 1.414 1.414l.707-.707a1 1 0 0 0-1.414-1.414l-.707.707a1 1 0 0 0 1.414 1.414l.707-.707a1 1 0 0 0-1.414-1.414l-1.004 1.004a7.5 7.5 0 1 0 1.66-1.114l-1.004-1.004a1 1 0 1 0-1.414 1.414l1.066 1.066a1 1 0 0 0-1.414-1.414l-1.066 1.066a1 1 0 0 0 1.414-1.414l-3-3z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-history-action btn-rename-chat" aria-label="Renomear">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m16.862 4.487 1.687-1.688a1.875 1.875 0 1 1 2.652 2.652L10.582 16.07a4.5 4.5 0 0 1-1.897 1.13L6 18l.8-2.685a4.5 4.5 0 0 1 1.13-1.897l8.932-8.931Zm0 0L19.5 7.125M18 14v4.75A2.25 2.25 0 0 1 15.75 21H5.25A2.25 2.25 0 0 1 3 18.75V8.25A2.25 2.25 0 0 1 5.25 6H10" />
|
||||
</svg>
|
||||
</button>
|
||||
<button class="btn-history-action btn-delete-chat" aria-label="Excluir">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
return item;
|
||||
};
|
||||
|
||||
// Emoji para cada tag
|
||||
const getTagEmoji = (tag) => {
|
||||
const emojis = { relatorios: '📋', planejamento: '📝', mindlab: '🧠', estudos: '📚' };
|
||||
return emojis[tag] || '🏷️';
|
||||
};
|
||||
|
||||
// Renderizar histórico completo
|
||||
const renderHistory = () => {
|
||||
historyItems.innerHTML = '';
|
||||
|
||||
@@ -136,38 +262,96 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
return;
|
||||
}
|
||||
|
||||
// Ordenar por timestamp mais recente
|
||||
const sortedChats = [...chats].sort((a, b) => b.updatedAt - a.updatedAt);
|
||||
// Aplicar filtros
|
||||
let filtered = [...chats];
|
||||
filtered = filterByTag(filtered);
|
||||
filtered = filterBySearch(filtered);
|
||||
|
||||
sortedChats.forEach(chat => {
|
||||
const item = document.createElement('div');
|
||||
item.className = `history-item ${chat.id === currentChatId ? 'active' : ''}`;
|
||||
item.dataset.id = chat.id;
|
||||
|
||||
item.innerHTML = `
|
||||
<div class="history-item-title">${escapeHtml(chat.title)}</div>
|
||||
<div class="history-item-actions">
|
||||
<button class="btn-history-action btn-delete-chat" aria-label="Excluir chat">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m14.74 9-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 0 1-2.244 2.077H8.084a2.25 2.25 0 0 1-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 0 0-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 0 1 3.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 0 0-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 0 0-7.5 0" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Selecionar chat
|
||||
item.addEventListener('click', (e) => {
|
||||
if (e.target.closest('.btn-delete-chat')) {
|
||||
e.stopPropagation();
|
||||
deleteChat(chat.id);
|
||||
return;
|
||||
}
|
||||
selectChat(chat.id);
|
||||
toggleSidebar(false);
|
||||
// Se tem busca, mostrar resultados direto (sem grupo)
|
||||
if (searchQuery.trim()) {
|
||||
searchResultsHeader.style.display = 'block';
|
||||
searchResultsCount.textContent = `${filtered.length} resultado${filtered.length !== 1 ? 's' : ''}`;
|
||||
filtered.sort((a, b) => b.updatedAt - a.updatedAt);
|
||||
filtered.forEach(chat => {
|
||||
const item = createHistoryItem(chat);
|
||||
item.addEventListener('click', (e) => {
|
||||
if (e.target.closest('.btn-delete-chat')) { e.stopPropagation(); deleteChat(chat.id); return; }
|
||||
if (e.target.closest('.btn-pin-chat')) { e.stopPropagation(); togglePin(chat.id); return; }
|
||||
if (e.target.closest('.btn-rename-chat')) { e.stopPropagation(); renameChat(chat.id); return; }
|
||||
selectChat(chat.id);
|
||||
toggleSidebar(false);
|
||||
});
|
||||
historyItems.appendChild(item);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
historyItems.appendChild(item);
|
||||
searchResultsHeader.style.display = 'none';
|
||||
|
||||
// Separar pinned e não-pinned
|
||||
const pinned = filtered.filter(c => c.pinned).sort((a, b) => b.updatedAt - a.updatedAt);
|
||||
const unpinned = filtered.filter(c => !c.pinned).sort((a, b) => b.updatedAt - a.updatedAt);
|
||||
|
||||
// Renderizar grupo se tiver items
|
||||
const renderGroup = (label, items) => {
|
||||
if (items.length === 0) return;
|
||||
const group = document.createElement('div');
|
||||
group.className = 'history-group';
|
||||
group.innerHTML = `<h3>${label}</h3>`;
|
||||
const container = document.createElement('div');
|
||||
container.className = 'history-items';
|
||||
items.forEach(chat => {
|
||||
const item = createHistoryItem(chat);
|
||||
item.addEventListener('click', (e) => {
|
||||
if (e.target.closest('.btn-delete-chat')) { e.stopPropagation(); deleteChat(chat.id); return; }
|
||||
if (e.target.closest('.btn-pin-chat')) { e.stopPropagation(); togglePin(chat.id); return; }
|
||||
if (e.target.closest('.btn-rename-chat')) { e.stopPropagation(); renameChat(chat.id); return; }
|
||||
selectChat(chat.id);
|
||||
toggleSidebar(false);
|
||||
});
|
||||
container.appendChild(item);
|
||||
});
|
||||
group.appendChild(container);
|
||||
historyItems.appendChild(group);
|
||||
};
|
||||
|
||||
// Pinned no topo
|
||||
if (pinned.length > 0) {
|
||||
renderGroup('📌 Fixadas', pinned);
|
||||
}
|
||||
|
||||
// Agrupar por data os não-pinned
|
||||
const groups = {};
|
||||
unpinned.forEach(chat => {
|
||||
const group = getDateGroup(chat.updatedAt);
|
||||
if (!groups[group]) groups[group] = [];
|
||||
groups[group].push(chat);
|
||||
});
|
||||
|
||||
['Hoje', 'Ontem', 'Esta Semana', 'Este Mês', 'Mais Antigas'].forEach(g => {
|
||||
if (groups[g]) renderGroup(g, groups[g]);
|
||||
});
|
||||
};
|
||||
|
||||
// Fixar/desfixar chat
|
||||
const togglePin = (id) => {
|
||||
const chat = chats.find(c => c.id === id);
|
||||
if (!chat) return;
|
||||
chat.pinned = !chat.pinned;
|
||||
saveChats();
|
||||
renderHistory();
|
||||
};
|
||||
|
||||
// Renomear chat
|
||||
const renameChat = (id) => {
|
||||
const chat = chats.find(c => c.id === id);
|
||||
if (!chat) return;
|
||||
const newTitle = prompt('Novo nome da conversa:', chat.title);
|
||||
if (newTitle && newTitle.trim()) {
|
||||
chat.title = newTitle.trim();
|
||||
saveChats();
|
||||
renderHistory();
|
||||
}
|
||||
};
|
||||
|
||||
const selectChat = (id) => {
|
||||
@@ -239,9 +423,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
contentHtml = marked.parse(content);
|
||||
}
|
||||
|
||||
const actionsHtml = !isUser ? `
|
||||
<div class="message-actions">
|
||||
<button class="msg-action-btn btn-copy-msg" title="Copiar resposta" data-content="${escapeHtml(content).replace(/"/g, '"')}">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M15.75 17.25v3.375c0 .621-.504 1.125-1.125 1.125h-9.75a1.125 1.125 0 0 1-1.125-1.125V7.875c0-.621.504-1.125 1.125-1.125H6.75a9.06 9.06 0 0 1 1.5.124m7.5 10.376h3.375c.621 0 1.125-.504 1.125-1.125V11.25c0-4.46-3.243-8.161-7.5-8.876a9.06 9.06 0 0 0-1.5-.124H9.375c-.621 0-1.125.504-1.125 1.125v3.5m7.5 10.375H9.375a1.125 1.125 0 0 1-1.125-1.125v-9.25m12 6.625v-1.875a3.375 3.375 0 0 0-3.375-3.375h-1.5a1.125 1.125 0 0 1-1.125-1.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H9.75" />
|
||||
</svg>
|
||||
<span>Copiar</span>
|
||||
</button>
|
||||
</div>
|
||||
` : '';
|
||||
|
||||
row.innerHTML = `
|
||||
<div class="message-icon">${avatarHtml}</div>
|
||||
<div class="message-content">${contentHtml}</div>
|
||||
<div class="message-content-wrapper">
|
||||
<div class="message-content">${contentHtml}</div>
|
||||
${actionsHtml}
|
||||
</div>
|
||||
`;
|
||||
|
||||
conversationList.appendChild(row);
|
||||
@@ -251,6 +449,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
hljs.highlightElement(block);
|
||||
});
|
||||
|
||||
// Event listener para copiar mensagem
|
||||
const copyBtn = row.querySelector('.btn-copy-msg');
|
||||
if (copyBtn) {
|
||||
copyBtn.addEventListener('click', () => {
|
||||
const text = copyBtn.dataset.content;
|
||||
navigator.clipboard.writeText(text).then(() => {
|
||||
const span = copyBtn.querySelector('span');
|
||||
const original = span.textContent;
|
||||
span.textContent = 'Copiado!';
|
||||
setTimeout(() => span.textContent = original, 2000);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return row;
|
||||
};
|
||||
|
||||
@@ -282,6 +494,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
chats.push({
|
||||
id: newId,
|
||||
title: title,
|
||||
tags: [],
|
||||
pinned: false,
|
||||
messages: [],
|
||||
createdAt: Date.now(),
|
||||
updatedAt: Date.now()
|
||||
|
||||
+31
-5
@@ -31,15 +31,41 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Busca no Histórico -->
|
||||
<div class="sidebar-search">
|
||||
<div class="sidebar-search-wrapper">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="search-icon">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z" />
|
||||
</svg>
|
||||
<input type="text" id="searchInput" placeholder="Buscar conversas..." class="search-input" autocomplete="off">
|
||||
<button class="search-clear" id="searchClear" aria-label="Limpar busca" style="display:none">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Tags de filtro -->
|
||||
<div class="sidebar-tags" id="sidebarTags">
|
||||
<button class="tag-filter active" data-tag="all">Todas</button>
|
||||
<button class="tag-filter" data-tag="relatorios">📋 Relatórios</button>
|
||||
<button class="tag-filter" data-tag="planejamento">📝 Planejamento</button>
|
||||
<button class="tag-filter" data-tag="mindlab">🧠 Mind Lab</button>
|
||||
<button class="tag-filter" data-tag="estudos">📚 Estudos</button>
|
||||
</div>
|
||||
|
||||
<!-- Histórico de Conversas -->
|
||||
<div class="chat-history" id="chatHistory">
|
||||
<!-- Grupos de datas dinâmicos por JS -->
|
||||
<div class="history-group">
|
||||
<h3>Hoje</h3>
|
||||
<div class="history-items" id="historyItems">
|
||||
<!-- Items gerados por JS -->
|
||||
<!-- Histórico filtrado/busca -->
|
||||
<div class="search-results-header" id="searchResultsHeader" style="display:none">
|
||||
<div class="search-results-info">
|
||||
<span id="searchResultsCount"></span>
|
||||
<button class="search-clear-all" id="searchClearAll">Limpar</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Items gerados por JS -->
|
||||
<div id="historyItems"></div>
|
||||
</div>
|
||||
|
||||
<!-- Rodapé do Menu Lateral -->
|
||||
|
||||
+211
-1
@@ -391,6 +391,138 @@ body {
|
||||
background-color: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
/* Busca no Histórico */
|
||||
.sidebar-search {
|
||||
padding: 12px 16px 0;
|
||||
}
|
||||
|
||||
.sidebar-search-wrapper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background-color: var(--bg-tertiary);
|
||||
border: 1px solid var(--border-light);
|
||||
border-radius: 10px;
|
||||
padding: 8px 12px;
|
||||
transition: border-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.sidebar-search-wrapper:focus-within {
|
||||
border-color: var(--border-focus);
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
color: var(--text-muted);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.search-input {
|
||||
flex: 1;
|
||||
background: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
color: var(--text-primary);
|
||||
font-size: 13px;
|
||||
font-family: var(--font-sans);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.search-input::placeholder {
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.search-clear {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
padding: 2px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
transition: color var(--transition-fast), background-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.search-clear:hover {
|
||||
color: var(--text-primary);
|
||||
background-color: rgba(255,255,255,0.05);
|
||||
}
|
||||
|
||||
.search-clear svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
/* Tags de filtro */
|
||||
.sidebar-tags {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
padding: 10px 16px 0;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none;
|
||||
}
|
||||
|
||||
.sidebar-tags::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.tag-filter {
|
||||
background-color: var(--bg-tertiary);
|
||||
border: 1px solid var(--border-light);
|
||||
border-radius: 20px;
|
||||
color: var(--text-secondary);
|
||||
font-size: 11.5px;
|
||||
font-weight: 500;
|
||||
padding: 5px 10px;
|
||||
cursor: pointer;
|
||||
white-space: nowrap;
|
||||
transition: all var(--transition-fast);
|
||||
font-family: var(--font-sans);
|
||||
}
|
||||
|
||||
.tag-filter:hover {
|
||||
background-color: var(--bg-accent);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.tag-filter.active {
|
||||
background-color: var(--brand-green);
|
||||
border-color: var(--brand-green);
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Busca results header */
|
||||
.search-results-header {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
|
||||
.search-results-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
font-size: 12px;
|
||||
color: var(--text-muted);
|
||||
}
|
||||
|
||||
.search-clear-all {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--brand-green);
|
||||
cursor: pointer;
|
||||
font-size: 12px;
|
||||
font-family: var(--font-sans);
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
transition: background-color var(--transition-fast);
|
||||
}
|
||||
|
||||
.search-clear-all:hover {
|
||||
background-color: var(--brand-glow);
|
||||
}
|
||||
|
||||
.history-group h3 {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
@@ -416,7 +548,7 @@ body {
|
||||
cursor: pointer;
|
||||
color: var(--text-primary);
|
||||
font-size: 13.5px;
|
||||
gap: 10px;
|
||||
gap: 8px;
|
||||
text-decoration: none;
|
||||
position: relative;
|
||||
transition: background-color var(--transition-fast);
|
||||
@@ -432,11 +564,42 @@ body {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.history-item.pinned {
|
||||
border-left: 2px solid var(--brand-green);
|
||||
padding-left: 8px;
|
||||
}
|
||||
|
||||
.history-item-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.history-item-title {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.pin-icon {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
color: var(--brand-green);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.history-item-tags {
|
||||
display: flex;
|
||||
gap: 2px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.history-tag-badge {
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.history-item-actions {
|
||||
@@ -794,6 +957,53 @@ body {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.message-content-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* Ações de mensagem (copiar) */
|
||||
.message-actions {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
opacity: 0;
|
||||
transition: opacity var(--transition-fast);
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.message-row:hover .message-actions {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.msg-action-btn {
|
||||
background: none;
|
||||
border: 1px solid var(--border-light);
|
||||
border-radius: 6px;
|
||||
color: var(--text-muted);
|
||||
cursor: pointer;
|
||||
padding: 4px 8px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
font-size: 12px;
|
||||
font-family: var(--font-sans);
|
||||
transition: all var(--transition-fast);
|
||||
}
|
||||
|
||||
.msg-action-btn:hover {
|
||||
background-color: var(--bg-tertiary);
|
||||
color: var(--text-primary);
|
||||
border-color: rgba(255,255,255,0.15);
|
||||
}
|
||||
|
||||
.msg-action-btn svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.message-content p {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user