feat: complete UI redesign — modern, clean search interface
- New CSS: complete design system with CSS variables, modern color palette - Homepage: full-viewport hero with centered search, logo, tagline - Result cards: rounded, shadowed, with favicons via Google Favicon API - Layout: sidebar + results grid, responsive - Typography: proper font stack, variable weights - Settings panel: polished popover with animations - Autocomplete: modern dropdown with keyboard nav - Dark mode: full color palette via data-theme attribute - Favicon: clean search icon SVG
This commit is contained in:
parent
f1436310eb
commit
f7cece9648
7 changed files with 940 additions and 755 deletions
|
|
@ -1,6 +1,6 @@
|
|||
{{define "base"}}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<html lang="en" data-theme="light">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
|
@ -13,31 +13,43 @@
|
|||
<link rel="icon" href="/static/img/favicon.svg" type="image/svg+xml">
|
||||
<link title="kafka" type="application/opensearchdescription+xml" rel="search" href="/opensearch.xml">
|
||||
</head>
|
||||
<body class="{{if .Query}}search_on_results{{end}}">
|
||||
<body>
|
||||
<header class="site-header">
|
||||
<span class="site-title">kafka</span>
|
||||
<!-- Desktop trigger (hidden on mobile via CSS) -->
|
||||
<button id="settings-trigger" class="settings-trigger settings-trigger-desktop"
|
||||
aria-label="Preferences" aria-expanded="false" aria-controls="settings-popover">⚙</button>
|
||||
<a href="/" class="site-logo">
|
||||
<svg class="site-logo-mark" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
|
||||
<circle cx="11" cy="11" r="8"/>
|
||||
<path d="m21 21-4.35-4.35"/>
|
||||
</svg>
|
||||
<span class="site-name">kafka</span>
|
||||
</a>
|
||||
<button id="settings-trigger" class="settings-trigger" aria-label="Preferences" aria-expanded="false" aria-controls="settings-popover">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"/>
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
</svg>
|
||||
</button>
|
||||
</header>
|
||||
<!-- Mobile FAB trigger (shown only on mobile via CSS) -->
|
||||
<button id="settings-trigger-mobile" class="settings-trigger settings-trigger-mobile"
|
||||
aria-label="Preferences" aria-expanded="false" aria-controls="settings-popover"
|
||||
style="display:none;">⚙</button>
|
||||
<main>
|
||||
|
||||
<main class="{{if .Query}}page-results{{else}}page-home{{end}}">
|
||||
{{template "content" .}}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>Powered by <a href="https://git.ashisgreat.xyz/penal-colony/kafka">kafka</a> — a privacy-respecting, open metasearch engine</p>
|
||||
</footer>
|
||||
|
||||
<script src="/static/js/settings.js"></script>
|
||||
|
||||
<div id="settings-popover" data-open="false" role="dialog" aria-label="Preferences" aria-modal="true">
|
||||
<div class="settings-popover-header">
|
||||
Preferences
|
||||
<button class="settings-popover-close" aria-label="Close">×</button>
|
||||
<button class="settings-popover-close" aria-label="Close">×</button>
|
||||
</div>
|
||||
<div class="settings-popover-body"></div>
|
||||
</div>
|
||||
|
||||
<div id="autocomplete-dropdown"></div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
'use strict';
|
||||
|
|
@ -50,12 +62,10 @@
|
|||
var activeIndex = -1;
|
||||
var fetchController = null;
|
||||
|
||||
// Escape regex special chars for highlight matching
|
||||
function escapeRegex(str) {
|
||||
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
// Highlight matching prefix
|
||||
function highlight(text, query) {
|
||||
if (!query) return text;
|
||||
var re = new RegExp('^(' + escapeRegex(query) + ')', 'i');
|
||||
|
|
@ -72,7 +82,7 @@
|
|||
var escaped = highlight(suggestions[i], input.value);
|
||||
html += '<div class="autocomplete-suggestion" data-index="' + i + '">' + escaped + '</div>';
|
||||
}
|
||||
html += '<div class="autocomplete-footer">Press <kbd>↑</kbd><kbd>↓</kbd> to navigate, Enter to select, Esc to close</div>';
|
||||
html += '<div class="autocomplete-footer">↑↓ navigate · Enter select · Esc close</div>';
|
||||
dropdown.innerHTML = html;
|
||||
dropdown.classList.add('open');
|
||||
activeIndex = -1;
|
||||
|
|
@ -141,14 +151,13 @@
|
|||
});
|
||||
|
||||
input.addEventListener('blur', function () {
|
||||
// Delay to allow click events on suggestions
|
||||
setTimeout(closeDropdown, 150);
|
||||
});
|
||||
|
||||
dropdown.addEventListener('mousedown', function (e) {
|
||||
var item = e.target.closest('.autocomplete-suggestion');
|
||||
if (item) {
|
||||
e.preventDefault(); // prevent blur from firing before select
|
||||
e.preventDefault();
|
||||
var idx = parseInt(item.getAttribute('data-index'), 10);
|
||||
selectSuggestion(idx);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue