Skip to content
🌏 Translated with the assistance of DeepSeek and ChatGPT

Menu

Must feed.

Basic Usage

Organize the menu structure through Menu, MenuItem, MenuGroup, and Submenu components.

When MenuItem receives the href or route parameter, it will be rendered as an <a> tag or as a Vue Router RouterLink component.

WARNING

The href and route properties will be directly rendered into the <a> tag. If values such as javascript:alert(1) or malicious URLs are passed, this may lead to XSS or open redirect vulnerabilities.

<template>
	<px-menu :default-active="'Home'">
		<px-menu-item index="Home" href="/pixelium-design/">
			Home
			<template #icon>
				<IconHome></IconHome>
			</template>
		</px-menu-item>
		<px-submenu index="Components" label="Components">
			<template #icon>
				<IconBars></IconBars>
			</template>
			<px-menu-item index="Button">
				Button
				<template #icon>
					<IconArrowAltCircleUp></IconArrowAltCircleUp>
				</template>
			</px-menu-item>
			<px-menu-item index="Input">
				Input
				<template #icon>
					<IconPencil></IconPencil>
				</template>
			</px-menu-item>
		</px-submenu>
		<px-menu-group index="More" label="More">
			<px-menu-item index="About">
				About
				<template #icon>
					<IconLink></IconLink>
				</template>
			</px-menu-item>
			<px-menu-item
				index="Github"
				href="https://github.com/shika-works/pixelium-design"
				target="_blank"
			>
				Github
				<template #icon>
					<IconGithub></IconGithub>
				</template>
			</px-menu-item>
		</px-menu-group>
	</px-menu>
</template>

<script setup lang="ts">
import {
	IconHome,
	IconArrowAltCircleUp,
	IconPencil,
	IconGithub,
	IconLink,
	IconBars
} from '@pixelium/web-vue/icon-hn/es'
</script>

Horizontal Menu

When direction is set to "horizontal", a horizontal menu is displayed. When ellipsis is true, overflowing menu items are automatically collapsed into a "..." submenu.

<template>
	<px-menu direction="horizontal" :ellipsis="true">
		<px-menu-item :key="i" :index="i" v-for="i in 15">Item {{ i }}</px-menu-item>
	</px-menu>
</template>

Collapsed Sidebar Mode

Use collapsed for sidebars to show compact UI.

<template>
	<div>
		<px-switch v-model="collapsed" inactive-tip="Expanded" active-tip="Collapsed"></px-switch>
		<px-menu :collapsed="collapsed" :default-active="1" style="margin-top: 8px">
			<px-menu-item index="Overview">
				Overview
				<template #icon>
					<IconGrid></IconGrid>
				</template>
			</px-menu-item>
			<px-submenu index="Components" label="Components">
				<template #icon>
					<IconBars></IconBars>
				</template>
				<px-menu-item index="Input">
					Input
					<template #icon>
						<IconPencil></IconPencil>
					</template>
				</px-menu-item>
				<px-menu-item index="Search">
					Search
					<template #icon>
						<IconSearch></IconSearch>
					</template>
				</px-menu-item>
			</px-submenu>
			<px-menu-group index="Help" label="Help">
				<px-menu-item index="Document">
					Document
					<template #icon>
						<IconFolder></IconFolder>
					</template>
				</px-menu-item>
				<px-menu-item index="AI">
					AI
					<template #icon>
						<IconRobot></IconRobot>
					</template>
				</px-menu-item>
			</px-menu-group>
		</px-menu>
	</div>
</template>
<script setup lang="ts">
import {
	IconGrid,
	IconPencil,
	IconSearch,
	IconRobot,
	IconFolder,
	IconBars
} from '@pixelium/web-vue/icon-hn'
import { ref } from 'vue'

const collapsed = ref(true)
</script>

Groups & Submenus

Combine MenuGroup and Submenu for complex nested menus.

<template>
	<px-menu>
		<px-menu-group index="Undead" label="Undead">
			<px-submenu index="Hero" label="Hero">
				<px-menu-item index="Death Knight">Death Knight</px-menu-item>
				<px-menu-item index="Lich">Lich</px-menu-item>
			</px-submenu>
			<px-submenu index="Unit" label="Unit">
				<px-submenu index="Crypt" label="Crypt">
					<px-menu-item index="Ghoul">Ghoul</px-menu-item>
					<px-menu-item index="Crypt Fiend">Crypt Fiend</px-menu-item>
				</px-submenu>
				<px-submenu index="Boneyard" label="Boneyard">
					<px-menu-item index="Frost Wyrm">Frost Wyrm</px-menu-item>
				</px-submenu>
			</px-submenu>
		</px-menu-group>
	</px-menu>
</template>

Emphasized Menu

