mirror of
https://github.com/kogakure/website-astro-stefanimhoff.de.git
synced 2026-02-03 12:05:28 +00:00
feat: add site search with pagefind
This commit is contained in:
@@ -2,10 +2,11 @@
|
||||
import { Link } from '.';
|
||||
|
||||
import navigation from '../data/navigation.json';
|
||||
import SearchLink from './SearchLink.astro';
|
||||
---
|
||||
|
||||
<nav
|
||||
class="navigation col-span-12 col-start-4 self-center md:col-span-14 md:col-start-3"
|
||||
class="navigation col-span-12 col-start-4 flex items-center self-center md:col-span-14 md:col-start-3"
|
||||
role="navigation"
|
||||
aria-label="Main"
|
||||
>
|
||||
@@ -23,4 +24,5 @@ import navigation from '../data/navigation.json';
|
||||
))
|
||||
}
|
||||
</ul>
|
||||
<SearchLink />
|
||||
</nav>
|
||||
|
||||
@@ -15,6 +15,7 @@ import '../styles/sal.css';
|
||||
declare const sal: any;
|
||||
|
||||
const swup = new Swup({
|
||||
ignoreVisit: (url, { el } = {}) => el?.closest('[data-pagefind-ui] a'),
|
||||
plugins: [
|
||||
new SwupFadeTheme(),
|
||||
new SwupHeadPlugin(),
|
||||
@@ -41,6 +42,7 @@ import '../styles/sal.css';
|
||||
}
|
||||
}
|
||||
|
||||
// Register scripts after swup page transition
|
||||
swup.on('pageView', () => {
|
||||
if (typeof sal !== 'undefined') {
|
||||
sal({
|
||||
@@ -50,6 +52,8 @@ import '../styles/sal.css';
|
||||
setActiveLink();
|
||||
setUpLink();
|
||||
setEmailLink();
|
||||
setSearchModalLink();
|
||||
setSearchLink();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -78,6 +82,45 @@ import '../styles/sal.css';
|
||||
});
|
||||
}
|
||||
|
||||
function setSearchLink() {
|
||||
const dialog = document.querySelector('dialog');
|
||||
const openDialogLink = document.getElementById('search-link');
|
||||
|
||||
openDialogLink?.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
dialog?.showModal();
|
||||
});
|
||||
|
||||
document.addEventListener('keydown', (event) => {
|
||||
if (event.key === '/') {
|
||||
event.preventDefault();
|
||||
dialog?.showModal();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function setSearchModalLink() {
|
||||
const dialog = document.querySelector('dialog');
|
||||
|
||||
dialog?.addEventListener('click', (event) => {
|
||||
if (event.target === dialog) {
|
||||
if (!dialog.classList.contains('hide')) {
|
||||
dialog.classList.add('hide');
|
||||
dialog.addEventListener(
|
||||
'animationend',
|
||||
(animationEvent) => {
|
||||
if (animationEvent.animationName === 'hide-modal') {
|
||||
dialog.close();
|
||||
dialog.classList.remove('hide');
|
||||
}
|
||||
},
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function handleEmailClick(event: Event) {
|
||||
event.preventDefault();
|
||||
const currentTarget = event.currentTarget;
|
||||
@@ -101,6 +144,8 @@ import '../styles/sal.css';
|
||||
setActiveLink();
|
||||
setUpLink();
|
||||
setEmailLink();
|
||||
setSearchLink();
|
||||
setSearchModalLink();
|
||||
</script>
|
||||
|
||||
<style is:global>
|
||||
|
||||
20
src/components/SearchLink.astro
Normal file
20
src/components/SearchLink.astro
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
import { Sprite } from 'astro-icon';
|
||||
|
||||
import { Link } from '.';
|
||||
---
|
||||
|
||||
<Link
|
||||
class="col-span-2 col-start-1 h-clickarea w-clickarea items-center justify-center self-center justify-self-center transition-transform duration-500 ease-in-out hover:scale-75 focus:scale-75 print:hidden md:col-span-1"
|
||||
id="search-link"
|
||||
title="Search (/)"
|
||||
>
|
||||
<button
|
||||
aria-label="Search the website (/)"
|
||||
class="flex h-clickarea w-clickarea cursor-pointer items-center justify-center border-none text-[0]"
|
||||
tabindex={-1}
|
||||
type="button"
|
||||
>
|
||||
<Sprite name="ri:search-line" class="h-icon w-icon" />
|
||||
</button>
|
||||
</Link>
|
||||
118
src/components/SearchModal.astro
Normal file
118
src/components/SearchModal.astro
Normal file
@@ -0,0 +1,118 @@
|
||||
---
|
||||
import Search from 'astro-pagefind/components/Search';
|
||||
---
|
||||
|
||||
<dialog>
|
||||
<Search />
|
||||
</dialog>
|
||||
|
||||
<style is:global>
|
||||
dialog::backdrop {
|
||||
@apply bg-black/50 backdrop-blur-sm;
|
||||
animation: show-dimmer 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
dialog.hide::backdrop {
|
||||
animation: hide-dimmer 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
dialog[open] {
|
||||
@apply h-[80vh] w-[80vw] max-w-[40em] bg-shibui-100 font-sans font-normal leading-relaxed text-shibui-950 common-ligatures dark:border-1 dark:border-solid dark:border-shibui-200/[0.25] dark:bg-shibui-900 dark:text-shibui-200/[0.87];
|
||||
animation: show-modal 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
dialog.hide {
|
||||
animation: hide-modal 0.5s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes show-modal {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(50px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes show-dimmer {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hide-modal {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: translateY(50px);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes hide-dimmer {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.pagefind-ui {
|
||||
@apply bg-shibui-100 !font-sans !font-normal !leading-relaxed text-shibui-950 common-ligatures dark:bg-shibui-900 dark:text-shibui-200/[0.87];
|
||||
}
|
||||
|
||||
.pagefind-ui__form::before {
|
||||
@apply !hidden;
|
||||
}
|
||||
|
||||
.pagefind-ui__search-input,
|
||||
.pagefind-ui__search-clear {
|
||||
@apply !bg-shibui-100 !text-shibui-950 dark:!bg-shibui-850 dark:!text-shibui-200/[0.87];
|
||||
}
|
||||
|
||||
.pagefind-ui__search-input {
|
||||
@apply !border-1 !border-solid !border-shibui-900/[0.25] !bg-shibui-100 !text-shibui-950 !pis-7 dark:!border-shibui-200/[0.25] dark:!bg-shibui-850 dark:!text-shibui-200/[0.87];
|
||||
}
|
||||
|
||||
.pagefind-ui__search-clear {
|
||||
@apply !inline-end-4;
|
||||
}
|
||||
|
||||
.pagefind-ui__result {
|
||||
@apply !border-solid !border-black/[0.1] !border-be-1 !border-bs-0 !border-ie-0 !border-is-0 dark:!border-white/[0.1];
|
||||
}
|
||||
|
||||
.pagefind-ui__result-inner,
|
||||
.pagefind-ui__message,
|
||||
.pagefind-ui__result-link {
|
||||
@apply !text-shibui-950 dark:!text-shibui-200/[0.87];
|
||||
}
|
||||
|
||||
.pagefind-ui__result-link {
|
||||
@apply inline !font-semibold !text-shibui-950 underline !decoration-shibui-900/20 !decoration-4 underline-offset-auto no-common-ligatures hover:!decoration-accent focus:!decoration-accent dark:!text-shibui-100;
|
||||
}
|
||||
|
||||
.pagefind-ui .pagefind-ui__result-link {
|
||||
@apply !text-3 !font-black leading-tight;
|
||||
}
|
||||
|
||||
.pagefind-ui .pagefind-ui__result-excerpt {
|
||||
@apply !text-2;
|
||||
}
|
||||
|
||||
.pagefind-ui__result-excerpt mark {
|
||||
@apply !rounded !border !border-black/[0.1] !bg-marked !text-black/[0.75] !pli-[0.3em] !pbe-[0.2em] !pbs-[0.3em] dark:!bg-marked/[0.7];
|
||||
}
|
||||
|
||||
.pagefind-ui__button {
|
||||
@apply !border-1 !border-solid !border-shibui-900/[0.25] !bg-shibui-200 !text-shibui-950 hover:!bg-shibui-300 dark:!border-shibui-200/[0.25] dark:!bg-shibui-950 dark:!text-shibui-200/[0.87] dark:hover:!bg-shibui-800;
|
||||
}
|
||||
</style>
|
||||
@@ -8,6 +8,7 @@ import { isProduction } from '../utils';
|
||||
import ThemeProvider from '../components/ThemeProvider.astro';
|
||||
import PageHeader from '../components/PageHeader.astro';
|
||||
import PageFooter from '../components/PageFooter.astro';
|
||||
import SearchModal from '../components/SearchModal.astro';
|
||||
import Scripts from '../components/Scripts.astro';
|
||||
|
||||
export interface Props {
|
||||
@@ -44,6 +45,7 @@ const schema = JSON.stringify({
|
||||
url: site.url,
|
||||
});
|
||||
|
||||
const pagefind = !noindex && { 'data-pagefind-body': '' };
|
||||
const webManifest = isProduction && {
|
||||
rel: 'manifest',
|
||||
href: '/manifest.webmanifest',
|
||||
@@ -164,13 +166,14 @@ const webManifest = isProduction && {
|
||||
<Sprite.Provider>
|
||||
{header && <PageHeader backLink={backLink} />}
|
||||
<div class="page-content flex grow">
|
||||
<main class="h-full w-full">
|
||||
<main class="h-full w-full" {...pagefind}>
|
||||
<slot />
|
||||
</main>
|
||||
</div>
|
||||
{footer && <PageFooter />}
|
||||
</Sprite.Provider>
|
||||
</div>
|
||||
<SearchModal />
|
||||
<script>
|
||||
console.info(
|
||||
'👋 I see you’re interested in the source code of this site? You can find it here 👉 https://github.com/kogakure/website-astro-stefanimhoff.de'
|
||||
|
||||
@@ -33,6 +33,7 @@ const description = 'This is a collection of AI art pieces I’ve created with S
|
||||
</article>
|
||||
|
||||
<nav class="col-start-1 col-end-18 md:col-start-1 md:col-end-16" aria-label="AI Art">
|
||||
data-pagefind-ignore
|
||||
<ol
|
||||
class="gap-[max(25px,_2vw)] md:grid md:grid-flow-row-dense md:auto-rows-[50px] md:grid-cols-[repeat(auto-fit,_minmax(50px,_1fr))] md:grid-rows-[50px]"
|
||||
>
|
||||
|
||||
@@ -39,6 +39,7 @@ The source code of this website is available on [GitHub](https://github.com/koga
|
||||
- The scroll animations are created with [Sal](https://mciastek.github.io/sal/) and for page transitions I use [Swup](https://swup.js.org/).
|
||||
- Icons are handled by [Astro Icon](https://github.com/natemoo-re/astro-icon).
|
||||
- All images are optimized with [Astro ImageTools](https://github.com/RafidMuhymin/astro-imagetools/).
|
||||
- My site search is build with [Pagefind](https://pagefind.app/) using the [Astro-Pagefind](https://github.com/shishkin/astro-pagefind) integration.
|
||||
- I use YouTube Lite, provided by [Astro Embed](https://github.com/astro-community/astro-embed).
|
||||
- [Astro SEO](https://github.com/jonasmerlin/astro-seo) makes it easy to add the SEO relevant information.
|
||||
- I use [Astro Webmanifest](https://github.com/alextim/astro-lib/tree/main/packages/astro-webmanifest) and [Astro Service Worker](https://github.com/tatethurston/astrojs-service-worker) to optimize the website.
|
||||
|
||||
@@ -30,8 +30,9 @@ const description =
|
||||
</article>
|
||||
|
||||
<nav
|
||||
class="col-start-1 col-end-17 print:hidden md:col-start-2 md:col-end-14"
|
||||
aria-label="Haiku"
|
||||
class="col-start-1 col-end-17 print:hidden md:col-start-2 md:col-end-14"
|
||||
data-pagefind-ignore
|
||||
>
|
||||
<ol
|
||||
class="grid list-none grid-cols-[repeat(auto-fill,_minmax(3rem,_1fr))] justify-items-center gap-[1rem]"
|
||||
|
||||
@@ -87,6 +87,7 @@ rssPosts.sort(sortMarkdownByDate);
|
||||
|
||||
<article
|
||||
class="min-[1794px]:[&_li:block col-start-2 col-end-18 grid w-full grid-cols-18 gap-y-gap mbe-12 min-[1097px]:[&_li:nth-child(n+5)]:hidden min-[1410px]:[&_li:nth-child(n+5)]:block min-[1411px]:[&_li:nth-child(n+6)]:hidden min-[1793px]:[&_li:nth-child(n+6)]:block"
|
||||
data-pagefind-ignore
|
||||
{...animation}
|
||||
>
|
||||
<JournalList entries={formattedLatest} />
|
||||
|
||||
@@ -29,6 +29,7 @@ const description = 'I am writing essays about various topics in this Journal.';
|
||||
|
||||
<article
|
||||
class="col-start-1 col-end-18 grid md:col-start-4 md:col-end-12 xl:col-start-5 xl:col-end-11"
|
||||
data-pagefind-ignore
|
||||
{...animation}
|
||||
>
|
||||
<Intro components={mapping} />
|
||||
|
||||
@@ -32,8 +32,9 @@ const description = 'This is a collection of Sketchnotes I’ve drawn.';
|
||||
</article>
|
||||
|
||||
<nav
|
||||
class="col-start-1 col-end-18 w-full md:col-start-1 md:col-end-16"
|
||||
aria-label="Sketchnotes"
|
||||
class="col-start-1 col-end-18 w-full md:col-start-1 md:col-end-16"
|
||||
data-pagefind-ignore
|
||||
>
|
||||
<ol
|
||||
class="gap-[max(25px,_2vw)] print:block md:grid md:grid-flow-row-dense md:auto-rows-[50px] md:grid-cols-[repeat(auto-fit,_minmax(50px,_1fr))] md:grid-rows-[50px]"
|
||||
|
||||
Reference in New Issue
Block a user