60 lines
2.4 KiB
Vue
60 lines
2.4 KiB
Vue
<script setup lang="ts">
|
|
// The note list, in the desktop sidebar and in the mobile drawer
|
|
const { docs: allDocs, error } = useNotes()
|
|
const { query, matches, searching } = useNotesSearch()
|
|
const docs = computed(() => matches.value ? allDocs.value.filter(doc => matches.value!.includes(doc.id)) : allDocs.value)
|
|
const { closeOnMobile } = useNotesSidebar()
|
|
const deleteDoc = useDeleteNote()
|
|
const route = useRoute()
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<div class="px-2 pb-2">
|
|
<UInput
|
|
v-model="query"
|
|
icon="i-lucide-search"
|
|
placeholder="Search"
|
|
:loading="searching"
|
|
class="w-full"
|
|
@keydown.esc="query = ''"
|
|
>
|
|
<template v-if="query" #trailing>
|
|
<UButton icon="i-lucide-x" color="neutral" variant="link" size="sm" aria-label="Clear search" @click="query = ''" />
|
|
</template>
|
|
</UInput>
|
|
</div>
|
|
|
|
<p v-if="error" class="px-4 text-sm text-error">Couldn't load the notes: {{ errorMessage(error) }}</p>
|
|
|
|
<nav class="px-2 pb-4">
|
|
<!-- The delete button shows on hover on desktop (instead of the date), always on mobile -->
|
|
<div v-for="doc in docs" :key="doc.id" class="group relative">
|
|
<NuxtLink
|
|
:to="`/notes/${doc.id}`"
|
|
class="flex items-baseline gap-2 rounded-md py-2.5 ps-2 pe-11 text-base md:py-1.5 md:pe-2 md:text-sm"
|
|
:class="String(doc.id) === route.params.id ? 'bg-elevated text-highlighted' : 'text-default hover:bg-elevated/50'"
|
|
@click="closeOnMobile"
|
|
>
|
|
<span class="flex-1 truncate" :class="{ 'text-muted': !doc.title }">{{ notesDocName(doc) }}</span>
|
|
<span class="hidden shrink-0 text-xs text-dimmed tabular-nums md:inline md:group-hover:invisible">{{ notesDocDay(doc.created) }}</span>
|
|
</NuxtLink>
|
|
<UButton
|
|
icon="i-lucide-trash-2"
|
|
color="neutral"
|
|
variant="ghost"
|
|
size="sm"
|
|
:aria-label="`Delete ${notesDocName(doc)}`"
|
|
title="Delete"
|
|
class="absolute inset-y-0 end-1 my-auto h-fit text-dimmed hover:text-error md:opacity-0 md:group-hover:opacity-100 md:focus-visible:opacity-100"
|
|
@click="deleteDoc(doc)"
|
|
/>
|
|
</div>
|
|
|
|
<p v-if="!docs.length && !error && !searching" class="px-2 py-4 text-sm text-muted">
|
|
{{ query.trim() ? 'No notes match.' : 'No notes yet.' }}
|
|
</p>
|
|
</nav>
|
|
</div>
|
|
</template>
|