diff --git a/apps/web/src/components/Lander.astro b/apps/web/src/components/Lander.astro index 25a62cbe8..bd368010b 100644 --- a/apps/web/src/components/Lander.astro +++ b/apps/web/src/components/Lander.astro @@ -14,14 +14,22 @@ @@ -45,6 +53,14 @@ GitHub +
@@ -340,7 +356,7 @@ tests: .av-nav-links { display: flex; align-items: center; - gap: 1.5rem; + gap: 1.25rem; } .av-nav-links > a { @@ -355,6 +371,128 @@ tests: color: var(--av-text); } +.av-nav-github { + display: flex; + align-items: center; + color: hsl(240, 5%, 65%) !important; + transition: color 0.15s !important; +} + +.av-nav-github:hover { + color: var(--av-text) !important; +} + +/* Search button */ +.av-nav-search { + all: unset; + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.35rem 0.75rem; + border: 1px solid var(--av-surface-border); + border-radius: 0.5rem; + background: var(--av-surface); + color: hsl(240, 5%, 65%); + font-size: 0.8rem; + font-family: inherit; + cursor: pointer; + transition: border-color 0.15s, color 0.15s, background 0.15s; + white-space: nowrap; + min-width: 12rem; +} + +.av-nav-search:hover { + border-color: hsl(240, 5%, 40%); + color: var(--av-text-muted); + background: hsl(240, 10%, 14%); +} + +.av-nav-search-label { + color: inherit; + flex: 1; + text-align: left; +} + +.av-nav-search-kbd { + display: inline-flex; + gap: 0.2rem; + margin-left: auto; +} + +.av-nav-search-kbd kbd { + display: inline-block; + padding: 0.1rem 0.35rem; + border: 1px solid hsl(240, 5%, 30%); + border-radius: 0.25rem; + background: hsl(240, 10%, 12%); + font-family: inherit; + font-size: 0.7rem; + line-height: 1.3; + color: hsl(240, 5%, 50%); +} + +/* Search dialog */ +.av-search-dialog { + position: fixed; + inset: 0; + margin: 0; + padding: 0; + border: 0; + width: 100%; + max-width: 100%; + height: 100%; + max-height: 100%; + background: transparent; +} + +.av-search-dialog::backdrop { + background: rgba(0, 0, 0, 0.6); + backdrop-filter: blur(4px); +} + +.av-search-dialog[open] { + display: flex; + justify-content: center; + align-items: flex-start; +} + +.av-search-dialog-frame { + position: relative; + margin-top: 4rem; + width: 90%; + max-width: 40rem; + max-height: calc(100vh - 8rem); + overflow: auto; + background: hsl(240, 10%, 10%); + border: 1px solid var(--av-surface-border); + border-radius: 0.5rem; + padding: 1.5rem; + box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.5); +} + +.av-search-close { + position: absolute; + top: 0.75rem; + right: 0.75rem; + display: flex; + align-items: center; + justify-content: center; + width: 2rem; + height: 2rem; + border: none; + border-radius: 0.375rem; + background: transparent; + color: hsl(240, 5%, 50%); + cursor: pointer; + transition: color 0.15s, background 0.15s; + z-index: 1; +} + +.av-search-close:hover { + color: var(--av-text); + background: hsl(240, 10%, 16%); +} + .av-nav-pill { all: unset; display: flex; @@ -464,6 +602,38 @@ tests: display: flex; gap: 0.875rem; flex-wrap: wrap; + align-items: center; +} + +.av-hero-install { + all: unset; + display: inline-flex; + align-items: center; + gap: 0.5rem; + cursor: pointer; + padding: 0.4rem 0.75rem; + background: var(--av-surface); + border: 1px solid var(--av-surface-border); + border-radius: 6px; + font-family: var(--av-font-mono); + font-size: 0.8rem; + color: hsl(240, 5%, 65%); + transition: border-color 0.15s, color 0.15s; + margin-top: 1.5rem; +} + +.av-hero-install:hover { + border-color: var(--av-indigo); + color: hsl(240, 5%, 85%); +} + +.av-hero-install-prompt { + color: var(--av-cyan); + font-weight: 600; +} + +.av-hero-install code { + font-family: inherit; } .av-btn-primary { @@ -1024,10 +1194,19 @@ td code { grid-template-columns: 1fr; } - .av-nav-pill { + .av-nav-search { + min-width: auto; + } + + .av-nav-search-label, + .av-nav-search-kbd { display: none; } + .av-hero-install { + font-size: 0.75rem; + } + .av-table-fade { display: block; position: absolute; @@ -1126,6 +1305,87 @@ td code { }); }); + // Search modal + const searchBtn = document.getElementById('av-nav-search'); + const dialog = document.getElementById('av-search-dialog') as HTMLDialogElement; + let pagefindLoaded = false; + + function openSearch() { + dialog.showModal(); + document.body.style.overflow = 'hidden'; + if (!pagefindLoaded) { + pagefindLoaded = true; + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = '/pagefind/pagefind-ui.css'; + document.head.appendChild(link); + const darkStyles = document.createElement('style'); + darkStyles.textContent = ` + #av-search-container { + --pagefind-ui-scale: 0.8; + --pagefind-ui-primary: #e2e8f0; + --pagefind-ui-text: #cbd5e1; + --pagefind-ui-font: system-ui, -apple-system, sans-serif; + --pagefind-ui-background: hsl(240,10%,6%); + --pagefind-ui-border: #475569; + --pagefind-ui-border-width: 1px; + --pagefind-ui-tag: #475569; + } + #av-search-container .pagefind-ui__form::before { --pagefind-ui-text: #e2e8f0; opacity: 1; } + #av-search-container .pagefind-ui__search-input { color: #f8fafc; font-weight: 400; } + #av-search-container input:focus { --pagefind-ui-border: #06b6d4; } + #av-search-container .pagefind-ui__search-clear { width: calc(60px * var(--pagefind-ui-scale)); padding: 0; background-color: transparent; overflow: hidden; } + `; + document.head.appendChild(darkStyles); + const script = document.createElement('script'); + script.src = '/pagefind/pagefind-ui.js'; + script.onload = () => { + // @ts-ignore + new PagefindUI({ element: '#av-search-container', showImages: false, showSubResults: true, baseUrl: '/' }); + setTimeout(() => { + const input = dialog.querySelector('.pagefind-ui__search-input'); + if (input) input.focus(); + }, 50); + }; + document.head.appendChild(script); + } else { + setTimeout(() => { + const input = dialog.querySelector('.pagefind-ui__search-input'); + if (input) { input.focus(); input.select(); } + }, 50); + } + } + + function closeSearch() { + dialog.close(); + document.body.style.overflow = ''; + } + + if (searchBtn) searchBtn.addEventListener('click', openSearch); + const closeSearchBtn = document.getElementById('av-search-close'); + if (closeSearchBtn) closeSearchBtn.addEventListener('click', closeSearch); + dialog?.addEventListener('click', (e) => { if (e.target === dialog) closeSearch(); }); + dialog?.addEventListener('close', () => { document.body.style.overflow = ''; }); + dialog?.addEventListener('click', (e) => { + const target = e.target as HTMLElement; + if (target.closest('a[href]')) closeSearch(); + }); + + document.addEventListener('keydown', (e) => { + if ((e.ctrlKey || e.metaKey) && e.key === 'k') { + e.preventDefault(); + dialog?.open ? closeSearch() : openSearch(); + } + if (e.key === 'Escape' && dialog?.open) closeSearch(); + }); + + // Update kbd hint for Mac + if (navigator.platform.includes('Mac') || navigator.userAgent.includes('Mac')) { + document.querySelectorAll('.av-nav-search-kbd').forEach((el) => { + el.innerHTML = '\u2318K'; + }); + } + // Nav scroll detection const nav = document.getElementById("av-nav"); if (nav) {