Files
SIRH/frontend/components/documentation/DocumentationPage.vue

68 lines
2.4 KiB
Vue

<template>
<div class="h-full flex gap-8">
<!-- Table des matières -->
<nav class="w-64 flex-shrink-0 overflow-y-auto pr-4 border-r border-neutral-200">
<h1 class="text-xl font-bold text-primary-500 mb-6">Documentation</h1>
<div v-for="section in visibleSections" :key="section.id" class="mb-4">
<div class="flex items-center gap-2 mb-1">
<Icon :name="section.icon" size="18" class="text-neutral-500"/>
<span class="text-sm font-semibold text-neutral-700">{{ section.title }}</span>
</div>
<ul class="pl-7 space-y-0.5">
<li v-for="article in section.articles" :key="article.id">
<button
class="text-xs text-neutral-500 hover:text-primary-500 text-left w-full py-0.5 transition-colors"
:class="activeArticleId === article.id ? 'text-primary-500 font-bold' : ''"
@click="scrollToArticle(article.id)"
>
{{ article.title }}
</button>
</li>
</ul>
</div>
</nav>
<!-- Contenu -->
<div ref="contentRef" class="flex-1 overflow-y-auto pr-4">
<DocumentationSection
v-for="section in visibleSections"
:key="section.id"
:section="section"
/>
</div>
</div>
</template>
<script setup lang="ts">
const { visibleSections, activeArticleId, scrollToArticle } = useDocumentation()
const contentRef = ref<HTMLElement | null>(null)
onMounted(() => {
if (!contentRef.value) return
const observer = new IntersectionObserver(
(entries) => {
for (const entry of entries) {
if (entry.isIntersecting) {
const id = entry.target.id.replace('doc-', '')
activeArticleId.value = id
break
}
}
},
{
root: contentRef.value,
rootMargin: '-10% 0px -80% 0px',
threshold: 0,
},
)
nextTick(() => {
const articles = contentRef.value?.querySelectorAll('[id^="doc-"]')
articles?.forEach(el => observer.observe(el))
})
onUnmounted(() => observer.disconnect())
})
</script>