v2.1.8
/
  • Get Started
  • Components
  • Composables
  • Typography
  • GitHub
  • Layout
  • App
  • Container
  • Error
  • SidebarLayout
  • Element
  • Advice
  • Alert
  • Avatar
  • AvatarGroup
  • Badge
  • Banner
  • Button
  • Calendar
  • Card
  • Chip
  • Collapsible
  • Countdown
  • FieldGroup
  • Kbd
  • Progress
  • Separator
  • Skeleton
  • Form
  • Checkbox
  • CheckboxGroup
  • ColorPicker
  • FileUpload
  • Form
  • FormField
  • Input
  • InputDate
  • InputMenu
  • InputNumber
  • InputTags
  • InputTime
  • PinInput
  • RadioGroup
  • Range
  • Select
  • SelectMenu
  • Switch
  • Textarea
  • Data
  • Accordion
  • DescriptionList
  • Empty
  • Table
  • TableWrapper
  • Timeline
  • User
  • Navigation
  • Breadcrumb
  • CommandPalette
  • Link
  • NavigationMenu
  • Pagination
  • Stepper
  • Tabs
  • Overlay
  • ContextMenu
  • DropdownMenu
  • Modal
  • Popover
  • Slideover
  • Toast
  • Tooltip
  • Page
  • PageCard
  • PageColumns
  • PageGrid
  • PageLinks
  • PageList
  • Dashboard
  • DashboardGroup
  • DashboardSearch
  • DashboardSearchButton
  • AI Chat
  • soonChatMessage
  • soonChatMessages
  • soonChatPalette
  • soonChatPrompt
  • soonChatPromptSubmit
  • Content
  • ContentSearch
  • ContentSearchButton
  • ContentSurround
  • ContentToc
  • Color Mode
  • ColorModeAvatar
  • ColorModeButton
  • ColorModeImage
  • ColorModeSelect
  • ColorModeSwitch
  • i18n
  • LocaleSelect
  • b24icons
  • b24jssdk
Use our Nuxt starter
v2.1.8
  • Docs
  • Components
  • Composables
  • Typography

NavigationMenu

A link list that can be arranged in horizontal or vertical orientation.
GitHub
Demo
Nuxt UI
NavigationMenuNavigationMenu

Usage

Use the NavigationMenu component to display a list of links horizontally or vertically.

  • GitHub
{
  "wait": "Loading client-side content..."
}

Items

Use the items prop as an array of objects with the following properties:

  • label?: string
  • icon?: IconComponent
  • avatar?: AvatarProps
  • badge?: string | number | BadgeProps
  • hint?: string
  • tooltip?: TooltipProps
  • trailingIcon?: IconComponent
  • type?: 'label' | 'trigger' | 'link'
  • defaultOpen?: boolean
  • open?: boolean
  • value?: string
  • disabled?: boolean
  • slot?: string
  • viewportRtl?: boolean
  • onSelect?: (e: Event) => void
  • children?: NavigationMenuChildItem[]
  • class?: any
  • b24ui?: { linkLeadingAvatarSize?: ClassNameValue, linkLeadingAvatar?: ClassNameValue, linkLeadingIcon?: ClassNameValue, linkLabel?: ClassNameValue, linkLabelExternalIcon?: ClassNameValue, linkTrailing?: ClassNameValue, linkLeadingHint?: ClassNameValue, linkLeadingBadgeSize?: ClassNameValue, linkLeadingBadge?: ClassNameValue, linkTrailingIcon?: ClassNameValue, label?: ClassNameValue, link?: ClassNameValue, content?: ClassNameValue, childList?: ClassNameValue, childLabel?: ClassNameValue, childItem?: ClassNameValue, childLink?: ClassNameValue, childLinkIcon?: ClassNameValue, childLinkHint?: ClassNameValue, childLinkBadgeSize?: ClassNameValue, childLinkBadge?: ClassNameValue, childLinkWrapper?: ClassNameValue, childLinkLabel?: ClassNameValue, childLinkLabelExternalIcon?: ClassNameValue, popoverWrapper?: ClassNameValue }

You can pass any property from the Link component such as to, target, etc.

  • GitHub
{
  "wait": "Loading client-side content..."
}
You can also pass an array of arrays to the items prop to display groups of items.
Use a flat children array of objects to define submenus:
  • label: string
  • icon?: IconComponent
  • onSelect?(e: Event): void
  • class?: any

Orientation

Use the orientation prop to change the orientation of the NavigationMenu.

When orientation is vertical, an Accordion component is used to display each group. You can control the open state of each item using the open and defaultOpen properties and change the behavior using the collapsible and type props.
The last top-level menu item needs to have viewportRtl set to ensure the drop-down menu is positioned correctly.
  • Links
  • GitHub
{
  "wait": "Loading client-side content..."
}
Groups will be spaced when orientation is horizontal and separated when orientation is vertical.

