diff --git a/pkg/appview/static/css/style.css b/pkg/appview/static/css/style.css index fcfff11..69ae194 100644 --- a/pkg/appview/static/css/style.css +++ b/pkg/appview/static/css/style.css @@ -153,18 +153,62 @@ body { color: var(--primary); } -.nav-search { - flex: 1; - max-width: 400px; - margin: 0 2rem; +/* Expandable search */ +.nav-search-wrapper { + position: relative; + display: flex; + align-items: center; } -.nav-search input { +.search-toggle-btn { + display: inline-flex; + align-items: center; + justify-content: center; + background: transparent; + border: none; + color: var(--navbar-fg); + cursor: pointer; + padding: 0.5rem; + border-radius: 4px; +} + +.search-toggle-btn:hover { + background: var(--secondary); +} + +.search-toggle-btn .search-icon { + width: 1.25rem; + height: 1.25rem; +} + +.nav-search-form { + position: absolute; + right: 100%; + width: 0; + opacity: 0; + overflow: hidden; + transition: width 0.3s ease, opacity 0.3s ease; + margin-right: 0.5rem; +} + +.nav-search-wrapper.expanded .nav-search-form { + width: 250px; + opacity: 1; +} + +.nav-search-form input { width: 100%; padding: 0.5rem 1rem; border: none; border-radius: 4px; font-size: 0.95rem; + background: var(--bg); + color: var(--fg); +} + +.nav-search-form input:focus { + outline: 2px solid var(--primary); + outline-offset: -2px; } .nav-links { @@ -2078,9 +2122,8 @@ a.license-badge:hover { gap: 1rem; } - .nav-search { - max-width: 100%; - margin: 0; + .nav-search-wrapper.expanded .nav-search-form { + width: 200px; } .push-details { diff --git a/pkg/appview/static/js/app.js b/pkg/appview/static/js/app.js index 83503ee..231b517 100644 --- a/pkg/appview/static/js/app.js +++ b/pkg/appview/static/js/app.js @@ -35,6 +35,50 @@ function updateThemeIcon() { themeBtn.setAttribute('aria-label', currentTheme === 'dark' ? 'Switch to light mode' : 'Switch to dark mode'); } +// Expandable search +function toggleSearch() { + const wrapper = document.querySelector('.nav-search-wrapper'); + const input = document.getElementById('nav-search-input'); + + if (!wrapper || !input) return; + + wrapper.classList.toggle('expanded'); + + if (wrapper.classList.contains('expanded')) { + input.focus(); + } +} + +function closeSearch() { + const wrapper = document.querySelector('.nav-search-wrapper'); + if (wrapper) { + wrapper.classList.remove('expanded'); + } +} + +// Close search on Escape key and click outside +document.addEventListener('DOMContentLoaded', () => { + const wrapper = document.querySelector('.nav-search-wrapper'); + const input = document.getElementById('nav-search-input'); + + if (!wrapper || !input) return; + + // Close on Escape key + document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && wrapper.classList.contains('expanded')) { + closeSearch(); + } + }); + + // Close on click outside + document.addEventListener('click', (e) => { + if (wrapper.classList.contains('expanded') && + !wrapper.contains(e.target)) { + closeSearch(); + } + }); +}); + // Copy to clipboard function copyToClipboard(text) { navigator.clipboard.writeText(text).then(() => { diff --git a/pkg/appview/templates/components/nav-search.html b/pkg/appview/templates/components/nav-search.html index 61f1d07..ca0e9be 100644 --- a/pkg/appview/templates/components/nav-search.html +++ b/pkg/appview/templates/components/nav-search.html @@ -1,7 +1,10 @@ {{ define "nav-search" }} -