Skip to content

Commit

Permalink
feat(NavigationMenu): conditionally-rendered links
Browse files Browse the repository at this point in the history
  • Loading branch information
GalacticHypernova authored Jan 24, 2025
1 parent 8d941e1 commit 2464953
Showing 1 changed file with 77 additions and 66 deletions.
143 changes: 77 additions & 66 deletions src/runtime/components/NavigationMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ export interface NavigationMenuItem extends Omit<LinkProps, 'type' | 'raw' | 'cu
* `{ size: 'sm', color: 'neutral', variant: 'outline' }`{lang="ts-type"}
*/
badge?: string | number | BadgeProps
/**
* The condition under which to render the item
* Omitting this property will render the item at all times
*
* @defaultValue true
*/
condition?: boolean
trailingIcon?: string
/**
* The type of the item.
Expand Down Expand Up @@ -229,75 +236,79 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
<NavigationMenuRoot v-bind="rootProps" :data-collapsed="collapsed" :class="ui.root({ class: [props.class, props.ui?.root] })">
<template v-for="(list, listIndex) in lists" :key="`list-${listIndex}`">
<NavigationMenuList :class="ui.list({ class: props.ui?.list })">
<component
:is="(orientation === 'vertical' && item.children?.length) ? UCollapsible : NavigationMenuItem"
<template

Check failure on line 239 in src/runtime/components/NavigationMenu.vue

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

Trailing spaces not allowed
v-for="(item, index) in list"
:key="`list-${listIndex}-${index}`"
as="li"
:value="item.value || String(index)"
:default-open="item.defaultOpen"
:unmount-on-hide="(orientation === 'vertical' && item.children?.length) ? unmountOnHide : undefined"
:open="item.open"
:class="ui.item({ class: props.ui?.item })"
>
<div v-if="orientation === 'vertical' && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
<ReuseItemTemplate :item="(item as T)" :index="index" />
</div>
<ULink v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
<component
:is="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) ? NavigationMenuTrigger : NavigationMenuLink"
as-child
:active="active"
:disabled="item.disabled"
@select="item.onSelect"
>
<ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: !(orientation === 'vertical' && item.children?.length) })">
<ReuseItemTemplate :item="(item as T)" :active="active || item.active" :index="index" />
</ULinkBase>
</component>

<NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])" v-bind="contentProps" :class="ui.content({ class: props.ui?.content })">
<slot :name="item.slot ? `${item.slot}-content` : 'item-content'" :item="(item as T)" :active="active" :index="index">
<ul :class="ui.childList({ class: props.ui?.childList })">
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
<ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
<NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
<ULinkBase v-bind="childSlotProps" :class="ui.childLink({ class: [props.ui?.childLink, childItem.class], active: childActive })">
<UIcon v-if="childItem.icon" :name="childItem.icon" :class="ui.childLinkIcon({ class: props.ui?.childLinkIcon, active: childActive })" />

<div :class="ui.childLinkWrapper({ class: props.ui?.childLinkWrapper })">
<p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
{{ get(childItem, props.labelKey as string) }}

<UIcon v-if="childItem.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
</p>
<p v-if="childItem.description" :class="ui.childLinkDescription({ class: props.ui?.childLinkDescription, active: childActive })">
{{ childItem.description }}
</p>
</div>
</ULinkBase>
</NavigationMenuLink>
</ULink>
</li>
</ul>
</slot>
</NavigationMenuContent>
</ULink>

<template v-if="orientation === 'vertical' && item.children?.length" #content>
<ul :class="ui.childList({ class: props.ui?.childList })">
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
<ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
<NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
<ULinkBase v-bind="childSlotProps" :class="ui.link({ class: [props.ui?.link, childItem.class], active: childActive, disabled: !!childItem.disabled, level: true })">
<ReuseItemTemplate :item="(childItem as T)" :active="childActive" :index="childIndex" />
</ULinkBase>
</NavigationMenuLink>
</ULink>
</li>
</ul>
</template>
</component>
<component
v-if="item.condition ?? true"
:is="(orientation === 'vertical' && item.children?.length) ? UCollapsible : NavigationMenuItem"

Check warning on line 245 in src/runtime/components/NavigationMenu.vue

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

Attribute ":is" should go before "v-if"
as="li"
:value="item.value || String(index)"
:default-open="item.defaultOpen"
:unmount-on-hide="(orientation === 'vertical' && item.children?.length) ? unmountOnHide : undefined"
:open="item.open"
:class="ui.item({ class: props.ui?.item })"
>
<div v-if="orientation === 'vertical' && item.type === 'label'" :class="ui.label({ class: props.ui?.label })">
<ReuseItemTemplate :item="(item as T)" :index="index" />
</div>
<ULink v-else-if="item.type !== 'label'" v-slot="{ active, ...slotProps }" v-bind="(orientation === 'vertical' && item.children?.length) ? {} : pickLinkProps(item as Omit<NavigationMenuItem, 'type'>)" custom>
<component
:is="(orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) ? NavigationMenuTrigger : NavigationMenuLink"
as-child
:active="active"
:disabled="item.disabled"
@select="item.onSelect"
>
<ULinkBase v-bind="slotProps" :class="ui.link({ class: [props.ui?.link, item.class], active: active || item.active, disabled: !!item.disabled, level: !(orientation === 'vertical' && item.children?.length) })">
<ReuseItemTemplate :item="(item as T)" :active="active || item.active" :index="index" />
</ULinkBase>
</component>

Check failure on line 268 in src/runtime/components/NavigationMenu.vue

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

Trailing spaces not allowed
<NavigationMenuContent v-if="orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])" v-bind="contentProps" :class="ui.content({ class: props.ui?.content })">
<slot :name="item.slot ? `${item.slot}-content` : 'item-content'" :item="(item as T)" :active="active" :index="index">
<ul :class="ui.childList({ class: props.ui?.childList })">
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
<ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
<NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
<ULinkBase v-bind="childSlotProps" :class="ui.childLink({ class: [props.ui?.childLink, childItem.class], active: childActive })">
<UIcon v-if="childItem.icon" :name="childItem.icon" :class="ui.childLinkIcon({ class: props.ui?.childLinkIcon, active: childActive })" />

Check failure on line 277 in src/runtime/components/NavigationMenu.vue

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

Trailing spaces not allowed
<div :class="ui.childLinkWrapper({ class: props.ui?.childLinkWrapper })">
<p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
{{ get(childItem, props.labelKey as string) }}

Check failure on line 281 in src/runtime/components/NavigationMenu.vue

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

Trailing spaces not allowed
<UIcon v-if="childItem.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
</p>
<p v-if="childItem.description" :class="ui.childLinkDescription({ class: props.ui?.childLinkDescription, active: childActive })">
{{ childItem.description }}
</p>
</div>
</ULinkBase>
</NavigationMenuLink>
</ULink>
</li>
</ul>
</slot>
</NavigationMenuContent>
</ULink>

Check failure on line 296 in src/runtime/components/NavigationMenu.vue

View workflow job for this annotation

GitHub Actions / build (ubuntu-latest, 22)

Trailing spaces not allowed
<template v-if="orientation === 'vertical' && item.children?.length" #content>
<ul :class="ui.childList({ class: props.ui?.childList })">
<li v-for="(childItem, childIndex) in item.children" :key="childIndex" :class="ui.childItem({ class: props.ui?.childItem })">
<ULink v-slot="{ active: childActive, ...childSlotProps }" v-bind="pickLinkProps(childItem)" custom>
<NavigationMenuLink as-child :active="childActive" @select="childItem.onSelect">
<ULinkBase v-bind="childSlotProps" :class="ui.link({ class: [props.ui?.link, childItem.class], active: childActive, disabled: !!childItem.disabled, level: true })">
<ReuseItemTemplate :item="(childItem as T)" :active="childActive" :index="childIndex" />
</ULinkBase>
</NavigationMenuLink>
</ULink>
</li>
</ul>
</template>
</component>
</template>
</NavigationMenuList>

<div v-if="orientation === 'vertical' && listIndex < lists.length - 1" :class="ui.separator({ class: props.ui?.separator })" />
Expand Down

0 comments on commit 2464953

Please sign in to comment.