Collapsed

In vertical orientation, use the collapsed prop to collapse the NavigationMenu, this can be useful in a sidebar for example.

You can use the tooltip and popover props to display more information on the collapsed items.
{
  "wait": "Loading client-side content..."
}

Trailing Icon

Use the trailing-icon prop to customize the trailing Icon of each item. This icon is only displayed when an item has children.

You can also set an icon for a specific item by using the trailingIcon property in the item object.
{
  "wait": "Loading client-side content..."
}

Unmount

Use the unmount-on-hide prop to control the content unmounting behavior. Defaults to true.

    • Online workspace

    • CoPilot in Chat

    • useToast

    • Employee management

    • Culture & engagement

    • Automation

{
  "wait": "Loading client-side content..."
}
You can inspect the DOM to see each item's content being rendered.

Examples

With tooltip in items

When orientation is vertical and the menu is collapsed, you can set the tooltip prop to true to display a Tooltip around items with their label but you can also use the tooltip property on each item to override the default tooltip.

You can pass any property from the Tooltip component globally or on each item.

{
  "wait": "Loading client-side content..."
}

With popover in items

When orientation is vertical and the menu is collapsed, you can set the popover prop to true to display a Popover around items with their children but you can also use the popover property on each item to override the default popover.

You can pass any property from the Popover component globally or on each item.

{
  "wait": "Loading client-side content..."
}
You can use the #content slot to customize the content of the popover in the vertical orientation.

Control active item

You can control the active item(s) by using the default-value prop or the v-model directive with the value of the item. If no value is provided, it defaults to item-${index} for top-level items or item-${level}-${index} for nested items.

{
  "wait": "Loading client-side content..."
}
In this example, leveraging defineShortcuts, you can switch the active item by pressing 1, 2, or 3.

With custom slot

Use the slot property to customize a specific item.

You will have access to the following slots:

  • #{{ item.slot }}
  • #{{ item.slot }}-leading
  • #{{ item.slot }}-label
  • #{{ item.slot }}-trailing
  • #{{ item.slot }}-content
{
  "wait": "Loading client-side content..."
}
You can also use the #item, #item-leading, #item-label, #item-trailing and #item-content slots to customize all items.

With content slot

Use the #item-content slot or the slot property (#{{ item.slot }}-content) to customize the content of a specific item.

  • GitHub
{
  "wait": "Loading client-side content..."
}
In this example, we add the sm:w-(--reka-navigation-menu-viewport-width) class on the viewport to have a dynamic width. This requires to set a width on the content's first child.

API

Props

Prop Default Type
as'div'any

The element or component this component should render as.

type'multiple' "single" | "multiple"

Determines whether a "single" or "multiple" items can be selected at a time.

Only works when orientation is vertical.

modelValue string | string[]

The controlled value of the active item(s).

  • In horizontal orientation: always string
  • In vertical orientation with type="single": string
  • In vertical orientation with type="multiple": string[]

Use this when you need to control the state of the items. Can be binded with v-model

defaultValue string | string[]

The default active value of the item(s).

  • In horizontal orientation: always string
  • In vertical orientation with type="single": string
  • In vertical orientation with type="multiple": string[]

Use when you do not need to control the state of the item(s).

trailingIconicons.chevronDownIconComponent

The icon displayed to open the menu.

externalIcontrueIconComponent

The icon displayed when the item is an external link. Set to false to hide the external icon.

