ContentNavigationPRO

GitHub
一个手风琴式导航组件,用于组织页面链接。
此组件仅在安装了 @nuxt/content 模块时可用。

用法

使用 navigation prop 和您在获取应用程序导航时获得的 navigation 值。

<script setup lang="ts">
import type { ContentNavigationItem } from '@nuxt/content'

const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
</script>

<template>
  <UContentNavigation :navigation="navigation" highlight />
</template>

类型

type prop 设置为 single 以仅允许一次打开一个项目。默认为 multiple

<script setup lang="ts">
const navigation = ref([
  {
    title: 'Guide',
    icon: 'i-lucide-book-open',
    path: '#getting-started',
    children: [
      {
        title: 'Introduction',
        path: '#introduction',
        active: true
      },
      {
        title: 'Installation',
        path: '#installation'
      }
    ]
  },
  {
    title: 'Composables',
    icon: 'i-lucide-database',
    path: '#composables',
    children: [
      {
        title: 'defineShortcuts',
        path: '#defineshortcuts'
      },
      {
        title: 'useModal',
        path: '#usemodal'
      }
    ]
  }
])
</script>

<template>
  <UContentNavigation type="single" />
</template>

颜色

使用 color prop 更改导航链接的颜色。

<script setup lang="ts">
const navigation = ref([
  {
    title: 'Guide',
    icon: 'i-lucide-book-open',
    path: '#getting-started',
    children: [
      {
        title: 'Introduction',
        path: '#introduction',
        active: true
      },
      {
        title: 'Installation',
        path: '#installation'
      }
    ]
  },
  {
    title: 'Composables',
    icon: 'i-lucide-database',
    path: '#composables',
    children: [
      {
        title: 'defineShortcuts',
        path: '#defineshortcuts'
      },
      {
        title: 'useModal',
        path: '#usemodal'
      }
    ]
  }
])
</script>

<template>
  <UContentNavigation color="neutral" />
</template>

变体

使用 variant prop 更改导航链接的变体。

<script setup lang="ts">
const navigation = ref([
  {
    title: 'Guide',
    icon: 'i-lucide-book-open',
    path: '#getting-started',
    children: [
      {
        title: 'Introduction',
        path: '#introduction',
        active: true
      },
      {
        title: 'Installation',
        path: '#installation'
      }
    ]
  },
  {
    title: 'Composables',
    icon: 'i-lucide-database',
    path: '#composables',
    children: [
      {
        title: 'defineShortcuts',
        path: '#defineshortcuts'
      },
      {
        title: 'useModal',
        path: '#usemodal'
      }
    ]
  }
])
</script>

<template>
  <UContentNavigation variant="link" />
</template>

高亮显示

使用 highlight prop 为活动链接显示高亮边框。

使用 highlight-color prop 更改边框的颜色。它默认为 color prop。

<script setup lang="ts">
const navigation = ref([
  {
    title: 'Guide',
    icon: 'i-lucide-book-open',
    path: '#getting-started',
    children: [
      {
        title: 'Introduction',
        path: '#introduction',
        active: true
      },
      {
        title: 'Installation',
        path: '#installation'
      }
    ]
  },
  {
    title: 'Composables',
    icon: 'i-lucide-database',
    path: '#composables',
    children: [
      {
        title: 'defineShortcuts',
        path: '#defineshortcuts'
      },
      {
        title: 'useModal',
        path: '#usemodal'
      }
    ]
  }
])
</script>

<template>
  <UContentNavigation highlight highlight-color="primary" color="primary" variant="pill" />
</template>

尾部图标

<script setup lang="ts">
const navigation = ref([
  {
    title: 'Guide',
    icon: 'i-lucide-book-open',
    path: '#getting-started',
    children: [
      {
        title: 'Introduction',
        path: '#introduction',
        active: true
      },
      {
        title: 'Installation',
        path: '#installation'
      }
    ]
  },
  {
    title: 'Composables',
    icon: 'i-lucide-database',
    path: '#composables',
    children: [
      {
        title: 'defineShortcuts',
        path: '#defineshortcuts'
      },
      {
        title: 'useModal',
        path: '#usemodal'
      }
    ]
  }
])
</script>

