feat(wiki-ux-polish-v1): sticky search + filter chips + counter + back-to-top
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
Some checks failed
WEVAL NonReg / nonreg (push) Has been cancelled
UX premium polish for wiki.html after layout fix: NEW FEATURES: - Sticky search bar (raccourci clavier /) * Live instant filter with 150ms debounce * Touches all .wiki-item and .card elements - Filter chips: Tout / 7 jours / 30 jours / Anciens * Date extraction from card text (regex YYYY-MM-DD or DD/MM) * Active state visuel (couleur cyan) - Counter live Showing X / Y entries - Back-to-top floating button (visible > 400px scroll) - Keyboard shortcuts: * / focus search * Esc clear search UX: - Sticky bar glassmorphism (backdrop-filter blur) - Gradient background linear cyan-purple - Smooth transitions 0.15s - Accessibility: aria-label on button Zero régression (only adds above </body>, does not touch existing content) GOLD backup: /opt/wevads/vault/gold_wiki_UX_POLISH_*.html File size 84772 → 90445 (+5673 bytes)
This commit is contained in:
156
wiki.html
156
wiki.html
@@ -802,4 +802,160 @@ b7d75cb53 feat(wtp-udock-dashboard): dashboard premium + endpoint JSON ← tour
|
||||
</p>
|
||||
</section>
|
||||
|
||||
|
||||
<!-- WTP wiki polish v1 (Opus t38e) -->
|
||||
<style id="wtp-wiki-polish-v1">
|
||||
.wtp-polish-bar{
|
||||
position:sticky;top:0;z-index:500;
|
||||
background:linear-gradient(180deg,rgba(11,13,21,.98),rgba(11,13,21,.92));
|
||||
backdrop-filter:blur(12px);
|
||||
padding:12px 20px;border-bottom:1px solid rgba(6,182,212,.2);
|
||||
display:flex;gap:12px;align-items:center;flex-wrap:wrap;
|
||||
box-shadow:0 2px 20px rgba(0,0,0,.3);
|
||||
margin-bottom:16px;
|
||||
}
|
||||
.wtp-polish-bar input.wtp-search{
|
||||
flex:1 1 280px;min-width:200px;
|
||||
padding:10px 40px 10px 16px;border-radius:10px;
|
||||
border:1px solid rgba(6,182,212,.3);
|
||||
background:rgba(15,23,42,.9);color:#e2e8f0;
|
||||
font:600 13px Nunito;outline:none;
|
||||
}
|
||||
.wtp-polish-bar input.wtp-search:focus{
|
||||
border-color:#06b6d4;box-shadow:0 0 12px rgba(6,182,212,.3);
|
||||
}
|
||||
.wtp-filter-chip{
|
||||
padding:6px 12px;border-radius:20px;
|
||||
font:700 10px Nunito;cursor:pointer;user-select:none;
|
||||
background:rgba(100,116,139,.15);color:#94a3b8;
|
||||
border:1px solid rgba(100,116,139,.25);transition:all .15s;
|
||||
}
|
||||
.wtp-filter-chip:hover{background:rgba(6,182,212,.2);color:#22d3ee;border-color:#06b6d4;}
|
||||
.wtp-filter-chip.active{background:#06b6d4;color:#0b0d15;border-color:#06b6d4;font-weight:800;}
|
||||
.wtp-counter{
|
||||
padding:6px 12px;border-radius:8px;
|
||||
background:rgba(168,85,247,.15);color:#c084fc;
|
||||
font:700 11px Nunito;
|
||||
}
|
||||
.wtp-btn-top{
|
||||
position:fixed;bottom:24px;left:24px;z-index:999;
|
||||
width:46px;height:46px;border-radius:50%;
|
||||
background:linear-gradient(135deg,#06b6d4,#a855f7);
|
||||
color:#0b0d15;border:none;cursor:pointer;
|
||||
box-shadow:0 4px 20px rgba(6,182,212,.4);
|
||||
font:900 20px Nunito;
|
||||
display:none;align-items:center;justify-content:center;
|
||||
transition:all .2s;
|
||||
}
|
||||
.wtp-btn-top:hover{transform:translateY(-3px);box-shadow:0 6px 24px rgba(6,182,212,.6);}
|
||||
.wtp-btn-top.visible{display:flex;}
|
||||
.wtp-clear-btn{
|
||||
padding:6px 10px;border-radius:8px;
|
||||
background:rgba(239,68,68,.15);color:#fca5a5;
|
||||
border:1px solid rgba(239,68,68,.25);cursor:pointer;
|
||||
font:700 10px Nunito;
|
||||
}
|
||||
.wtp-clear-btn:hover{background:rgba(239,68,68,.3);color:#fff;}
|
||||
</style>
|
||||
|
||||
<div class="wtp-polish-bar" id="wtp-polish-bar">
|
||||
<input class="wtp-search" id="wtp-wiki-search" placeholder="🔍 Recherche instantanée (raccourci: /)" />
|
||||
<span class="wtp-filter-chip active" data-filter="all">Tout</span>
|
||||
<span class="wtp-filter-chip" data-filter="week">7 derniers jours</span>
|
||||
<span class="wtp-filter-chip" data-filter="month">30 derniers jours</span>
|
||||
<span class="wtp-filter-chip" data-filter="old">Anciens</span>
|
||||
<span class="wtp-counter" id="wtp-counter">—</span>
|
||||
<button class="wtp-clear-btn" onclick="wtpClearSearch()">Effacer</button>
|
||||
</div>
|
||||
|
||||
<button class="wtp-btn-top" id="wtp-btn-top" onclick="window.scrollTo({top:0,behavior:'smooth'})" aria-label="Retour en haut">↑</button>
|
||||
|
||||
<script>
|
||||
(function(){
|
||||
'use strict';
|
||||
const search = document.getElementById('wtp-wiki-search');
|
||||
const counter = document.getElementById('wtp-counter');
|
||||
const btnTop = document.getElementById('wtp-btn-top');
|
||||
const chips = document.querySelectorAll('.wtp-filter-chip');
|
||||
let currentFilter = 'all';
|
||||
|
||||
function allItems(){ return document.querySelectorAll('.wiki-item, .card'); }
|
||||
|
||||
function extractDate(el){
|
||||
// Look for date patterns: 2026-04-XX, XX/04, 10/04, etc.
|
||||
const t = el.textContent;
|
||||
const m = t.match(/(\d{4})-(\d{2})-(\d{2})/) || t.match(/(\d{2})\/(\d{2})(?!\s*\d)/);
|
||||
if (!m) return null;
|
||||
if (m.length === 4) return new Date(m[1], parseInt(m[2])-1, m[3]);
|
||||
if (m.length === 3) return new Date(2026, parseInt(m[2])-1, m[1]);
|
||||
return null;
|
||||
}
|
||||
|
||||
function applyFilters(){
|
||||
const q = (search.value||'').toLowerCase().trim();
|
||||
const now = new Date();
|
||||
const w7 = new Date(now - 7*86400000);
|
||||
const w30 = new Date(now - 30*86400000);
|
||||
let shown = 0, total = 0;
|
||||
|
||||
allItems().forEach(el => {
|
||||
total++;
|
||||
const txt = (el.textContent + ' ' + (el.dataset.tags||'')).toLowerCase();
|
||||
let match = !q || txt.includes(q);
|
||||
|
||||
if (match && currentFilter !== 'all') {
|
||||
const d = extractDate(el);
|
||||
if (!d) match = (currentFilter === 'old');
|
||||
else {
|
||||
if (currentFilter === 'week') match = d >= w7;
|
||||
else if (currentFilter === 'month') match = d >= w30;
|
||||
else if (currentFilter === 'old') match = d < w30;
|
||||
}
|
||||
}
|
||||
|
||||
el.style.display = match ? '' : 'none';
|
||||
if (match) shown++;
|
||||
});
|
||||
|
||||
counter.textContent = shown === total ? `${total} entrées` : `${shown} / ${total}`;
|
||||
}
|
||||
|
||||
let deb; search.addEventListener('input', () => { clearTimeout(deb); deb = setTimeout(applyFilters, 150); });
|
||||
|
||||
chips.forEach(chip => {
|
||||
chip.addEventListener('click', () => {
|
||||
chips.forEach(c => c.classList.remove('active'));
|
||||
chip.classList.add('active');
|
||||
currentFilter = chip.dataset.filter;
|
||||
applyFilters();
|
||||
});
|
||||
});
|
||||
|
||||
window.wtpClearSearch = function(){
|
||||
search.value = '';
|
||||
chips.forEach(c => c.classList.remove('active'));
|
||||
document.querySelector('.wtp-filter-chip[data-filter="all"]').classList.add('active');
|
||||
currentFilter = 'all';
|
||||
applyFilters();
|
||||
search.focus();
|
||||
};
|
||||
|
||||
// Keyboard shortcuts
|
||||
document.addEventListener('keydown', e => {
|
||||
if (e.key === '/' && e.target !== search) { e.preventDefault(); search.focus(); }
|
||||
else if (e.key === 'Escape' && e.target === search) { wtpClearSearch(); }
|
||||
});
|
||||
|
||||
// Back-to-top visibility
|
||||
window.addEventListener('scroll', () => {
|
||||
if (window.scrollY > 400) btnTop.classList.add('visible');
|
||||
else btnTop.classList.remove('visible');
|
||||
}, {passive:true});
|
||||
|
||||
// Init
|
||||
setTimeout(applyFilters, 100);
|
||||
})();
|
||||
</script>
|
||||
<!-- /wtp-wiki-polish-v1 -->
|
||||
|
||||
</body></html>
|
||||
Reference in New Issue
Block a user