feat: refactorer l'interface avec système de vues grid/list/compact, toolbar moderne avec toggle de vue et pagination intégrée, styles hover unifiés pour header-nav-link avec état active, suppression des pills Notes obsolètes, ajout content-container responsive, link cards avec sélection visuelle et checkbox repositionné, badges visibility/readlater optimisés, et restructuration majeure du CSS avec 2500+ lignes de nouveaux styles pour grilles adaptatives, modales, formulaires, et compos

This commit is contained in:
2026-02-20 10:31:41 -05:00
parent 83d9a7425e
commit f230ff0acd
9 changed files with 15500 additions and 189 deletions
+60 -40
View File
@@ -85,20 +85,21 @@ document.addEventListener('DOMContentLoaded', () => {
});
// ===== Search Overlay (Spotlight Style) =====
const searchOverlay = document.getElementById('search-overlay');
const searchToggleBtns = document.querySelectorAll('[data-search-toggle]');
const searchModalInput = document.getElementById('search-modal-input');
const searchResults = document.getElementById('search-results');
const searchTagsBtn = document.getElementById('search-tags-btn');
const searchAllBtn = document.getElementById('search-all-btn');
const searchNotesBtn = document.getElementById('search-notes-btn');
const searchForm = document.getElementById('search-form');
try {
const searchOverlay = document.getElementById('search-overlay');
const searchToggleBtns = document.querySelectorAll('[data-search-toggle]');
const searchModalInput = document.getElementById('search-modal-input');
const searchResults = document.getElementById('search-results');
const searchTagsBtn = document.getElementById('search-tags-btn');
const searchAllBtn = document.getElementById('search-all-btn');
const searchNotesBtn = document.getElementById('search-notes-btn');
const searchForm = document.getElementById('search-form');
let searchMode = 'search'; // 'search' | 'tags' | 'notes'
let selectedIndex = -1;
let searchTimeout = null;
let cachedBookmarks = null;
let cachedTags = null;
let searchMode = 'search'; // 'search' | 'tags' | 'notes'
let selectedIndex = -1;
let searchTimeout = null;
let cachedBookmarks = null;
let cachedTags = null;
// Escape HTML to prevent XSS
function escapeHtml(text) {
@@ -185,12 +186,12 @@ document.addEventListener('DOMContentLoaded', () => {
function getSearchHint(mode) {
if (mode === 'tags') {
return 'Type to search in tags...';
return 'Rechercher dans les tags...';
}
if (mode === 'notes') {
return 'Type to search in notes...';
return 'Rechercher dans les notes...';
}
return 'Type to search in bookmarks and notes...';
return 'Rechercher dans les bookmarks et notes...';
}
// Render search results (tags, global bookmarks, or notes)
@@ -375,6 +376,36 @@ document.addEventListener('DOMContentLoaded', () => {
selectedIndex = -1;
}
function submitSearchByMode() {
const basePath = (typeof shaarli !== 'undefined' && shaarli.basePath) ? shaarli.basePath : '';
const query = (searchModalInput?.value || '').trim();
if (selectedIndex >= 0 && navigateToSelected()) {
return;
}
if (!query) {
if (searchMode === 'tags') {
window.location.href = `${basePath}/tags/cloud`;
return;
}
window.location.href = `${basePath}/`;
return;
}
if (searchMode === 'tags') {
window.location.href = `${basePath}/?searchtags=${encodeURIComponent(query)}`;
return;
}
if (searchMode === 'notes') {
window.location.href = `${basePath}/?searchterm=${encodeURIComponent(query)}&searchtags=note`;
return;
}
window.location.href = `${basePath}/?searchterm=${encodeURIComponent(query)}`;
}
// Toggle search mode (tags vs search)
function setSearchMode(mode) {
if (!['search', 'tags', 'notes'].includes(mode)) {
@@ -391,6 +422,10 @@ document.addEventListener('DOMContentLoaded', () => {
searchTagsBtn?.setAttribute('aria-pressed', String(mode === 'tags'));
searchNotesBtn?.setAttribute('aria-pressed', String(mode === 'notes'));
searchAllBtn?.setAttribute('aria-selected', String(mode === 'search'));
searchTagsBtn?.setAttribute('aria-selected', String(mode === 'tags'));
searchNotesBtn?.setAttribute('aria-selected', String(mode === 'notes'));
if (searchModalInput) {
searchModalInput.name = mode === 'tags' ? 'searchtags' : 'searchterm';
searchModalInput.placeholder = getSearchHint(mode);
@@ -427,19 +462,8 @@ document.addEventListener('DOMContentLoaded', () => {
});
searchForm?.addEventListener('submit', (e) => {
if (searchMode === 'notes') {
e.preventDefault();
if (selectedIndex < 0) {
updateSelection(0);
}
navigateToSelected();
return;
}
if (selectedIndex >= 0) {
e.preventDefault();
navigateToSelected();
}
e.preventDefault();
submitSearchByMode();
});
// Live search on input
@@ -455,7 +479,7 @@ document.addEventListener('DOMContentLoaded', () => {
});
// Keyboard shortcuts
document.addEventListener('keydown', (e) => {
document.addEventListener('keydown', (e) => {
const isSearchOpen = searchOverlay?.classList.contains('show');
const target = e.target;
const isTyping = Boolean(
@@ -490,15 +514,8 @@ document.addEventListener('DOMContentLoaded', () => {
updateSelection(selectedIndex - 1);
break;
case 'Enter':
// If an item is selected, navigate to it
if (selectedIndex >= 0 && navigateToSelected()) {
e.preventDefault();
} else if (searchMode === 'notes') {
e.preventDefault();
updateSelection(0);
navigateToSelected();
}
// Otherwise, submit the form normally
e.preventDefault();
submitSearchByMode();
break;
}
return;
@@ -521,7 +538,10 @@ document.addEventListener('DOMContentLoaded', () => {
e.preventDefault();
openSearch('notes');
}
});
});
} catch (error) {
console.error('Search overlay initialization failed:', error);
}
// ===== Filter Panel =====
const filterToggleBtn = document.getElementById('filter-toggle-btn');