Set the Menu dark attribute to true to enable high-contrast dark mode.

<template>
	<px-menu :default-active="'Home'" dark>
		<px-menu-item index="Home">
			Home
			<template #icon>
				<IconHome></IconHome>
			</template>
		</px-menu-item>
		<px-submenu index="Components" label="Components">
			<template #icon>
				<IconBars></IconBars>
			</template>
			<px-menu-item index="Button">
				Button
				<template #icon>
					<IconArrowAltCircleUp></IconArrowAltCircleUp>
				</template>
			</px-menu-item>
			<px-menu-item index="Input">
				Input
				<template #icon>
					<IconPencil></IconPencil>
				</template>
			</px-menu-item>
		</px-submenu>
		<px-menu-group index="More" label="More">
			<px-menu-item index="About">
				About
				<template #icon>
					<IconLink></IconLink>
				</template>
			</px-menu-item>
			<px-menu-item index="Github">
				Github
				<template #icon>
					<IconGithub></IconGithub>
				</template>
			</px-menu-item>
		</px-menu-group>
	</px-menu>
</template>

<script setup lang="ts">
import {
	IconHome,
	IconArrowAltCircleUp,
	IconPencil,
	IconGithub,
	IconLink,
	IconBars
} from '@pixelium/web-vue/icon-hn/es'
</script>

Options Property

The options property of Menu is used to directly pass in options, which can be used for quick creation of simple menus. The string value of the option and the index field of the option serve as unique identifiers for the menu sub-components. It is recommended to ensure their uniqueness.

<template>
	<px-space direction="vertical">
		<px-menu :options="optionsHorizontal" direction="horizontal"> </px-menu>
		<px-menu :options="optionsVertical"> </px-menu>
	</px-space>
</template>

<script setup lang="ts">
import {
	IconHome,
	IconArrowAltCircleUp,
	IconPencil,
	IconGithub,
	IconLink,
	IconBars
} from '@pixelium/web-vue/icon-hn/es'
import { h, ref } from 'vue'

const optionsVertical = ref([
	{
		label: 'Home',
		index: 'Home',
		href: '/pixelium-design/',
		icon: h(IconHome)
	},
	{
		label: 'Components',
		index: 'Components',
		icon: h(IconBars),
		type: 'submenu',
		children: [
			{
				label: 'Button',
				index: 'Button',
				icon: h(IconArrowAltCircleUp)
			},
			{
				label: 'Input',
				index: 'Input',
				icon: h(IconPencil)
			}
		]
	},
	{
		label: 'More',
		index: 'More',
		type: 'group',
		children: [
			{
				label: 'About',
				index: 'About',
				icon: h(IconLink)
			},
			{
				label: 'Github',
				index: 'Github',
				href: 'https://github.com/shika-works/pixelium-design',
				target: '_blank',
				icon: h(IconGithub)
			},
			'Contact us'
		]
	}
])
const optionsHorizontal = ref([
	{
		label: 'Home',
		index: 'Home',
		href: '/pixelium-design/',
		icon: h(IconHome)
	},
	{
		label: 'Components',
		index: 'Components',
		icon: h(IconBars),
		type: 'submenu',
		children: [
			{
				label: 'Form',
				type: 'submenu',
				children: [
					{
						label: 'Button',
						index: 'Button',
						icon: h(IconArrowAltCircleUp)
					},
					{
						label: 'Input',
						index: 'Input',
						icon: h(IconPencil)
					}
				]
			}
		]
	},
	{
		label: 'More',
		index: 'More',
		type: 'submenu',
		children: [
			{
				label: 'Link',
				index: 'Link',
				type: 'group',
				children: [
					{
						label: 'About',
						index: 'About',
						icon: h(IconLink)
					},
					{
						label: 'Github',
						index: 'Github',
						href: 'https://github.com/shika-works/pixelium-design',
						target: '_blank',
						icon: h(IconGithub)
					},
					'Contact us'
				]
			}
		]
	}
])
</script>

Controlled Menu

Control the selected menu and expanded menus by passing active and expanded. Supports v-model. If not passed or set to undefined, it operates in uncontrolled mode. In this case, default values can be set using defaultActive and defaultExpanded.

Active: 1 | Expanded: [ "2" ]
<template>
	<div>
		<px-menu v-model:active="active" v-model:expanded="expanded">
			<px-menu-item index="1">Home</px-menu-item>
			<px-submenu index="2" label="Features">
				<px-menu-item index="2-1">One</px-menu-item>
				<px-menu-item index="2-2">Two</px-menu-item>
			</px-submenu>
		</px-menu>

		<div style="margin-top: 12px">Active: {{ active }} | Expanded: {{ expanded }}</div>
	</div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
const active = ref('1')
const expanded = ref(['2'])
</script>