<template>
  <UContentNavigation trailing-icon="i-lucide-arrow-up" />
</template>

示例

在布局中

在布局中,将 ContentNavigation 组件放在 PageAside 组件内,以显示页面的导航。

layouts/docs.vue
<script setup lang="ts">
import type { ContentNavigationItem } from '@nuxt/content'

const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
</script>

<template>
  <UPage>
    <template #left>
      <UPageAside>
        <UContentNavigation :navigation="navigation" highlight />
      </UPageAside>
    </template>

    <slot />
  </UPage>
</template>

在头部中

在移动端,将 ContentNavigation 组件放在 Header 组件的 content slot 内,以显示页面的导航。

components/Header.vue
<script setup lang="ts">
import type { ContentNavigationItem } from '@nuxt/content'

const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
</script>

<template>
  <UHeader>
    <template #body>
      <UContentNavigation :navigation="navigation" highlight />
    </template>
  </UHeader>
</template>

API

属性

属性默认值类型
as

'nav'

任意

此组件应渲染为的元素或组件。

defaultOpen

void 0

布尔值

当为 true 时,树将根据当前路由打开。当为 false 时,树将关闭。当为 undefined(默认值)时,type="single" 将打开第一个项目,而 type="multiple" 将打开第一级。

trailingIcon

appConfig.ui.icons.chevronDown

字符串

显示用于切换手风琴的图标。

color

'primary'

"error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"

variant

'pill'

"link" | "pill"

高亮

false

布尔值

在活动链接旁边显示一条线。

highlightColor

'primary'

"error" | "primary" | "secondary" | "success" | "info" | "warning" | "neutral"

collapsible

true

布尔值

当类型为“single”时,允许在点击已打开的项目触发器时关闭内容。当类型为“multiple”时,此属性无效。

level

0

数字

navigation

ContentNavigationLink[]

disabled

false

布尔值

当为 `true` 时,防止用户与折叠面板及其所有项目交互。

type

'multiple'

"multiple" | "single"

确定一次可以选择“单个”还是“多个”项目。

此 prop 将覆盖从 modelValuedefaultValue 推断的类型。

unmountOnHide

true

布尔值

当为 `true` 时,元素在关闭状态下将被卸载。

ui

{ root?: ClassNameValue; content?: ClassNameValue; list?: ClassNameValue; item?: ClassNameValue; listWithChildren?: ClassNameValue; itemWithChildren?: ClassNameValue; trigger?: ClassNameValue; link?: ClassNameValue; linkLeadingIcon?: ClassNameValue; linkTrailing?: ClassNameValue; linkTrailingBadge?: ClassNameValue; linkTrailingBadgeSize?: ClassNameValue; linkTrailingIcon?: ClassNameValue; linkTitle?: ClassNameValue; linkTitleExternalIcon?: ClassNameValue; }

插槽

插槽类型
link

{ link: ContentNavigationLink; active?: boolean | undefined; }

link-leading

{ link: ContentNavigationLink; active?: boolean | undefined; }

link-title

{ link: ContentNavigationLink; active?: boolean | undefined; }

link-trailing

{ link: ContentNavigationLink; active?: boolean | undefined; }

事件

事件类型
update:modelValue

[string | string[] | undefined]

主题

