Init svelte components

Signed-off-by: Hadi <hadi@example.com>
This commit is contained in:
Hadi
2026-04-28 16:57:00 +02:00
parent f00515e4c3
commit 1025d5bfa1
16 changed files with 1050 additions and 931 deletions
+115
View File
@@ -0,0 +1,115 @@
---
import { getCategory, extractInlineHashtags } from "../utils/notes";
import type { CollectionEntry } from "astro:content";
interface Props {
notes: CollectionEntry<"notes">[];
currentEntry: CollectionEntry<"notes">;
categories: string[];
}
const { notes, currentEntry, categories } = Astro.props;
---
<style>
/*
* DaisyUI's menu items use display:grid with grid-auto-columns:minmax(auto,max-content)
* which expands to fit content. Override to block so text-overflow:ellipsis works directly.
* Inner <ul> has no w-full so DaisyUI's margin-inline-start/padding-inline-start don't overflow.
*/
.nav-item {
display: block !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
}
</style>
<aside
class="w-56 flex flex-col border-r border-base-300/60 h-[calc(100vh-3rem)]"
style="background: oklch(4% 0 0);"
>
<div class="px-3 py-3 border-b border-base-300/40">
<label
class="input input-sm w-full font-mono text-xs border-base-300/40 bg-base-200/50"
>
<span class="text-base-content/30"></span>
<input
data-search
type="text"
placeholder="search..."
class="text-base-content/70 placeholder:text-base-content/25"
/>
</label>
</div>
<ul
class="nav-sidebar menu menu-xs flex-1 min-h-0 overflow-y-auto overflow-x-hidden px-2 py-2 bg-transparent"
>
{
categories.map((cat) => (
<li class="w-full">
<details open={cat === getCategory(currentEntry)}>
<summary class="font-bold tracking-tight text-sm">
<span class="text-primary/50 font-mono">/</span>
{cat}
</summary>
<ul>
{notes
.filter((n) => getCategory(n) === cat)
.map((n) => (
<li>
<a
href={`/notes/${n.id}`}
class:list={[
"nav-item font-mono text-xs tooltip tooltip-right",
n.id === currentEntry.id ? "active" : "",
]}
data-tip={n.data.title}
data-title={n.data.title.toLowerCase()}
data-tags={[
...n.data.tags,
...extractInlineHashtags(n.body ?? ""),
].join(",")}
>
{n.data.title}
</a>
</li>
))}
</ul>
</details>
</li>
))
}
</ul>
</aside>
<script>
document.addEventListener("astro:page-load", () => {
const navItems = document.querySelectorAll<HTMLElement>(".nav-item");
document
.querySelectorAll<HTMLInputElement>("[data-search]")
.forEach((input) => {
input.addEventListener("input", (e) => {
const target = e.target as HTMLInputElement;
const raw = target.value.toLowerCase().trim();
document
.querySelectorAll<HTMLInputElement>("[data-search]")
.forEach((o) => {
if (o !== target) o.value = target.value;
});
const isTag = raw.startsWith("#");
const search = isTag ? raw.slice(1) : raw;
navItems.forEach((item) => {
const title = item.dataset.title ?? "";
const tags = item.dataset.tags ? item.dataset.tags.split(",") : [];
const match =
!search ||
(isTag
? tags.some((t) => t.includes(search))
: title.includes(search) || tags.join(",").includes(search));
item.style.display = match ? "" : "none";
});
});
});
});
</script>