items NavigationMenuItem[] | NavigationMenuItem[][]
  • label?: string
  • icon?: IconComponent

    Icon is only used when orientation is vertical

  • avatar?: AvatarProps

    Avatar is only used when orientation is vertical

  • badge?: string | number | BadgeProps

    Display a badge on the item. { size: 'xs', color: 'air-primary-alert' }

  • hint?: string

    Display a hint on the item in horizontal orientation.

  • tooltip?: boolean | TooltipProps

    Display a tooltip on the item when the menu is collapsed with the label of the item. This has priority over the global tooltip prop.

  • popover?: boolean | PopoverProps<PopoverMode>

    Display a popover on the item when the menu is collapsed with the children list. This has priority over the global popover prop.

  • trailingIcon?: IconComponent
  • type?: "label" | "link" | "trigger"

    The type of the item. The label type is only displayed in vertical orientation. The trigger type is used to force the item to be collapsible when its a link in vertical orientation. Defaults to 'link'.

  • slot?: string
  • value?: string

    The value of the item. Avoid using index as the value to prevent conflicts in horizontal orientation with Reka UI. Defaults to item-${index}.

  • children?: NavigationMenuChildItem[]
  • viewportRtl?: boolean

    With orientation=horizontal if true it will position the dropdown menu correctly

  • defaultOpen?: boolean
  • open?: boolean
  • onSelect?: ((e: Event) => void)
  • class?: any
  • b24ui?: Pick<{ root?: ClassNameValue; list?: ClassNameValue; label?: ClassNameValue; item?: ClassNameValue; link?: ClassNameValue; linkLeadingIcon?: ClassNameValue; linkLeadingAvatar?: ClassNameValue; linkLeadingAvatarSize?: ClassNameValue; linkLeadingHint?: ClassNameValue; linkLeadingBadge?: ClassNameValue; linkLeadingBadgeSize?: ClassNameValue; linkTrailing?: ClassNameValue; linkTrailingIcon?: ClassNameValue; linkLabel?: ClassNameValue; linkLabelWrapper?: ClassNameValue; linkLabelExternalIcon?: ClassNameValue; childList?: ClassNameValue; childLabel?: ClassNameValue; childItem?: ClassNameValue; childLink?: ClassNameValue; childLinkWrapper?: ClassNameValue; childLinkIcon?: ClassNameValue; childLinkHint?: ClassNameValue; childLinkBadge?: ClassNameValue; childLinkBadgeSize?: ClassNameValue; childLinkLabel?: ClassNameValue; childLinkLabelExternalIcon?: ClassNameValue; separator?: ClassNameValue; popoverWrapper?: ClassNameValue; viewportWrapper?: ClassNameValue; viewport?: ClassNameValue; content?: ClassNameValue; }, "label" | "content" | "link" | "linkTrailing" | "childList" | "item" | "linkLeadingIcon" | "linkLeadingAvatar" | "linkLeadingAvatarSize" | "linkLeadingHint" | "linkLeadingBadge" | "linkLeadingBadgeSize" | "linkTrailingIcon" | "linkLabel" | "linkLabelExternalIcon" | "childLabel" | "childItem" | "childLink" | "childLinkWrapper" | "childLinkIcon" | "childLinkHint" | "childLinkBadge" | "childLinkBadgeSize" | "childLinkLabel" | "childLinkLabelExternalIcon" | "popoverWrapper">
  • disabled?: boolean
  • to?: string | RouteLocationAsRelativeGeneric | RouteLocationAsPathGeneric

    Route Location the link should navigate to when clicked on.

  • autofocus?: Booleanish
  • name?: string
  • download?: any
  • hreflang?: string
  • media?: string
  • ping?: string
  • target?: (string & {}) | "_blank" | "_parent" | "_self" | "_top" | null

    Where to display the linked URL, as the name for a browsing context.

  • referrerpolicy?: HTMLAttributeReferrerPolicy
  • as?: any

    The element or component this component should render as when not a link. Defaults to 'button'.

  • active?: boolean

    Force the link to be active independent of the current route.

  • isAction?: boolean

    When true, uses special underlined styling.

  • trailingSlash?: "append" | "remove"

    An option to either add or remove trailing slashes in the href for this specific link. Overrides the global trailingSlash option if provided.

orientation'horizontal' "vertical" | "horizontal"

The orientation of the menu.

collapsedfalseboolean

Collapse the navigation menu to only show icons. Only works when orientation is vertical.

tooltipfalseboolean | TooltipProps

Display a tooltip on the items when the menu is collapsed with the label of the item. { delayDuration: 0, content: { side: 'right' } }

  • text?: string

    The text content of the tooltip.

  • kbds?: (string )[] | KbdProps[] | undefined

    The keyboard keys to display in the tooltip.

  • content?: (TooltipContentProps & Partial<EmitsToProps<TooltipContentImplEmits>>)

    The content of the tooltip. Defaults to { side: 'bottom', sideOffset: 8, collisionPadding: 8 }.

  • arrow?: boolean | TooltipArrowProps

    Display an arrow alongside the tooltip. Defaults to false.

  • portal?: string | boolean | HTMLElement

    Render the tooltip in a portal. Defaults to true.

  • reference?: ReferenceElement

    The reference (or anchor) element that is being referred to for positioning.

    If not provided will use the current component as anchor.

  • class?: any
  • b24ui?: { content?: ClassNameValue; arrow?: ClassNameValue; text?: ClassNameValue; kbds?: ClassNameValue; kbdsSize?: ClassNameValue; kbdsAccent?: ClassNameValue; }
  • defaultOpen?: boolean

    The open state of the tooltip when it is initially rendered. Use when you do not need to control its open state.

  • open?: boolean

    The controlled open state of the tooltip.

  • delayDuration?: number

    Override the duration given to the Provider to customise the open delay for a specific tooltip. Defaults to 700.

  • disableHoverableContent?: boolean

    Prevents Tooltip.Content from remaining open when hovering. Disabling this has accessibility consequences. Inherits from Tooltip.Provider.

  • disableClosingTrigger?: boolean

    When true, clicking on trigger will not close the content. Defaults to false.

  • disabled?: boolean

    When true, disable tooltip Defaults to false.

  • ignoreNonKeyboardFocus?: boolean

    Prevent the tooltip from opening if the focus did not come from the keyboard by matching against the :focus-visible selector. This is useful if you want to avoid opening it when switching browser tabs or closing a dialog. Defaults to false.

