fix(sidebar) : lien actif sur les sous-routes (match préfixe) + option exact

L'actif reposait sur l'active-class de NuxtLink, qui dépend de l'imbrication des
routes Vue Router : sur un routing plat, /supplier n'était plus actif sur
/supplier/1/edit. On calcule désormais l'actif côté composant via useRoute().path :
actif si path === item.to OU path commence par item.to + '/'. Nouvelle option
`exact: true` par item pour forcer le match strict.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-19 15:55:58 +02:00
parent 5a06cf642f
commit 61e1925ccd
4 changed files with 73 additions and 9 deletions
+16 -1
View File
@@ -53,10 +53,10 @@
>
<NuxtLink
:to="item.to"
active-class="!text-m-primary font-semibold"
:class="twMerge(
'block truncate text-[15px] leading-[150%]',
collapsed ? 'px-3 text-center' : 'pl-[32px]',
isActive(item) ? '!text-m-primary font-semibold' : '',
)"
>
<span v-if="!collapsed">{{ item.label }}</span>
@@ -87,6 +87,7 @@
<script setup lang="ts">
import {computed, ref, useId} from 'vue'
import {useRoute} from 'vue-router'
import {Icon as IconifyIcon} from '@iconify/vue'
import {twMerge} from 'tailwind-merge'
@@ -95,6 +96,10 @@ defineOptions({name: 'MalioSidebar', inheritAttrs: false})
export type SidebarItem = {
label: string
to: string
// Par défaut, un lien est actif sur sa route ET ses sous-routes (préfixe) :
// `/supplier` reste actif sur `/supplier/1/edit`. `exact: true` force le match
// strict (actif uniquement sur la route exacte).
exact?: boolean
}
export type SidebarSection = {
@@ -123,6 +128,16 @@ const emit = defineEmits<{
const generatedId = useId()
const componentId = computed(() => props.id || `malio-sidebar-${generatedId}`)
const route = useRoute()
// Actif si la route courante est le lien lui-même OU une de ses sous-routes
// (match par préfixe), pour que `/supplier` reste actif sur `/supplier/1/edit`.
// `item.exact` force le match strict.
function isActive(item: SidebarItem): boolean {
const path = route.path
if (item.exact) return path === item.to
return path === item.to || path.startsWith(`${item.to}/`)
}
const isControlled = computed(() => props.modelValue !== undefined)
const localValue = ref(false)