Skip to content

Commit da6e056

Browse files
committed
feat(NcAppNavigationItem): reintroduce exact prop for exact route matching
Signed-off-by: Wolfgang <github@linux-dude.de>
1 parent 9b864a1 commit da6e056

File tree

1 file changed

+36
-7
lines changed

1 file changed

+36
-7
lines changed

src/components/NcAppNavigationItem/NcAppNavigationItem.vue

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -315,20 +315,20 @@ Just set the `pinned` prop.
315315
class="app-navigation-entry-wrapper">
316316
<component
317317
:is="isRouterLink ? 'router-link' : 'NcVNodes'"
318-
v-slot="{ href: routerLinkHref, navigate, isActive }"
318+
v-slot="{ href: routerLinkHref, navigate, isActive, isExactActive }"
319319
v-bind="{ ...isRouterLink && { custom: true, to } }">
320320
<div
321321
class="app-navigation-entry"
322322
:class="{
323323
'app-navigation-entry--editing': editingActive,
324324
'app-navigation-entry--deleted': undo,
325-
active: (to && isActive) || active,
325+
active: isActiveLink(isActive, isExactActive),
326326
}">
327327
<!-- Icon and name -->
328328
<a
329329
v-if="!undo"
330330
class="app-navigation-entry-link"
331-
:aria-current="active || (to && isActive) ? 'page' : undefined"
331+
:aria-current="isActiveLink(isActive, isExactActive) ? 'page' : undefined"
332332
:aria-description="ariaDescription"
333333
:aria-expanded="!!$slots.default ? opened.toString() : undefined"
334334
:href="href || routerLinkHref || '#'"
@@ -346,7 +346,7 @@ Just set the `pinned` prop.
346346
:class="{ [icon]: icon }">
347347
<NcLoadingIcon v-if="loading" />
348348
<!-- @slot Slot for the optional leading icon. This slots get the `active`-slot attribute passed which is based on the vue-routers active route or the `active` prop. -->
349-
<slot v-else name="icon" :active="active || (to && isActive)" />
349+
<slot v-else name="icon" :active="isActiveLink(isActive, isExactActive)" />
350350
</div>
351351
<span class="app-navigation-entry__name" :class="{ 'hidden-visually': editingActive }">
352352
{{ name }}
@@ -356,7 +356,7 @@ Just set the `pinned` prop.
356356
ref="editingInput"
357357
v-model="editingValue"
358358
:placeholder="editPlaceholder !== '' ? editPlaceholder : name"
359-
:primary="(to && isActive) || active"
359+
:primary="isActiveLink(isActive, isExactActive)"
360360
@cancel="cancelEditing"
361361
@confirm="handleEditingDone" />
362362
</div>
@@ -391,7 +391,7 @@ Just set the `pinned` prop.
391391
:open="menuOpen"
392392
:force-menu="forceMenu"
393393
:default-icon="menuIcon"
394-
:variant="(to && isActive) || active ? 'tertiary-on-primary' : 'tertiary'"
394+
:variant="isActiveLink(isActive, isExactActive) ? 'tertiary-on-primary' : 'tertiary'"
395395
@update:open="onMenuToggle">
396396
<template #icon>
397397
<!-- @slot Slot for the custom menu icon -->
@@ -420,7 +420,7 @@ Just set the `pinned` prop.
420420
</div>
421421
<NcAppNavigationIconCollapsible
422422
v-if="allowCollapse && !!$slots.default"
423-
:active="(to && isActive) || active"
423+
:active="isActiveLink(isActive, isExactActive)"
424424
:open="opened"
425425
@click.prevent.stop="toggleCollapse" />
426426

@@ -473,6 +473,15 @@ export default {
473473
default: false,
474474
},
475475
476+
/**
477+
* Pass in `true` if you want the matching behaviour to be
478+
* non-inclusive using vue-router's active state `isExactActive`
479+
*/
480+
exact: {
481+
type: Boolean,
482+
default: false,
483+
},
484+
476485
/**
477486
* The main text content of the entry.
478487
*/
@@ -814,6 +823,26 @@ export default {
814823
// Match any protocol
815824
return href && href.match(/[a-z]+:\/\//i)
816825
},
826+
827+
/**
828+
* Determines whether the navigation item should be marked as active.
829+
*
830+
* When using vue-router, the active state is derived from the router's `isActive`
831+
* or `isExactActive` values. The `exact` prop decides which state to use.
832+
*
833+
* When not using vue-router, the component falls back to the `active` prop
834+
* provided by the parent component.
835+
*
836+
* @param {boolean} isActive - The router-provided active state for partial matches
837+
* @param {boolean} isExactActive - The router-provided active state for exact matches
838+
* @return {boolean} True if the navigation item should be rendered in active state
839+
*/
840+
isActiveLink(isActive, isExactActive) {
841+
if (this.to) {
842+
return this.exact ? isExactActive : isActive
843+
}
844+
return this.active
845+
},
817846
},
818847
}
819848
</script>

0 commit comments

Comments
 (0)