popoverfalseboolean | PopoverProps<PopoverMode>

Display a popover on the items when the menu is collapsed with the children list. { mode: 'hover', content: { side: 'right', align: 'center', alignOffset: 2 } }

content NavigationMenuContentProps & Partial<EmitsToProps<DismissableLayerEmits>>

The content of the menu.

  • disableOutsidePointerEvents?: boolean

    When true, hover/focus/click interactions will be disabled on elements outside the DismissableLayer. Users will need to click twice on outside elements to interact with them: once to close the DismissableLayer, and again to trigger the element.

  • onEscapeKeyDown?: ((event: KeyboardEvent) => void)
  • onPointerDownOutside?: ((event: PointerDownOutsideEvent) => void)
  • onFocusOutside?: ((event: FocusOutsideEvent) => void)
  • onInteractOutside?: ((event: PointerDownOutsideEvent | FocusOutsideEvent) => void)
labelKey'label' string | number

The key used to get the label from the item.

delayDuration0 number

The duration from when the pointer enters the trigger until the tooltip gets opened.

disableClickTriggerfalseboolean

If true, menu cannot be open by click on trigger

disableHoverTriggerfalseboolean

If true, menu cannot be open by hover on trigger

skipDelayDuration300 number

How much time a user has to enter another trigger without incurring a delay again.

disablePointerLeaveClosefalseboolean

If true, menu will not close during pointer leave event

unmountOnHidetrueboolean

When true, the element will be unmounted on closed state.

disabledfalseboolean

When true, prevents the user from interacting with the accordion and all its items

collapsibletrueboolean

When type is "single", allows closing content when clicking trigger for an open item. When type is "multiple", this prop has no effect.

b24ui { root?: ClassNameValue; list?: ClassNameValue; label?: ClassNameValue; item?: ClassNameValue; link?: ClassNameValue; linkLeadingIcon?: ClassNameValue; linkLeadingAvatar?: ClassNameValue; linkLeadingAvatarSize?: ClassNameValue; linkLeadingHint?: ClassNameValue; linkLeadingBadge?: ClassNameValue; linkLeadingBadgeSize?: ClassNameValue; linkTrailing?: ClassNameValue; linkTrailingIcon?: ClassNameValue; linkLabel?: ClassNameValue; linkLabelWrapper?: ClassNameValue; linkLabelExternalIcon?: ClassNameValue; childList?: ClassNameValue; childLabel?: ClassNameValue; childItem?: ClassNameValue; childLink?: ClassNameValue; childLinkWrapper?: ClassNameValue; childLinkIcon?: ClassNameValue; childLinkHint?: ClassNameValue; childLinkBadge?: ClassNameValue; childLinkBadgeSize?: ClassNameValue; childLinkLabel?: ClassNameValue; childLinkLabelExternalIcon?: ClassNameValue; separator?: ClassNameValue; popoverWrapper?: ClassNameValue; viewportWrapper?: ClassNameValue; viewport?: ClassNameValue; content?: ClassNameValue; }

Slots

Slot Type
item{ item: NavigationMenuItem; index: number; active?: boolean | undefined; b24ui: object; }
item-leading{ item: NavigationMenuItem; index: number; active?: boolean | undefined; b24ui: object; }
item-label{ item: NavigationMenuItem; index: number; active?: boolean | undefined; }
item-trailing{ item: NavigationMenuItem; index: number; active?: boolean | undefined; b24ui: object; }
item-content{ item: NavigationMenuItem; index: number; active?: boolean | undefined; b24ui: object; }
list-leading{}
list-trailing{}

Emits

Event Type
update:modelValue[value: string | string[] | undefined]

Theme

