260 lines
9.2 KiB
Plaintext
260 lines
9.2 KiB
Plaintext
---
|
|
// Heavy inspiration taken from Astro Starlight -> https://github.com/withastro/starlight/blob/main/packages/starlight/components/Search.astro
|
|
|
|
import "@pagefind/default-ui/css/ui.css";
|
|
import { Icon } from "astro-icon/components";
|
|
---
|
|
|
|
<site-search class="ms-auto" id="search">
|
|
<button
|
|
class="flex h-8 w-8 items-center justify-center rounded-lg drop-shadow-[0px_1.5px_1.5px_rgba(0,0,0,0.175)] hover:text-accent-two"
|
|
data-open-modal
|
|
disabled
|
|
>
|
|
<Icon aria-hidden="true" class="h-6 w-6" focusable="false" name="hugeicons:search-01" />
|
|
</button>
|
|
|
|
<dialog
|
|
aria-label="search"
|
|
class="h-full max-h-full w-full max-w-full md:h-fit bg-bgColor backdrop:backdrop-blur-xl md:my-8 md:min-h-[6.5rem] 'md:w-5/6' md:max-w-[44rem] md:rounded-lg overflow-y-hidden"
|
|
>
|
|
<div class="dialog-frame flex flex-col h-[100%] px-4 pt-4 pb-4 md:px-8 md:py-8 gap-4">
|
|
<!-- Заголовок и кнопка закрытия -->
|
|
<div class="md:hidden sticky top-0 z-20 flex items-center justify-between bg-bgColor">
|
|
<h4 class="title flex items-end font-semibold">Search</h4>
|
|
<button
|
|
class="flex size-8 cursor-pointer items-center justify-center rounded-lg bg-color-100 text-textColor hover:text-accent-base hover:bg-accent-base/5"
|
|
data-close-modal
|
|
>
|
|
<Icon aria-hidden="true" class="h-6 w-6" focusable="false" name="hugeicons:cancel-01" />
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Содержимое -->
|
|
{
|
|
import.meta.env.DEV ? (
|
|
<div class="mx-auto text-center text-textColor">
|
|
<p>
|
|
Search is only available in production builds. <br />
|
|
Try building and previewing the site to test it out locally.
|
|
</p>
|
|
</div>
|
|
) : (
|
|
<div class="search-container h-full">
|
|
<div id="citrus__search" />
|
|
</div>
|
|
)
|
|
}
|
|
</div>
|
|
</dialog>
|
|
</site-search>
|
|
|
|
<script>
|
|
class SiteSearch extends HTMLElement {
|
|
private closeBtn: HTMLButtonElement;
|
|
private dialog: HTMLDialogElement;
|
|
private dialogFrame: HTMLDivElement;
|
|
private openBtn: HTMLButtonElement;
|
|
|
|
closeModal = () => {
|
|
if (this.dialog.open) {
|
|
this.dialog.close();
|
|
document.body.classList.remove("overflow-hidden");
|
|
window.removeEventListener("click", this.onWindowClick);
|
|
}
|
|
};
|
|
|
|
onWindowClick = (event: MouseEvent) => {
|
|
// Check if it's a link
|
|
const isLink = "href" in (event.target || {});
|
|
// Make sure the click is either a link or outside of the dialog
|
|
if (
|
|
isLink ||
|
|
(document.body.contains(event.target as Node) &&
|
|
!this.dialogFrame.contains(event.target as Node))
|
|
)
|
|
this.closeModal();
|
|
};
|
|
|
|
onWindowKeydown = (e: KeyboardEvent) => {
|
|
// Check if it's the / key
|
|
if (e.key === "/" && !this.dialog.open) {
|
|
this.openModal();
|
|
e.preventDefault();
|
|
}
|
|
};
|
|
|
|
openModal = (event?: MouseEvent) => {
|
|
this.dialog.showModal();
|
|
document.body.classList.add("overflow-hidden");
|
|
this.querySelector("input")?.focus();
|
|
event?.stopPropagation();
|
|
window.addEventListener("click", this.onWindowClick);
|
|
};
|
|
|
|
constructor() {
|
|
super();
|
|
this.openBtn = this.querySelector<HTMLButtonElement>("button[data-open-modal]")!;
|
|
this.closeBtn = this.querySelector<HTMLButtonElement>("button[data-close-modal]")!;
|
|
this.dialog = this.querySelector("dialog")!;
|
|
this.dialogFrame = this.querySelector(".dialog-frame")!;
|
|
|
|
this.openBtn.addEventListener("click", this.openModal);
|
|
this.openBtn.disabled = false;
|
|
this.closeBtn.addEventListener("click", this.closeModal);
|
|
}
|
|
|
|
connectedCallback() {
|
|
// Listen for keyboard shortcut
|
|
window.addEventListener("keydown", this.onWindowKeydown);
|
|
|
|
// Only add pagefind in production
|
|
if (import.meta.env.DEV) return;
|
|
const onIdle = window.requestIdleCallback || ((cb) => setTimeout(cb, 1));
|
|
onIdle(async () => {
|
|
const { PagefindUI } = await import("@pagefind/default-ui");
|
|
new PagefindUI({
|
|
baseUrl: import.meta.env.BASE_URL,
|
|
bundlePath: import.meta.env.BASE_URL.replace(/\/$/, "") + "/pagefind/",
|
|
element: "#citrus__search",
|
|
showImages: false,
|
|
showSubResults: true,
|
|
});
|
|
});
|
|
}
|
|
|
|
disconnectedCallback() {
|
|
window.removeEventListener("keydown", this.onWindowKeydown);
|
|
}
|
|
}
|
|
|
|
customElements.define("site-search", SiteSearch);
|
|
</script>
|
|
|
|
<style is:global>
|
|
:root {
|
|
--pagefind-ui-border-radius: 0.5rem; /* 8px */
|
|
}
|
|
|
|
#citrus__search {
|
|
--pagefind-ui-primary: theme("colors.accent-two");
|
|
--pagefind-ui-text: theme("colors.textColor");
|
|
--pagefind-ui-background: theme("colors.bgColor");
|
|
--pagefind-ui-border: theme("colors.color.400");
|
|
@apply h-full;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui {
|
|
@apply w-full h-full text-textColor font-sans;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__hidden {
|
|
@apply hidden;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__suppressed {
|
|
@apply opacity-0 pointer-events-none;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__form {
|
|
@apply relative h-full;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__form::before {
|
|
@apply absolute pointer-events-none block opacity-70 z-10 size-4 top-3 left-3;
|
|
content: "";
|
|
-webkit-mask-image:
|
|
url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");
|
|
mask-image:
|
|
url("data:image/svg+xml,%3Csvg width='18' height='18' viewBox='0 0 18 18' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12.7549 11.255H11.9649L11.6849 10.985C12.6649 9.845 13.2549 8.365 13.2549 6.755C13.2549 3.165 10.3449 0.255005 6.75488 0.255005C3.16488 0.255005 0.254883 3.165 0.254883 6.755C0.254883 10.345 3.16488 13.255 6.75488 13.255C8.36488 13.255 9.84488 12.665 10.9849 11.685L11.2549 11.965V12.755L16.2549 17.745L17.7449 16.255L12.7549 11.255ZM6.75488 11.255C4.26488 11.255 2.25488 9.245 2.25488 6.755C2.25488 4.26501 4.26488 2.255 6.75488 2.255C9.24488 2.255 11.2549 4.26501 11.2549 6.755C11.2549 9.245 9.24488 11.255 6.75488 11.255Z' fill='%23000000'/%3E%3C/svg%3E%0A");
|
|
-webkit-mask-size: 100%;
|
|
mask-size: 100%;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__search-input {
|
|
@apply bg-color-100 rounded-lg border-none text-base text-textColor font-normal w-full flex h-10 py-0 px-10 outline-none;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__search-input::placeholder {
|
|
@apply opacity-20;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__search-clear::before {
|
|
@apply bg-accent-two block w-full h-full;
|
|
content: "";
|
|
-webkit-mask:
|
|
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='currentColor' %3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M6 18L18 6M6 6l12 12'%3E%3C/path%3E%3C/svg%3E")
|
|
center / 60% no-repeat;
|
|
mask:
|
|
url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='currentColor' %3E%3Cpath stroke-linecap='round' stroke-linejoin='round' d='M6 18L18 6M6 6l12 12'%3E%3C/path%3E%3C/svg%3E")
|
|
center / 60% no-repeat;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__search-clear {
|
|
@apply overflow-hidden absolute top-0 right-0 size-10 py-0 px-0 text-textColor font-medium cursor-pointer bg-transparent rounded-lg;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__search-clear:focus {
|
|
/* Доработать */
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__drawer {
|
|
@apply flex flex-wrap md:h-[calc(100vh-10.5rem)] h-full pb-0 m-auto;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__message {
|
|
@apply text-base font-normal text-lighter h-10 py-0 flex items-center border-none;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__button {
|
|
@apply absolute bottom-0 m-0 shadow-md border-none text-bgColor flex items-center justify-center rounded-lg h-10 py-0 px-2 text-base text-center font-medium cursor-pointer bg-accent-base;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__button:hover {
|
|
@apply brightness-110;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__result {
|
|
@apply border-none p-0 mb-8;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__result:last-of-type {
|
|
@apply mb-0;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__result-link {
|
|
@apply title text-base bg-transparent text-accent-base font-medium;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__result-link:hover {
|
|
/* Добаботать */
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__result-nested {
|
|
@apply ps-4;
|
|
}
|
|
#citrus__search .pagefind-ui__result-nested:first-of-type {
|
|
@apply pt-0;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__result-excerpt {
|
|
@apply inline-block font-normal text-base text-textColor mt-0 mb-0 md:line-clamp-1 mr-2;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__result-inner {
|
|
@apply flex-1 flex flex-col items-start mt-0;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__results {
|
|
@apply p-0 text-textColor text-base max-h-[calc(100vh-13.5rem)] md:max-h-[calc(100vh-13rem)] overflow-y-auto;
|
|
}
|
|
|
|
#citrus__search .pagefind-ui__results-area {
|
|
@apply flex-1 mt-0 mb-0;
|
|
/* min-width: min(25rem, 100%); */ /* 400px */
|
|
}
|
|
|
|
#citrus__search mark {
|
|
@apply text-accent-two bg-transparent;
|
|
}
|
|
</style> |