app.config.ts
export default defineAppConfig({
  uiPro: {
    contentNavigation: {
      slots: {
        root: '',
        content: 'data-[state=open]:animate-[accordion-down_200ms_ease-out] data-[state=closed]:animate-[accordion-up_200ms_ease-out] overflow-hidden focus:outline-none',
        list: 'isolate -mx-2.5 -mt-1.5',
        item: '',
        listWithChildren: 'ms-5 border-s border-default',
        itemWithChildren: 'flex flex-col data-[state=open]:mb-1.5',
        trigger: 'font-semibold',
        link: 'group relative w-full px-2.5 py-1.5 before:inset-y-px before:inset-x-0 flex items-center gap-1.5 text-sm before:absolute before:z-[-1] before:rounded-md focus:outline-none focus-visible:outline-none focus-visible:before:ring-inset focus-visible:before:ring-2',
        linkLeadingIcon: 'shrink-0 size-5',
        linkTrailing: 'ms-auto inline-flex gap-1.5 items-center',
        linkTrailingBadge: 'shrink-0',
        linkTrailingBadgeSize: 'sm',
        linkTrailingIcon: 'size-5 transform transition-transform duration-200 shrink-0 group-data-[state=open]:rotate-180',
        linkTitle: 'truncate',
        linkTitleExternalIcon: 'size-3 align-top text-dimmed'
      },
      variants: {
        color: {
          primary: {
            trigger: 'focus-visible:ring-primary',
            link: 'focus-visible:before:ring-primary'
          },
          secondary: {
            trigger: 'focus-visible:ring-secondary',
            link: 'focus-visible:before:ring-secondary'
          },
          success: {
            trigger: 'focus-visible:ring-success',
            link: 'focus-visible:before:ring-success'
          },
          info: {
            trigger: 'focus-visible:ring-info',
            link: 'focus-visible:before:ring-info'
          },
          warning: {
            trigger: 'focus-visible:ring-warning',
            link: 'focus-visible:before:ring-warning'
          },
          error: {
            trigger: 'focus-visible:ring-error',
            link: 'focus-visible:before:ring-error'
          },
          neutral: {
            trigger: 'focus-visible:ring-inverted',
            link: 'focus-visible:before:ring-inverted'
          }
        },
        highlightColor: {
          primary: '',
          secondary: '',
          success: '',
          info: '',
          warning: '',
          error: '',
          neutral: ''
        },
        variant: {
          pill: '',
          link: ''
        },
        active: {
          true: {
            link: 'font-medium'
          },
          false: {
            link: 'text-muted',
            linkLeadingIcon: 'text-dimmed'
          }
        },
        disabled: {
          true: {
            link: 'cursor-not-allowed opacity-75'
          }
        },
        highlight: {
          true: {}
        },
        level: {
          true: {
            item: 'ps-1.5 -ms-px',
            itemWithChildren: 'ps-1.5 -ms-px'
          }
        }
      },
      compoundVariants: [
        {
          highlight: true,
          level: true,
          class: {
            link: [
              'after:absolute after:-left-1.5 after:inset-y-0.5 after:block after:w-px after:rounded-full',
              'after:transition-colors'
            ]
          }
        },
        {
          disabled: false,
          active: false,
          variant: 'pill',
          class: {
            link: [
              'hover:text-highlighted hover:before:bg-elevated/50 data-[state=open]:text-highlighted',
              'transition-colors before:transition-colors'
            ],
            linkLeadingIcon: [
              'group-hover:text-default group-data-[state=open]:text-default',
              'transition-colors'
            ]
          }
        },
        {
          color: 'primary',
          variant: 'pill',
          active: true,
          class: {
            link: 'text-primary',
            linkLeadingIcon: 'text-primary group-data-[state=open]:text-primary'
          }
        },
        {
          color: 'neutral',
          variant: 'pill',
          active: true,
          class: {
            link: 'text-highlighted',
            linkLeadingIcon: 'text-highlighted group-data-[state=open]:text-highlighted'
          }
        },
        {
          variant: 'pill',
          active: true,
          highlight: false,
          class: {
            link: 'before:bg-elevated'
          }
        },
        {
          variant: 'pill',
          active: true,
          highlight: true,
          class: {
            link: [
              'hover:before:bg-elevated/50',
              'before:transition-colors'
            ]
          }
        },
        {
          disabled: false,
          active: false,
          variant: 'link',
          class: {
            link: [
              'hover:text-highlighted data-[state=open]:text-highlighted',
              'transition-colors'
            ],
            linkLeadingIcon: [
              'group-hover:text-default group-data-[state=open]:text-default',
              'transition-colors'
            ]
          }
        },
        {
          color: 'primary',
          variant: 'link',
          active: true,
          class: {
            link: 'text-primary',
            linkLeadingIcon: 'text-primary group-data-[state=open]:text-primary'
          }
        },
        {
          color: 'neutral',
          variant: 'link',
          active: true,
          class: {
            link: 'text-highlighted',
            linkLeadingIcon: 'text-highlighted group-data-[state=open]:text-highlighted'
          }
        },
        {
          highlightColor: 'primary',
          highlight: true,
          level: true,
          active: true,
          class: {
            link: 'after:bg-primary'
          }
        },
        {
          highlightColor: 'neutral',
          highlight: true,
          level: true,
          active: true,
          class: {
            link: 'after:bg-inverted'
          }
        }
      ],
      defaultVariants: {
        color: 'primary',
        highlightColor: 'primary',
        variant: 'pill'
      }
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ui from '@nuxt/ui/vite'

export default defineConfig({
  plugins: [
    vue(),
    ui({
      uiPro: {
        contentNavigation: {
          slots: {
            root: '',
            content: 'data-[state=open]:animate-[accordion-down_200ms_ease-out] data-[state=closed]:animate-[accordion-up_200ms_ease-out] overflow-hidden focus:outline-none',
            list: 'isolate -mx-2.5 -mt-1.5',
            item: '',
            listWithChildren: 'ms-5 border-s border-default',
            itemWithChildren: 'flex flex-col data-[state=open]:mb-1.5',
            trigger: 'font-semibold',
            link: 'group relative w-full px-2.5 py-1.5 before:inset-y-px before:inset-x-0 flex items-center gap-1.5 text-sm before:absolute before:z-[-1] before:rounded-md focus:outline-none focus-visible:outline-none focus-visible:before:ring-inset focus-visible:before:ring-2',
            linkLeadingIcon: 'shrink-0 size-5',
            linkTrailing: 'ms-auto inline-flex gap-1.5 items-center',
            linkTrailingBadge: 'shrink-0',
            linkTrailingBadgeSize: 'sm',
            linkTrailingIcon: 'size-5 transform transition-transform duration-200 shrink-0 group-data-[state=open]:rotate-180',
            linkTitle: 'truncate',
            linkTitleExternalIcon: 'size-3 align-top text-dimmed'
          },
          variants: {
            color: {
              primary: {
                trigger: 'focus-visible:ring-primary',
                link: 'focus-visible:before:ring-primary'
              },
              secondary: {
                trigger: 'focus-visible:ring-secondary',
                link: 'focus-visible:before:ring-secondary'
              },
              success: {
                trigger: 'focus-visible:ring-success',
                link: 'focus-visible:before:ring-success'
              },
              info: {
                trigger: 'focus-visible:ring-info',
                link: 'focus-visible:before:ring-info'
              },
              warning: {
                trigger: 'focus-visible:ring-warning',
                link: 'focus-visible:before:ring-warning'
              },
              error: {
                trigger: 'focus-visible:ring-error',
                link: 'focus-visible:before:ring-error'
              },
              neutral: {
                trigger: 'focus-visible:ring-inverted',
                link: 'focus-visible:before:ring-inverted'
              }
            },
            highlightColor: {
              primary: '',
              secondary: '',
              success: '',
              info: '',
              warning: '',
              error: '',
              neutral: ''
            },
            variant: {
              pill: '',
              link: ''
            },
            active: {
              true: {
                link: 'font-medium'
              },
              false: {
                link: 'text-muted',
                linkLeadingIcon: 'text-dimmed'
              }
            },
            disabled: {
              true: {
                link: 'cursor-not-allowed opacity-75'
              }
            },
            highlight: {
              true: {}
            },
            level: {
              true: {
                item: 'ps-1.5 -ms-px',
                itemWithChildren: 'ps-1.5 -ms-px'
              }
            }
          },
          compoundVariants: [
            {
              highlight: true,
              level: true,
              class: {
                link: [
                  'after:absolute after:-left-1.5 after:inset-y-0.5 after:block after:w-px after:rounded-full',
                  'after:transition-colors'
                ]
              }
            },
            {
              disabled: false,
              active: false,
              variant: 'pill',
              class: {
                link: [
                  'hover:text-highlighted hover:before:bg-elevated/50 data-[state=open]:text-highlighted',
                  'transition-colors before:transition-colors'
                ],
                linkLeadingIcon: [
                  'group-hover:text-default group-data-[state=open]:text-default',
                  'transition-colors'
                ]
              }
            },
            {
              color: 'primary',
              variant: 'pill',
              active: true,
              class: {
                link: 'text-primary',
                linkLeadingIcon: 'text-primary group-data-[state=open]:text-primary'
              }
            },
            {
              color: 'neutral',
              variant: 'pill',
              active: true,
              class: {
                link: 'text-highlighted',
                linkLeadingIcon: 'text-highlighted group-data-[state=open]:text-highlighted'
              }
            },
            {
              variant: 'pill',
              active: true,
              highlight: false,
              class: {
                link: 'before:bg-elevated'
              }
            },
            {
              variant: 'pill',
              active: true,
              highlight: true,
              class: {
                link: [
                  'hover:before:bg-elevated/50',
                  'before:transition-colors'
                ]
              }
            },
            {
              disabled: false,
              active: false,
              variant: 'link',
              class: {
                link: [
                  'hover:text-highlighted data-[state=open]:text-highlighted',
                  'transition-colors'
                ],
                linkLeadingIcon: [
                  'group-hover:text-default group-data-[state=open]:text-default',
                  'transition-colors'
                ]
              }
            },
            {
              color: 'primary',
              variant: 'link',
              active: true,
              class: {
                link: 'text-primary',
                linkLeadingIcon: 'text-primary group-data-[state=open]:text-primary'
              }
            },
            {
              color: 'neutral',
              variant: 'link',
              active: true,
              class: {
                link: 'text-highlighted',
                linkLeadingIcon: 'text-highlighted group-data-[state=open]:text-highlighted'
              }
            },
            {
              highlightColor: 'primary',
              highlight: true,
              level: true,
              active: true,
              class: {
                link: 'after:bg-primary'
              }
            },
            {
              highlightColor: 'neutral',
              highlight: true,
              level: true,
              active: true,
              class: {
                link: 'after:bg-inverted'
              }
            }
          ],
          defaultVariants: {
            color: 'primary',
            highlightColor: 'primary',
            variant: 'pill'
          }
        }
      }
    })
  ]
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import uiPro from '@nuxt/ui-pro/vite'

export default defineConfig({
  plugins: [
    vue(),
    uiPro({
      uiPro: {
        contentNavigation: {
          slots: {
            root: '',
            content: 'data-[state=open]:animate-[accordion-down_200ms_ease-out] data-[state=closed]:animate-[accordion-up_200ms_ease-out] overflow-hidden focus:outline-none',
            list: 'isolate -mx-2.5 -mt-1.5',
            item: '',
            listWithChildren: 'ms-5 border-s border-default',
            itemWithChildren: 'flex flex-col data-[state=open]:mb-1.5',
            trigger: 'font-semibold',
            link: 'group relative w-full px-2.5 py-1.5 before:inset-y-px before:inset-x-0 flex items-center gap-1.5 text-sm before:absolute before:z-[-1] before:rounded-md focus:outline-none focus-visible:outline-none focus-visible:before:ring-inset focus-visible:before:ring-2',
            linkLeadingIcon: 'shrink-0 size-5',
            linkTrailing: 'ms-auto inline-flex gap-1.5 items-center',
            linkTrailingBadge: 'shrink-0',
            linkTrailingBadgeSize: 'sm',
            linkTrailingIcon: 'size-5 transform transition-transform duration-200 shrink-0 group-data-[state=open]:rotate-180',
            linkTitle: 'truncate',
            linkTitleExternalIcon: 'size-3 align-top text-dimmed'
          },
          variants: {
            color: {
              primary: {
                trigger: 'focus-visible:ring-primary',
                link: 'focus-visible:before:ring-primary'
              },
              secondary: {
                trigger: 'focus-visible:ring-secondary',
                link: 'focus-visible:before:ring-secondary'
              },
              success: {
                trigger: 'focus-visible:ring-success',
                link: 'focus-visible:before:ring-success'
              },
              info: {
                trigger: 'focus-visible:ring-info',
                link: 'focus-visible:before:ring-info'
              },
              warning: {
                trigger: 'focus-visible:ring-warning',
                link: 'focus-visible:before:ring-warning'
              },
              error: {
                trigger: 'focus-visible:ring-error',
                link: 'focus-visible:before:ring-error'
              },
              neutral: {
                trigger: 'focus-visible:ring-inverted',
                link: 'focus-visible:before:ring-inverted'
              }
            },
            highlightColor: {
              primary: '',
              secondary: '',
              success: '',
              info: '',
              warning: '',
              error: '',
              neutral: ''
            },
            variant: {
              pill: '',
              link: ''
            },
            active: {
              true: {
                link: 'font-medium'
              },
              false: {
                link: 'text-muted',
                linkLeadingIcon: 'text-dimmed'
              }
            },
            disabled: {
              true: {
                link: 'cursor-not-allowed opacity-75'
              }
            },
            highlight: {
              true: {}
            },
            level: {
              true: {
                item: 'ps-1.5 -ms-px',
                itemWithChildren: 'ps-1.5 -ms-px'
              }
            }
          },
          compoundVariants: [
            {
              highlight: true,
              level: true,
              class: {
                link: [
                  'after:absolute after:-left-1.5 after:inset-y-0.5 after:block after:w-px after:rounded-full',
                  'after:transition-colors'
                ]
              }
            },
            {
              disabled: false,
              active: false,
              variant: 'pill',
              class: {
                link: [
                  'hover:text-highlighted hover:before:bg-elevated/50 data-[state=open]:text-highlighted',
                  'transition-colors before:transition-colors'
                ],
                linkLeadingIcon: [
                  'group-hover:text-default group-data-[state=open]:text-default',
                  'transition-colors'
                ]
              }
            },
            {
              color: 'primary',
              variant: 'pill',
              active: true,
              class: {
                link: 'text-primary',
                linkLeadingIcon: 'text-primary group-data-[state=open]:text-primary'
              }
            },
            {
              color: 'neutral',
              variant: 'pill',
              active: true,
              class: {
                link: 'text-highlighted',
                linkLeadingIcon: 'text-highlighted group-data-[state=open]:text-highlighted'
              }
            },
            {
              variant: 'pill',
              active: true,
              highlight: false,
              class: {
                link: 'before:bg-elevated'
              }
            },
            {
              variant: 'pill',
              active: true,
              highlight: true,
              class: {
                link: [
                  'hover:before:bg-elevated/50',
                  'before:transition-colors'
                ]
              }
            },
            {
              disabled: false,
              active: false,
              variant: 'link',
              class: {
                link: [
                  'hover:text-highlighted data-[state=open]:text-highlighted',
                  'transition-colors'
                ],
                linkLeadingIcon: [
                  'group-hover:text-default group-data-[state=open]:text-default',
                  'transition-colors'
                ]
              }
            },
            {
              color: 'primary',
              variant: 'link',
              active: true,
              class: {
                link: 'text-primary',
                linkLeadingIcon: 'text-primary group-data-[state=open]:text-primary'
              }
            },
            {
              color: 'neutral',
              variant: 'link',
              active: true,
              class: {
                link: 'text-highlighted',
                linkLeadingIcon: 'text-highlighted group-data-[state=open]:text-highlighted'
              }
            },
            {
              highlightColor: 'primary',
              highlight: true,
              level: true,
              active: true,
              class: {
                link: 'after:bg-primary'
              }
            },
            {
              highlightColor: 'neutral',
              highlight: true,
              level: true,
              active: true,
              class: {
                link: 'after:bg-inverted'
              }
            }
          ],
          defaultVariants: {
            color: 'primary',
            highlightColor: 'primary',
            variant: 'pill'
          }
        }
      }
    })
  ]
})
为便于阅读,compoundVariants 中的某些颜色已省略。请在 GitHub 上查看源代码。