app.config.ts
export default defineAppConfig({
  b24ui: {
    navigationMenu: {
      slots: {
        root: 'relative flex [&>div]:min-w-0 font-[family-name:var(--ui-font-family-secondary)]',
        list: 'isolate min-w-0',
        label: 'w-full h-[22px] overflow-hidden mt-[10px] opacity-70 text-(length:--ui-font-size-sm)',
        item: 'min-w-0',
        link: 'min-w-[38px] w-full max-w-full p-0 m-0 group relative cursor-pointer flex items-center gap-[2px] font-(--ui-font-weight-normal) text-(length:--ui-font-size-lg) focus:outline-none focus-visible:rounded-(--menu-item-border-radius) focus-visible:outline-none focus-visible:ring-inset focus-visible:ring-1 focus-visible:ring-(--ui-color-base-4) rounded-(--menu-item-border-radius) text-(--menu-item-color) bg-(--menu-item-background) hover:bg-(--menu-item-background-hover) data-[state=open]:bg-(--menu-item-background-hover) border-0',
        linkLeadingIcon: 'shrink-0 size-[26px]',
        linkLeadingAvatar: 'shrink-0',
        linkLeadingAvatarSize: 'xs',
        linkLeadingHint: 'inline-flex m-0 absolute -top-[5px] left-[8px] text-(length:--ui-font-size-4xs) leading-[8px] font-semibold text-(--b24ui-typography-description-color) uppercase ml-px',
        linkLeadingBadge: 'inline-flex m-0 absolute',
        linkLeadingBadgeSize: 'xs',
        linkTrailing: 'group inline-flex mt-[2px] items-center',
        linkTrailingIcon: 'text-(--ui-color-design-plain-na-content-icon) shrink-0',
        linkLabel: 'truncate',
        linkLabelWrapper: 'flex items-center justify-between rtl:flex-row-reverse',
        linkLabelExternalIcon: 'inline-block size-[16px] text-(--ui-color-design-plain-content-icon-secondary)',
        childList: 'isolate',
        childLabel: '',
        childItem: 'h-[36px] mt-(--menu-item-block-stack-space)',
        childLink: 'group relative size-full flex flex-row rtl:flex-row-reverse items-center transition-colors text-start',
        childLinkWrapper: 'min-w-0 flex-1 flex flex-row items-center justify-start rtl:justify-end gap-0.5',
        childLinkIcon: 'size-[18px] shrink-0',
        childLinkHint: 'inline-flex m-0 absolute -top-[2px] left-[24px] text-(length:--ui-font-size-4xs) leading-[8px] font-semibold text-(--b24ui-typography-description-color) uppercase ml-px',
        childLinkBadge: 'inline-flex m-0',
        childLinkBadgeSize: 'xs',
        childLinkLabel: 'truncate ms-[2px] -mt-px',
        childLinkLabelExternalIcon: 'inline-block size-4 text-(--ui-color-design-plain-content-icon-secondary)',
        separator: 'h-px bg-(--leftmenu-bg-divider) my-[16px]',
        popoverWrapper: 'px-0 py-(--menu-popup-padding)',
        viewportWrapper: 'absolute top-[53px] left-0 flex w-full',
        viewport: 'light relative overflow-hidden w-full bg-(--popup-window-background-color) shadow-(--popup-window-box-shadow) h-(--reka-navigation-menu-viewport-height) w-(--reka-navigation-menu-viewport-width) left-(--reka-navigation-menu-viewport-left) rounded-(--popup-window-border-radius) will-change-[opacity] [&:has(>[data-viewport=rtl])]:left-auto [&:has(>[data-viewport=rtl])]:-right-[calc(100%-var(--reka-navigation-menu-viewport-width))] transition-[width,height] duration-200 origin-[top_center] z-[1]',
        content: ''
      },
      variants: {
        orientation: {
          horizontal: {
            root: 'relative h-full items-center justify-between',
            list: 'flex items-center gap-x-1 h-full',
            item: 'empty:hidden',
            link: 'menu-item-horizontal h-[32px] min-h-[32px] px-[10px] border border-(--menu-item-background) hover:border-(--ui-color-design-plain-na-focused-stroke) data-[state=open]:bg-(--ui-color-design-plain-na-focused-stroke)',
            linkTrailingIcon: 'size-[16px]',
            linkLeadingBadge: '-top-[6px] -right-[14px] -translate-x-1/2',
            linkLabelWrapper: 'gap-[4px] truncate',
            childList: 'grid px-0 py-(--menu-popup-padding)',
            childLink: 'px-[18px] min-w-[195px] whitespace-nowrap font-[family-name:var(--ui-font-family-primary)] text-(length:--menu-popup-item-font-size) text-(--menu-popup-item-color) hover:text-(--menu-popup-item-color-hover) hover:bg-(--menu-popup-item-bg-color-hover)',
            childLinkLabel: '',
            content: 'absolute top-0 left-0 w-full max-h-[70vh] overflow-y-auto scrollbar-thin scrollbar-transparent'
          },
          vertical: {
            root: 'flex-col w-full ps-(--menu-items-block-padding-x) rtl:pe-(--menu-items-block-padding-x)',
            list: 'flex flex-col',
            item: 'mt-(--menu-item-block-stack-space) data-[state=open]:rounded-(--menu-item-border-radius) data-[state=open]:border-(length:--leftmenu-group-stroke-weight) data-[state=open]:border-(--leftmenu-group-stroke)',
            link: 'menu-item-vertical overflow-hidden h-[38px] min-h-[38px] p-[6px] flex-row rtl:flex-row-reverse justify-between data-[state=open]:text-(length:--ui-font-size-sm) data-[state=open]:opacity-70',
            linkLeadingIcon: '',
            linkTrailingIcon: 'size-[20px] group-data-[state=open]:rotate-180 transition-transform duration-200',
            linkLeadingBadge: '-top-[4px] left-[24px] -translate-x-1/2',
            linkLabelWrapper: 'relative h-[22px]',
            childList: '',
            childLink: 'px-[18px] min-w-[195px] whitespace-nowrap font-[family-name:var(--ui-font-family-primary)] text-(length:--menu-popup-item-font-size) text-(--menu-popup-item-color) hover:text-(--menu-popup-item-color-hover) hover:bg-(--menu-popup-item-bg-color-hover)',
            childLabel: 'w-full min-w-[195px] h-(--popup-window-delimiter-section-height) px-[18px] mt-(--menu-item-block-stack-space) flex flex-row rtl:flex-row-reverse items-center select-none outline-none whitespace-nowrap text-start text-(length:--popup-window-delimiter-font-size) text-(--popup-window-delimiter-text-color) font-(--popup-window-delimiter-font-weight) after:ms-[10px] after:block after:flex-1 after:min-w-[15px] after:h-px after:bg-(--popup-window-delimiter-bg-color)'
          }
        },
        active: {
          true: {
            childLink: 'text-(--ui-color-accent-main-primary) hover:text-(--ui-color-accent-main-primary)',
            childLinkIcon: 'text-(--ui-color-accent-main-primary)'
          },
          false: {
            linkLeadingIcon: 'text-(--ui-color-design-plain-content-icon-secondary)',
            childLinkIcon: 'text-(--ui-color-design-plain-content-icon-secondary) group-hover:text-(--ui-color-accent-main-primary)'
          }
        },
        disabled: {
          true: {
            link: 'cursor-not-allowed opacity-75'
          }
        },
        level: {
          true: ''
        },
        collapsed: {
          true: ''
        }
      },
      compoundVariants: [
        {
          orientation: 'horizontal',
          class: {
            childList: '',
            content: 'w-[240px]'
          }
        },
        {
          orientation: 'vertical',
          collapsed: false,
          class: {
            item: 'data-[state=open]:bg-(--leftmenu-group-bg)',
            childList: '',
            childItem: '',
            content: 'motion-safe:data-[state=open]:animate-[collapsible-down_200ms_ease-out] motion-safe:data-[state=closed]:animate-[collapsible-up_200ms_ease-out] overflow-hidden',
            linkLabel: 'ms-[9px]'
          }
        },
        {
          orientation: 'vertical',
          collapsed: true,
          class: {
            childList: 'grid px-0 py-(--menu-popup-padding)',
            linkLabel: 'hidden',
            linkTrailing: 'hidden'
          }
        },
        {
          orientation: 'vertical',
          collapsed: false,
          class: {
            link: 'collapsed data-[state=open]:-mt-(--leftmenu-group-stroke-weight) data-[state=open]:-mx-(--leftmenu-group-stroke-weight)'
          }
        },
        {
          disabled: false,
          active: false,
          class: {
            link: 'transition-colors',
            linkLeadingIcon: 'group-hover:text-(--ui-color-design-selection-content-icon)'
          }
        },
        {
          active: true,
          class: {
            link: 'leading-9 text-(--menu-item-color-active) bg-(--menu-item-background-active)'
          }
        },
        {
          active: true,
          orientation: 'horizontal',
          class: {
            link: 'menu-item-horizontal-active border-(--menu-item-border)'
          }
        },
        {
          active: true,
          orientation: 'vertical',
          class: {
            link: 'menu-item-vertical-active'
          }
        }
      ],
      defaultVariants: {}
    }
  }
})
vite.config.ts
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import bitrix24UIPluginVite from '@bitrix24/b24ui-nuxt/vite'