API

AttributeTypeOptionalDefaultDescriptionVersion
direction'horizontal' | 'vertical'True'vertical'Orientation of the menu.0.1.0
darkbooleanTruefalseWhether the menu uses dark mode.0.1.0
activenumber | string | symbol | nullTrueActivated menu item. Supports controlled mode via v-model.0.1.0
defaultActivenumber | string | symbol | nullTrueDefault value for the activated menu item in uncontrolled mode.0.1.0
expanded(number | string | symbol)[] | nullTrueExpanded submenus. Supports controlled mode via v-model.0.1.0
defaultExpanded(number | string | symbol)[] | nullTrueDefault value for expanded submenus in uncontrolled mode.0.1.0
collapsedbooleanTruefalseWhether the vertical menu is collapsed.0.1.0
submenuMode'inline' | 'popover'True'inline'Display mode for submenus. This value will be used if the submenu's own mode is not set.0.1.0
submenuTrigger'hover' | 'click'True'hover'Trigger method for submenu popups. This value will be used if the submenu's own trigger is not set.0.1.0
indentnumberTrue16Indentation for each menu level.0.1.0
ellipsisbooleanTruetrueWhether overflowing items in a horizontal menu are collapsed into a "..." submenu.0.1.0
options(string | MenuOption | MenuGroupOption | SubmenuOption)[]TrueOptions for creating menu sub-components, effective when the default slot is not passed.0.1.0
EventParameterDescriptionVersion
update:activevalue: number | string | symbolCallback when active updates.0.1.0
update:expendvalue: (number | string | symbol)[]0.1.0
selectindex: number | string | symbol, event: MouseEventCallback when a menu item is selected.0.1.0
expandChangevalue: (number | string | symbol)[], event: MouseEventCallback when expanded submenus change.0.1.0
expandindex: number | string | symbol, event: MouseEventCallback triggered when a submenu expands.0.1.0
foldindex: number | string | symbol, event: MouseEventCallback triggered when a submenu folds.0.1.0
SlotParameterDescriptionVersion
defaultChild components that make up the menu.0.1.0
AttributeTypeOptionalDefaultDescriptionVersion
labelstringTrueText label.0.1.0
indexnumber | string | symbolFalseUnique identifier. The index property of MenuItem and Submenu components must not be duplicated.0.1.0
disabledbooleanTruefalseWhether it is disabled.0.1.0
routestring | objectTrue0.1.0
hrefstringTrueThe href attribute of the <a> tag. When a href parameter is passed, it will render the text label as an <a> tag.0.1.0
targetstringTrueThe target attribute of the <a> tag.0.1.0
SlotParameterDescriptionVersion
defaultText label.0.1.0
iconIcon.0.1.0
AttributeTypeOptionalDefaultDescriptionVersion
labelstringTrueText label.0.1.0
indexnumber | string | symbolFalseUnique identifier. The index property of MenuItem and Submenu components must not be duplicated.0.1.0
disabledbooleanTruefalseWhether it is disabled.0.1.0
modebooleanTrueDisplay mode for the submenu. inline renders it as an inline dropdown, popover renders it in a popup window. The inline value only takes effect within vertical menus and non-popup submenus.0.1.0
triggerbooleanTrueTrigger method for the submenu popup.0.1.0
popoverPropsOmit<PopoverProps, 'visible' | 'defaultVisible' | 'content'> & EmitEvent<PopoverEvents>TrueProperties for the internal Popover component.0.1.0
SlotParameterDescriptionVersion
defaultChild components that make up the menu.0.1.0
labelText label.0.1.0
iconIcon.0.1.0
AttributeTypeOptionalDefaultDescriptionVersion
labelstringTrueText label.0.1.0
SlotParameterDescriptionVersion
defaultChild components that make up the menu.0.1.0
labelText label.0.1.0
ts
export interface MenuOption extends NavigationOption {
	disabled?: boolean
	href?: string
	route?: string | object
	target?: string
	icon?: () => ValidVNodeContent
}

export interface MenuGroupOption extends NavigationOption {
	children: (string | MenuOption | MenuGroupOption | SubmenuOption)[]
	type: 'group'
}

export interface SubmenuOption extends NavigationOption {
	children: (string | MenuOption | MenuGroupOption | SubmenuOption)[]
	disabled?: boolean
	type: 'submenu'
	icon?: () => ValidVNodeContent
}

export interface NavigationOption {
	index: string | number | symbol
	label?: string
}
export type ValidVNodeContent = (...args: any[]) => VNode | JSX.Element

EmitEvent

ts
export type EmitEvent<T extends Record<string, any>> = {
	[K in keyof T as `on${Capitalize<K & string>}`]?: (...args: T[K]) => void
}