primitives
Navigation Menu
Navigation Menu — базовый примитив RevueUI (Reka UI + shadcn-совместимый API).
Загрузка превью…
src/ui/navigation-menu/NavigationMenu.vue
<script setup lang="ts">
/**
* Порт базового радикс-слоя (registry/bases/radix/ui/navigation-menu.tsx, MIT).
* Radix NavigationMenuPrimitive -> reka-ui NavigationMenu*, один в один.
*/
import type { HTMLAttributes } from "vue"
import { NavigationMenuRoot } from "reka-ui"
import { cn } from "@/lib/utils"
import NavigationMenuViewport from "./NavigationMenuViewport.vue"
const props = withDefaults(
defineProps<{
class?: HTMLAttributes["class"]
viewport?: boolean
}>(),
{
viewport: true,
}
)
</script>
<template>
<NavigationMenuRoot
data-slot="navigation-menu"
:data-viewport="props.viewport"
:class="
cn(
'cn-navigation-menu group/navigation-menu relative flex max-w-max flex-1 items-center justify-center',
props.class
)
"
>
<slot />
<NavigationMenuViewport v-if="props.viewport" />
</NavigationMenuRoot>
</template>
src/ui/navigation-menu/NavigationMenuContent.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { NavigationMenuContent } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<NavigationMenuContent
data-slot="navigation-menu-content"
:class="
cn(
'cn-navigation-menu-content top-0 left-0 w-full group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none md:absolute md:w-auto',
props.class
)
"
>
<slot />
</NavigationMenuContent>
</template>
src/ui/navigation-menu/NavigationMenuIndicator.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { NavigationMenuIndicator } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<NavigationMenuIndicator
data-slot="navigation-menu-indicator"
:class="
cn(
'cn-navigation-menu-indicator top-full z-1 flex h-1.5 items-end justify-center overflow-hidden',
props.class
)
"
>
<div class="cn-navigation-menu-indicator-arrow relative top-[60%] h-2 w-2 rotate-45" />
</NavigationMenuIndicator>
</template>
src/ui/navigation-menu/NavigationMenuItem.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { NavigationMenuItem } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<NavigationMenuItem
data-slot="navigation-menu-item"
:class="cn('cn-navigation-menu-item relative', props.class)"
>
<slot />
</NavigationMenuItem>
</template>
src/ui/navigation-menu/NavigationMenuLink.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { NavigationMenuLink } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<NavigationMenuLink
data-slot="navigation-menu-link"
:class="cn('cn-navigation-menu-link', props.class)"
>
<slot />
</NavigationMenuLink>
</template>
src/ui/navigation-menu/NavigationMenuList.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { NavigationMenuList } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<NavigationMenuList
data-slot="navigation-menu-list"
:class="
cn(
'cn-navigation-menu-list group flex flex-1 list-none items-center justify-center',
props.class
)
"
>
<slot />
</NavigationMenuList>
</template>
src/ui/navigation-menu/NavigationMenuTrigger.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { NavigationMenuTrigger } from "reka-ui"
import { cn } from "@/lib/utils"
import { navigationMenuTriggerStyle } from "./variants"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<NavigationMenuTrigger
data-slot="navigation-menu-trigger"
:class="cn(navigationMenuTriggerStyle(), 'group', props.class)"
>
<slot /> <svg
class="cn-navigation-menu-trigger-icon"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="m6 9 6 6 6-6" />
</svg>
</NavigationMenuTrigger>
</template>
src/ui/navigation-menu/NavigationMenuViewport.vue
<script setup lang="ts">
import type { HTMLAttributes } from "vue"
import { NavigationMenuViewport } from "reka-ui"
import { cn } from "@/lib/utils"
const props = defineProps<{
class?: HTMLAttributes["class"]
}>()
</script>
<template>
<div :class="cn('cn-navigation-menu-viewport-wrapper absolute top-full left-0 isolate z-50 flex justify-center')">
<NavigationMenuViewport
data-slot="navigation-menu-viewport"
:class="
cn(
'cn-navigation-menu-viewport origin-top-center relative mt-1.5 h-(--radix-navigation-menu-viewport-height) w-full overflow-hidden md:w-(--radix-navigation-menu-viewport-width)',
props.class
)
"
/>
</div>
</template>
src/ui/navigation-menu/index.ts
export { default as NavigationMenu } from "./NavigationMenu.vue"
export { default as NavigationMenuList } from "./NavigationMenuList.vue"
export { default as NavigationMenuItem } from "./NavigationMenuItem.vue"
export { default as NavigationMenuContent } from "./NavigationMenuContent.vue"
export { default as NavigationMenuTrigger } from "./NavigationMenuTrigger.vue"
export { default as NavigationMenuLink } from "./NavigationMenuLink.vue"
export { default as NavigationMenuIndicator } from "./NavigationMenuIndicator.vue"
export { default as NavigationMenuViewport } from "./NavigationMenuViewport.vue"
export { navigationMenuTriggerStyle } from "./variants"
src/ui/navigation-menu/variants.ts
import { cva } from "class-variance-authority"
export const navigationMenuTriggerStyle = cva(
"cn-navigation-menu-trigger group/navigation-menu-trigger inline-flex h-9 w-max items-center justify-center outline-none disabled:pointer-events-none"
)
Установка
npx shadcn-vue@latest add https://revueui.rootapi.dev/r/navigation-menu.jsonЗависимости реестра
npm-зависимости
- class-variance-authority
- reka-ui
Источник: порт из ReUI (Keenthemes, MIT)