export default defineConfig({
  plugins: [
    vue(),
    bitrix24UIPluginVite({
      b24ui: {
        navigationMenu: {
          slots: {
            root: 'relative flex [&>div]:min-w-0 font-[family-name:var(--ui-font-family-secondary)]',
            list: 'isolate min-w-0',
            label: 'w-full h-[22px] overflow-hidden mt-[10px] opacity-70 text-(length:--ui-font-size-sm)',
            item: 'min-w-0',
            link: 'min-w-[38px] w-full max-w-full p-0 m-0 group relative cursor-pointer flex items-center gap-[2px] font-(--ui-font-weight-normal) text-(length:--ui-font-size-lg) focus:outline-none focus-visible:rounded-(--menu-item-border-radius) focus-visible:outline-none focus-visible:ring-inset focus-visible:ring-1 focus-visible:ring-(--ui-color-base-4) rounded-(--menu-item-border-radius) text-(--menu-item-color) bg-(--menu-item-background) hover:bg-(--menu-item-background-hover) data-[state=open]:bg-(--menu-item-background-hover) border-0',
            linkLeadingIcon: 'shrink-0 size-[26px]',
            linkLeadingAvatar: 'shrink-0',
            linkLeadingAvatarSize: 'xs',
            linkLeadingHint: 'inline-flex m-0 absolute -top-[5px] left-[8px] text-(length:--ui-font-size-4xs) leading-[8px] font-semibold text-(--b24ui-typography-description-color) uppercase ml-px',
            linkLeadingBadge: 'inline-flex m-0 absolute',
            linkLeadingBadgeSize: 'xs',
            linkTrailing: 'group inline-flex mt-[2px] items-center',
            linkTrailingIcon: 'text-(--ui-color-design-plain-na-content-icon) shrink-0',
            linkLabel: 'truncate',
            linkLabelWrapper: 'flex items-center justify-between rtl:flex-row-reverse',
            linkLabelExternalIcon: 'inline-block size-[16px] text-(--ui-color-design-plain-content-icon-secondary)',
            childList: 'isolate',
            childLabel: '',
            childItem: 'h-[36px] mt-(--menu-item-block-stack-space)',
            childLink: 'group relative size-full flex flex-row rtl:flex-row-reverse items-center transition-colors text-start',
            childLinkWrapper: 'min-w-0 flex-1 flex flex-row items-center justify-start rtl:justify-end gap-0.5',
            childLinkIcon: 'size-[18px] shrink-0',
            childLinkHint: 'inline-flex m-0 absolute -top-[2px] left-[24px] text-(length:--ui-font-size-4xs) leading-[8px] font-semibold text-(--b24ui-typography-description-color) uppercase ml-px',
            childLinkBadge: 'inline-flex m-0',
            childLinkBadgeSize: 'xs',
            childLinkLabel: 'truncate ms-[2px] -mt-px',
            childLinkLabelExternalIcon: 'inline-block size-4 text-(--ui-color-design-plain-content-icon-secondary)',
            separator: 'h-px bg-(--leftmenu-bg-divider) my-[16px]',
            popoverWrapper: 'px-0 py-(--menu-popup-padding)',
            viewportWrapper: 'absolute top-[53px] left-0 flex w-full',
            viewport: 'light relative overflow-hidden w-full bg-(--popup-window-background-color) shadow-(--popup-window-box-shadow) h-(--reka-navigation-menu-viewport-height) w-(--reka-navigation-menu-viewport-width) left-(--reka-navigation-menu-viewport-left) rounded-(--popup-window-border-radius) will-change-[opacity] [&:has(>[data-viewport=rtl])]:left-auto [&:has(>[data-viewport=rtl])]:-right-[calc(100%-var(--reka-navigation-menu-viewport-width))] transition-[width,height] duration-200 origin-[top_center] z-[1]',
            content: ''
          },
          variants: {
            orientation: {
              horizontal: {
                root: 'relative h-full items-center justify-between',
                list: 'flex items-center gap-x-1 h-full',
                item: 'empty:hidden',
                link: 'menu-item-horizontal h-[32px] min-h-[32px] px-[10px] border border-(--menu-item-background) hover:border-(--ui-color-design-plain-na-focused-stroke) data-[state=open]:bg-(--ui-color-design-plain-na-focused-stroke)',
                linkTrailingIcon: 'size-[16px]',
                linkLeadingBadge: '-top-[6px] -right-[14px] -translate-x-1/2',
                linkLabelWrapper: 'gap-[4px] truncate',
                childList: 'grid px-0 py-(--menu-popup-padding)',
                childLink: 'px-[18px] min-w-[195px] whitespace-nowrap font-[family-name:var(--ui-font-family-primary)] text-(length:--menu-popup-item-font-size) text-(--menu-popup-item-color) hover:text-(--menu-popup-item-color-hover) hover:bg-(--menu-popup-item-bg-color-hover)',
                childLinkLabel: '',
                content: 'absolute top-0 left-0 w-full max-h-[70vh] overflow-y-auto scrollbar-thin scrollbar-transparent'
              },
              vertical: {
                root: 'flex-col w-full ps-(--menu-items-block-padding-x) rtl:pe-(--menu-items-block-padding-x)',
                list: 'flex flex-col',
                item: 'mt-(--menu-item-block-stack-space) data-[state=open]:rounded-(--menu-item-border-radius) data-[state=open]:border-(length:--leftmenu-group-stroke-weight) data-[state=open]:border-(--leftmenu-group-stroke)',
                link: 'menu-item-vertical overflow-hidden h-[38px] min-h-[38px] p-[6px] flex-row rtl:flex-row-reverse justify-between data-[state=open]:text-(length:--ui-font-size-sm) data-[state=open]:opacity-70',
                linkLeadingIcon: '',
                linkTrailingIcon: 'size-[20px] group-data-[state=open]:rotate-180 transition-transform duration-200',
                linkLeadingBadge: '-top-[4px] left-[24px] -translate-x-1/2',
                linkLabelWrapper: 'relative h-[22px]',
                childList: '',
                childLink: 'px-[18px] min-w-[195px] whitespace-nowrap font-[family-name:var(--ui-font-family-primary)] text-(length:--menu-popup-item-font-size) text-(--menu-popup-item-color) hover:text-(--menu-popup-item-color-hover) hover:bg-(--menu-popup-item-bg-color-hover)',
                childLabel: 'w-full min-w-[195px] h-(--popup-window-delimiter-section-height) px-[18px] mt-(--menu-item-block-stack-space) flex flex-row rtl:flex-row-reverse items-center select-none outline-none whitespace-nowrap text-start text-(length:--popup-window-delimiter-font-size) text-(--popup-window-delimiter-text-color) font-(--popup-window-delimiter-font-weight) after:ms-[10px] after:block after:flex-1 after:min-w-[15px] after:h-px after:bg-(--popup-window-delimiter-bg-color)'
              }
            },
            active: {
              true: {
                childLink: 'text-(--ui-color-accent-main-primary) hover:text-(--ui-color-accent-main-primary)',
                childLinkIcon: 'text-(--ui-color-accent-main-primary)'
              },
              false: {
                linkLeadingIcon: 'text-(--ui-color-design-plain-content-icon-secondary)',
                childLinkIcon: 'text-(--ui-color-design-plain-content-icon-secondary) group-hover:text-(--ui-color-accent-main-primary)'
              }
            },
            disabled: {
              true: {
                link: 'cursor-not-allowed opacity-75'
              }
            },
            level: {
              true: ''
            },
            collapsed: {
              true: ''
            }
          },
          compoundVariants: [
            {
              orientation: 'horizontal',
              class: {
                childList: '',
                content: 'w-[240px]'
              }
            },
            {
              orientation: 'vertical',
              collapsed: false,
              class: {
                item: 'data-[state=open]:bg-(--leftmenu-group-bg)',
                childList: '',
                childItem: '',
                content: 'motion-safe:data-[state=open]:animate-[collapsible-down_200ms_ease-out] motion-safe:data-[state=closed]:animate-[collapsible-up_200ms_ease-out] overflow-hidden',
                linkLabel: 'ms-[9px]'
              }
            },
            {
              orientation: 'vertical',
              collapsed: true,
              class: {
                childList: 'grid px-0 py-(--menu-popup-padding)',
                linkLabel: 'hidden',
                linkTrailing: 'hidden'
              }
            },
            {
              orientation: 'vertical',
              collapsed: false,
              class: {
                link: 'collapsed data-[state=open]:-mt-(--leftmenu-group-stroke-weight) data-[state=open]:-mx-(--leftmenu-group-stroke-weight)'
              }
            },
            {
              disabled: false,
              active: false,
              class: {
                link: 'transition-colors',
                linkLeadingIcon: 'group-hover:text-(--ui-color-design-selection-content-icon)'
              }
            },
            {
              active: true,
              class: {
                link: 'leading-9 text-(--menu-item-color-active) bg-(--menu-item-background-active)'
              }
            },
            {
              active: true,
              orientation: 'horizontal',
              class: {
                link: 'menu-item-horizontal-active border-(--menu-item-border)'
              }
            },
            {
              active: true,
              orientation: 'vertical',
              class: {
                link: 'menu-item-vertical-active'
              }
            }
          ],
          defaultVariants: {}
        }
      }
    })
  ]
})

Link

A wrapper around <NuxtLink> with extra props.

Pagination

A navigation component with buttons or links for pagination.

On this page

  • Usage
    • Items
    • Orientation
    • Collapsed
    • Trailing Icon
    • Unmount
  • Examples
    • With tooltip in items
    • With popover in items
    • Control active item
    • With custom slot
    • With content slot
  • API
    • Props
    • Slots
    • Emits
  • Theme
Releases
Published under MIT License.

Copyright © 2024-present Bitrix24