Updated menu demos

pull/4755/head^2
Cagatay Civici 2023-11-04 11:20:02 +03:00
parent f5e1c67c07
commit e2accc3d61
7 changed files with 488 additions and 340 deletions

View File

@ -13,8 +13,8 @@ export default {
data() {
return {
items: [
{ label: 'New', icon: 'pi pi-fw pi-plus' },
{ label: 'Delete', icon: 'pi pi-fw pi-trash' }
{ label: 'New', icon: 'pi pi-plus' },
{ label: 'Search', icon: 'pi pi-search' }
],
code: {
basic: `
@ -32,8 +32,8 @@ export default {
data() {
return {
items: [
{ label: 'New', icon: 'pi pi-fw pi-plus' },
{ label: 'Delete', icon: 'pi pi-fw pi-trash' }
{ label: 'New', icon: 'pi pi-plus' },
{ label: 'Search', icon: 'pi pi-search' }
]
};
}
@ -51,8 +51,8 @@ export default {
import { ref } from "vue";
const items = ref([
{ label: 'New', icon: 'pi pi-fw pi-plus' },
{ label: 'Delete', icon: 'pi pi-fw pi-trash' }
{ label: 'New', icon: 'pi pi-plus' },
{ label: 'Search', icon: 'pi pi-search' }
]);
<\/script>
`

105
doc/menu/CommandDoc.vue Normal file
View File

@ -0,0 +1,105 @@
<template>
<DocSectionText v-bind="$attrs">
<p>The <i>command</i> property defines the callback to run when an item is activated by click or a key event.</p>
</DocSectionText>
<div class="card flex justify-content-center">
<Menu :model="items" />
</div>
<DocSectionCode :code="code" />
</template>
<script>
export default {
data() {
return {
items: [
{
label: 'New',
icon: 'pi pi-plus',
command: () => {
this.$toast.add({ severity: 'success', summary: 'Success', detail: 'File created', life: 3000 });
}
},
{
label: 'Search',
icon: 'pi pi-search',
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Search Completed', detail: 'No results found', life: 3000 });
}
}
],
code: {
basic: `
<Menu :model="items" />
<Toast />
`,
options: `
<template>
<div class="card flex justify-content-center">
<Menu :model="items" />
<Toast />
</div>
</template>
<script>
export default {
data() {
return {
items: [
{
label: 'New',
icon: 'pi pi-plus',
command: () => {
this.$toast.add({ severity: 'success', summary: 'Success', detail: 'File created', life: 3000 });
}
},
{
label: 'Search',
icon: 'pi pi-search',
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Search Completed', detail: 'No results found', life: 3000 });
}
}
]
};
}
};
<\/script>
`,
composition: `
<template>
<div class="card flex justify-content-center">
<Menu :model="items" />
<Toast />
</div>
</template>
<script setup>
import { ref } from "vue";
import { useToast } from "primevue/usetoast";
const toast = useToast();
const items = ref([
{
label: 'New',
icon: 'pi pi-plus',
command: () => {
toast.add({ severity: 'success', summary: 'Success', detail: 'File created', life: 3000 });
}
},
{
label: 'Search',
icon: 'pi pi-search',
command: () => {
toast.add({ severity: 'warn', summary: 'Search Completed', detail: 'No results found', life: 3000 });
}
}
]);
<\/script>
`
}
};
}
};
</script>

View File

@ -1,6 +1,6 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Menu supports one level of nesting by defining children with <i>items</i> property.</p>
<p>Menu supports single level of grouping by defining children with the <i>items</i> property.</p>
</DocSectionText>
<div class="card flex justify-content-center">
<Menu :model="items" />
@ -14,21 +14,28 @@ export default {
return {
items: [
{
label: 'Options',
label: 'Documents',
items: [
{
label: 'Update',
icon: 'pi pi-refresh',
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
label: 'New',
icon: 'pi pi-plus'
},
{
label: 'Delete',
icon: 'pi pi-times',
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
label: 'Search',
icon: 'pi pi-search'
}
]
},
{
label: 'Profile',
items: [
{
label: 'Settings',
icon: 'pi pi-cog'
},
{
label: 'Logout',
icon: 'pi pi-sign-out'
}
]
}
@ -36,13 +43,11 @@ export default {
code: {
basic: `
<Menu :model="items" />
<Toast />
`,
options: `
<template>
<div class="card flex justify-content-center">
<Menu :model="items" />
<Toast />
</div>
</template>
@ -52,21 +57,28 @@ export default {
return {
items: [
{
label: 'Options',
label: 'Documents',
items: [
{
label: 'Update',
icon: 'pi pi-refresh',
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
label: 'New',
icon: 'pi pi-plus'
},
{
label: 'Delete',
icon: 'pi pi-times',
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
label: 'Search',
icon: 'pi pi-search'
}
]
},
{
label: 'Profile',
items: [
{
label: 'Settings',
icon: 'pi pi-cog'
},
{
label: 'Logout',
icon: 'pi pi-sign-out'
}
]
}
@ -80,32 +92,36 @@ export default {
<template>
<div class="card flex justify-content-center">
<Menu :model="items" />
<Toast />
</div>
</template>
<script setup>
import { ref } from "vue";
import { useToast } from "primevue/usetoast";
const toast = useToast();
const items = ref([
{
label: 'Options',
label: 'Documents',
items: [
{
label: 'Update',
icon: 'pi pi-refresh',
command: () => {
toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
label: 'New',
icon: 'pi pi-plus'
},
{
label: 'Delete',
icon: 'pi pi-times',
command: () => {
toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
label: 'Search',
icon: 'pi pi-search'
}
]
},
{
label: 'Profile',
items: [
{
label: 'Settings',
icon: 'pi pi-cog'
},
{
label: 'Logout',
icon: 'pi pi-sign-out'
}
]
}

View File

@ -1,9 +1,9 @@
<template>
<DocSectionText v-bind="$attrs">
<p>Popup mode is enabled by adding <i>popup</i> property and calling <i>toggle</i> method with an event of the target.</p>
<p>Overlay mode is enabled by adding <i>popup</i> property and calling <i>toggle</i> function of the menu ref with an event of the target.</p>
</DocSectionText>
<div class="card flex justify-content-center">
<Button type="button" label="Toggle" @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
<Button type="button" icon="pi pi-ellipsis-v" plain @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
<Menu ref="menu" id="overlay_menu" :model="items" :popup="true" />
</div>
<DocSectionCode :code="code" />
@ -18,34 +18,26 @@ export default {
label: 'Options',
items: [
{
label: 'Update',
icon: 'pi pi-refresh',
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
label: 'Refresh',
icon: 'pi pi-refresh'
},
{
label: 'Delete',
icon: 'pi pi-times',
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
}
label: 'Export',
icon: 'pi pi-upload'
}
]
}
],
code: {
basic: `
<Button type="button" label="Toggle" @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
<Button type="button" icon="pi pi-ellipsis-v" @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
<Menu ref="menu" id="overlay_menu" :model="items" :popup="true" />
<Toast />
`,
options: `
<template>
<div class="card flex justify-content-center">
<Button type="button" label="Toggle" @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
<Button type="button" icon="pi pi-ellipsis-v" @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
<Menu ref="menu" id="overlay_menu" :model="items" :popup="true" />
<Toast />
</div>
</template>
@ -55,23 +47,12 @@ export default {
return {
items: [
{
label: 'Options',
items: [
{
label: 'Update',
icon: 'pi pi-refresh',
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
label: 'Refresh',
icon: 'pi pi-refresh'
},
{
label: 'Delete',
icon: 'pi pi-times',
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
}
}
]
label: 'Export',
icon: 'pi pi-upload'
}
]
};
@ -79,46 +60,34 @@ export default {
methods: {
toggle(event) {
this.$refs.menu.toggle(event);
},
save() {
this.$toast.add({ severity: 'success', summary: 'Success', detail: 'Data Saved', life: 3000 });
}
},
}
};
<\/script>
`,
composition: `
<template>
<div class="card flex justify-content-center">
<Button type="button" label="Toggle" @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
<Button type="button" icon="pi pi-ellipsis-v" @click="toggle" aria-haspopup="true" aria-controls="overlay_menu" />
<Menu ref="menu" id="overlay_menu" :model="items" :popup="true" />
<Toast />
</div>
</template>
<script setup>
import { ref } from "vue";
import { useToast } from "primevue/usetoast";
const toast = useToast();
const menu = ref();
const items = ref([
{
label: 'Options',
items: [
{
label: 'Update',
icon: 'pi pi-refresh',
command: () => {
toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
label: 'Refresh',
icon: 'pi pi-refresh'
},
{
label: 'Delete',
icon: 'pi pi-times',
command: () => {
toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
}
label: 'Export',
icon: 'pi pi-upload'
}
]
}
@ -127,10 +96,6 @@ const items = ref([
const toggle = (event) => {
menu.value.toggle(event);
};
const save = () => {
toast.add({severity: 'success', summary: 'Success', detail: 'Data Saved', life: 3000});
};
<\/script>
`
}

View File

@ -1,27 +1,24 @@
<template>
<DocSectionText v-bind="$attrs">
<p>
Since v3.33.0 the vue-router dependency of menu components is deprecated and templating should be used to define router links instead. This approach provides flexibility to be able to use any kind of router link component such as
<i>NuxtLink</i> or <i>router-link</i>. Here is an example with vue-router.
</p>
<p>Items with navigation are defined with templating to be able to use a router link component, an external link or programmatic navigation.</p>
</DocSectionText>
<div class="card flex justify-content-center">
<Menu :model="items">
<template #item="{ label, item, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="routerProps.navigate">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<template #item="{ item, props }">
<router-link v-if="item.route" v-slot="{ href, navigate }" :to="item.route" custom>
<a :href="href" v-bind="props.action" @click="navigate">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
</a>
</router-link>
<a v-else :href="item.url" :target="item.target" v-bind="props.action">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<a v-else v-ripple :href="item.url" :target="item.target" v-bind="props.action">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
</a>
</template>
</Menu>
</div>
<DocSectionCode :code="code" />
<DocSectionCode :code="code" hideStackBlitz hideCodeSandbox />
</template>
<script>
@ -29,38 +26,25 @@ export default {
data() {
return {
items: [
{
label: 'Options',
items: [
{
label: 'Update',
icon: 'pi pi-refresh',
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
},
{
label: 'Delete',
icon: 'pi pi-times',
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
}
}
]
},
{
label: 'Navigate',
items: [
{
label: 'Vue Website',
icon: 'pi pi-external-link',
url: 'https://vuejs.org/',
target: '_blank'
label: 'Router Link',
icon: 'pi pi-palette',
route: '/unstyled'
},
{
label: 'Upload',
icon: 'pi pi-upload',
route: '/fileupload'
label: 'Programmatic',
icon: 'pi pi-link',
command: () => {
this.$router.push('/installation');
}
},
{
label: 'External',
icon: 'pi pi-external-link',
url: 'https://vuejs.org/'
}
]
}
@ -68,16 +52,16 @@ export default {
code: {
basic: `
<Menu :model="items">
<template #item="{ label, item, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="routerProps.navigate">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<template #item="{ item, props }">
<router-link v-if="item.route" v-slot="{ href, navigate }" :to="item.route" custom>
<a :href="href" v-bind="props.action" @click="navigate">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
</a>
</router-link>
<a v-else :href="item.url" v-bind="props.action">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<a v-else v-ripple :href="item.url" :target="item.target" v-bind="props.action">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
</a>
</template>
</Menu>
@ -86,20 +70,19 @@ export default {
<template>
<div class="card flex justify-content-center">
<Menu :model="items">
<template #item="{ label, item, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="routerProps.navigate">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<template #item="{ item, props }">
<router-link v-if="item.route" v-slot="{ href, navigate }" :to="item.route" custom>
<a :href="href" v-bind="props.action" @click="navigate">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
</a>
</router-link>
<a v-else :href="item.url" v-bind="props.action">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<a v-else v-ripple :href="item.url" :target="item.target" v-bind="props.action">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
</a>
</template>
</Menu>
<Toast />
</div>
</template>
@ -109,40 +92,21 @@ export default {
return {
items: [
{
label: 'Options',
items: [
label: 'Router Link',
icon: 'pi pi-palette',
route: '/unstyled'
},
{
label: 'Update',
icon: 'pi pi-refresh',
label: 'Programmatic',
icon: 'pi pi-link',
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
this.$router.push('/installation');
}
},
{
label: 'Delete',
icon: 'pi pi-times',
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
}
}
]
},
{
label: 'Navigate',
items: [
{
label: 'Vue Website',
label: 'External',
icon: 'pi pi-external-link',
url: 'https://vuejs.org/',
target: '_blank',
},
{
label: 'Upload',
icon: 'pi pi-upload',
route: '/fileupload'
}
]
url: 'https://vuejs.org/'
}
]
};
@ -154,62 +118,45 @@ export default {
<template>
<div class="card flex justify-content-center">
<Menu :model="items">
<template #item="{ label, item, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<template #item="{ item, props }">
<router-link v-if="item.route" v-slot="{ href, navigate }" :to="item.route" custom>
<a :href="href" v-bind="props.action" @click="navigate">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
</a>
</router-link>
<a v-else :href="item.url" v-bind="props.action">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<a v-else v-ripple :href="item.url" :target="item.target" v-bind="props.action">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
</a>
</template>
</Menu>
<Toast />
</div>
</template>
<script setup>
import { ref } from "vue";
import { useRouter } from "vue";
const router = useRouter();
const items = ref([
{
label: 'Options',
items: [
label: 'Router Link',
icon: 'pi pi-palette',
route: '/unstyled'
},
{
label: 'Update',
icon: 'pi pi-refresh',
label: 'Programmatic',
icon: 'pi pi-link',
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
this.$router.push('/installation');
}
},
{
label: 'Delete',
icon: 'pi pi-times',
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
}
}
]
},
{
label: 'Navigate',
items: [
{
label: 'Vue Website',
label: 'External',
icon: 'pi pi-external-link',
url: 'https://vuejs.org/',
target: '_blank',
},
{
label: 'Upload',
icon: 'pi pi-upload',
route: '/fileupload'
}
]
url: 'https://vuejs.org/'
}
]);
<\/script>

View File

@ -1,32 +1,45 @@
<template>
<DocSectionText v-bind="$attrs">
<p>
Menu offers item customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter. When item templating is used, it is suggested to bind the <i>action</i> prop from the slot props to handle
accessibility and pass through attributes. Additionally, two slots named <i>start</i> and <i>end</i> are provided to embed content before or after the menu.
Menu offers item customization with the <i>item</i> template that receives the menuitem instance from the model as a parameter. When item templating is used, bind the <i>action</i> prop from the slot props to handle accessibility and pass
through attributes. The submenu header has its own <i>submenuheader</i> template and additional slots named <i>start</i> and <i>end</i> are provided to embed content before or after the menu.
</p>
</DocSectionText>
<div class="card flex justify-content-center">
<Menu :model="items">
<Menu :model="items" class="w-full md:w-15rem">
<template #start>
<button @click="profileClick" class="w-full p-link flex align-items-center p-2 pl-3 text-color hover:surface-200 border-noround">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<div class="flex flex-column align">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Agent</span>
</div>
</button>
<span class="inline-flex align-items-center gap-1 px-2 py-2">
<svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-2rem">
<path
d="M25.87 18.05L23.16 17.45L25.27 20.46V29.78L32.49 23.76V13.53L29.18 14.73L25.87 18.04V18.05ZM25.27 35.49L29.18 31.58V27.67L25.27 30.98V35.49ZM20.16 17.14H20.03H20.17H20.16ZM30.1 5.19L34.89 4.81L33.08 12.33L24.1 15.67L30.08 5.2L30.1 5.19ZM5.72 14.74L2.41 13.54V23.77L9.63 29.79V20.47L11.74 17.46L9.03 18.06L5.72 14.75V14.74ZM9.63 30.98L5.72 27.67V31.58L9.63 35.49V30.98ZM4.8 5.2L10.78 15.67L1.81 12.33L0 4.81L4.79 5.19L4.8 5.2ZM24.37 21.05V34.59L22.56 37.29L20.46 39.4H14.44L12.34 37.29L10.53 34.59V21.05L12.42 18.23L17.45 26.8L22.48 18.23L24.37 21.05ZM22.85 0L22.57 0.69L17.45 13.08L12.33 0.69L12.05 0H22.85Z"
fill="var(--primary-color)"
/>
<path
d="M30.69 4.21L24.37 4.81L22.57 0.69L22.86 0H26.48L30.69 4.21ZM23.75 5.67L22.66 3.08L18.05 14.24V17.14H19.7H20.03H20.16H20.2L24.1 15.7L30.11 5.19L23.75 5.67ZM4.21002 4.21L10.53 4.81L12.33 0.69L12.05 0H8.43002L4.22002 4.21H4.21002ZM21.9 17.4L20.6 18.2H14.3L13 17.4L12.4 18.2L12.42 18.23L17.45 26.8L22.48 18.23L22.5 18.2L21.9 17.4ZM4.79002 5.19L10.8 15.7L14.7 17.14H14.74H15.2H16.85V14.24L12.24 3.09L11.15 5.68L4.79002 5.2V5.19Z"
fill="var(--text-color)"
/>
</svg>
<span class="font-medium text-xl font-semibold">PRIME<span class="text-primary">APP</span></span>
</span>
</template>
<template #item="{ item, label, props }">
<a class="flex" v-bind="props.action">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<template #submenuheader="{ item }">
<span class="text-primary font-bold">{{ item.label }}</span>
</template>
<template #item="{ item, props }">
<a v-ripple class="flex align-items-center" v-bind="props.action">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
<Badge v-if="item.badge" class="ml-auto" :value="item.badge" />
<span v-if="item.shortcut" class="ml-auto border-1 surface-border border-round surface-100 text-sm p-1">{{ item.shortcut }}</span>
</a>
</template>
<template #end>
<button class="w-full p-link flex align-items-center p-2 pl-4 text-color hover:surface-200 border-noround">
<i class="pi pi-sign-out" />
<span class="ml-2">Log Out</span>
<button v-ripple class="relative overflow-hidden w-full p-link flex align-items-center p-2 pl-3 text-color hover:surface-200 border-noround">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<span class="inline-flex flex-column">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Admin</span>
</span>
</button>
</template>
</Menu>
@ -39,41 +52,78 @@ export default {
data() {
return {
items: [
{ separator: true },
{
separator: true
},
{
label: 'Documents',
items: [
{
label: 'New',
icon: 'pi pi-plus',
shortcut: '⌘+N'
},
{
label: 'Search',
icon: 'pi pi-search',
shortcut: '⌘+S'
}
]
},
{
label: 'Profile',
icon: 'pi pi-fw pi-user'
},
items: [
{
label: 'Settings',
icon: 'pi pi-fw pi-cog',
icon: 'pi pi-cog',
shortcut: '⌘+O'
},
{
label: 'Messages',
icon: 'pi pi-inbox',
badge: 2
},
{ separator: true }
{
label: 'Logout',
icon: 'pi pi-sign-out',
shortcut: '⌘+Q'
}
]
},
{
separator: true
}
],
code: {
basic: `
<Menu :model="items">
<Menu :model="items" class="w-full md:w-15rem">
<template #start>
<button @click="profileClick" class="w-full p-link flex align-items-center p-2 pl-3 text-color hover:surface-200 border-noround">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<div class="flex flex-column align">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Agent</span>
</div>
</button>
<span class="inline-flex align-items-center gap-1 px-2 py-2">
<svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-2rem">
<path d="..." fill="var(--primary-color)" />
<path d="..." fill="var(--text-color)" />
</svg>
<span class="font-medium text-xl font-semibold">PRIME<span class="text-primary">APP</span></span>
</span>
</template>
<template #item="{ item, label, props }">
<a class="flex" v-bind="props.action">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<template #submenuheader="{ item }">
<span class="text-primary font-bold">{{ item.label }}</span>
</template>
<template #item="{ item, props }">
<a v-ripple class="flex align-items-center" v-bind="props.action">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
<Badge v-if="item.badge" class="ml-auto" :value="item.badge" />
<span v-if="item.shortcut" class="ml-auto border-1 surface-border border-round surface-100 text-sm p-1">{{ item.shortcut }}</span>
</a>
</template>
<template #end>
<button class="w-full p-link flex align-items-center p-2 pl-4 text-color hover:surface-200 border-noround">
<i class="pi pi-sign-out" />
<span class="ml-2">Log Out</span>
<button v-ripple class="relative overflow-hidden w-full p-link flex align-items-center p-2 pl-3 text-color hover:surface-200 border-noround">
<Avatar image="/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<span class="inline-flex flex-column">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Admin</span>
</span>
</button>
</template>
</Menu>
@ -81,31 +131,43 @@ export default {
options: `
<template>
<div class="card flex justify-content-center">
<Menu :model="items">
<Menu :model="items" class="w-full md:w-15rem">
<template #start>
<button @click="profileClick" class="w-full p-link flex align-items-center p-2 pl-3 text-color hover:surface-200 border-noround">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<div class="flex flex-column align">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Agent</span>
</div>
</button>
<span class="inline-flex align-items-center gap-1 px-2 py-2">
<svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-2rem">
<path
d="M25.87 18.05L23.16 17.45L25.27 20.46V29.78L32.49 23.76V13.53L29.18 14.73L25.87 18.04V18.05ZM25.27 35.49L29.18 31.58V27.67L25.27 30.98V35.49ZM20.16 17.14H20.03H20.17H20.16ZM30.1 5.19L34.89 4.81L33.08 12.33L24.1 15.67L30.08 5.2L30.1 5.19ZM5.72 14.74L2.41 13.54V23.77L9.63 29.79V20.47L11.74 17.46L9.03 18.06L5.72 14.75V14.74ZM9.63 30.98L5.72 27.67V31.58L9.63 35.49V30.98ZM4.8 5.2L10.78 15.67L1.81 12.33L0 4.81L4.79 5.19L4.8 5.2ZM24.37 21.05V34.59L22.56 37.29L20.46 39.4H14.44L12.34 37.29L10.53 34.59V21.05L12.42 18.23L17.45 26.8L22.48 18.23L24.37 21.05ZM22.85 0L22.57 0.69L17.45 13.08L12.33 0.69L12.05 0H22.85Z"
fill="var(--primary-color)"
/>
<path
d="M30.69 4.21L24.37 4.81L22.57 0.69L22.86 0H26.48L30.69 4.21ZM23.75 5.67L22.66 3.08L18.05 14.24V17.14H19.7H20.03H20.16H20.2L24.1 15.7L30.11 5.19L23.75 5.67ZM4.21002 4.21L10.53 4.81L12.33 0.69L12.05 0H8.43002L4.22002 4.21H4.21002ZM21.9 17.4L20.6 18.2H14.3L13 17.4L12.4 18.2L12.42 18.23L17.45 26.8L22.48 18.23L22.5 18.2L21.9 17.4ZM4.79002 5.19L10.8 15.7L14.7 17.14H14.74H15.2H16.85V14.24L12.24 3.09L11.15 5.68L4.79002 5.2V5.19Z"
fill="var(--text-color)"
/>
</svg>
<span class="font-medium text-xl font-semibold">PRIME<span class="text-primary">APP</span></span>
</span>
</template>
<template #item="{ item, label, props }">
<a class="flex" v-bind="props.action">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<template #submenuheader="{ item }">
<span class="text-primary font-bold">{{ item.label }}</span>
</template>
<template #item="{ item, props }">
<a v-ripple class="flex align-items-center" v-bind="props.action">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
<Badge v-if="item.badge" class="ml-auto" :value="item.badge" />
<span v-if="item.shortcut" class="ml-auto border-1 surface-border border-round surface-100 text-sm p-1">{{ item.shortcut }}</span>
</a>
</template>
<template #end>
<button class="w-full p-link flex align-items-center p-2 pl-4 text-color hover:surface-200 border-noround">
<i class="pi pi-sign-out" />
<span class="ml-2">Log Out</span>
<button v-ripple class="relative overflow-hidden w-full p-link flex align-items-center p-2 pl-3 text-color hover:surface-200 border-noround">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<span class="inline-flex flex-column">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Admin</span>
</span>
</button>
</template>
</Menu>
<Toast />
</div>
</template>
@ -114,24 +176,49 @@ export default {
data() {
return {
items: [
{ separator: true },
{
separator: true
},
{
label: 'Documents',
items: [
{
label: 'New',
icon: 'pi pi-plus',
shortcut: '⌘+N'
},
{
label: 'Search',
icon: 'pi pi-search',
shortcut: '⌘+S'
}
]
},
{
label: 'Profile',
icon: 'pi pi-fw pi-user'
},
items: [
{
label: 'Settings',
icon: 'pi pi-fw pi-cog',
icon: 'pi pi-cog',
shortcut: '⌘+O'
},
{
label: 'Messages',
icon: 'pi pi-inbox',
badge: 2
},
{ separator: true }
{
label: 'Logout',
icon: 'pi pi-sign-out',
shortcut: '⌘+Q'
}
]
},
{
separator: true
}
]
};
},
methods: {
profileClick() {
this.toast.add({ severity: 'info', summary: 'Info', detail: 'Item Selected', life: 3000 });
}
}
};
<\/script>
@ -139,66 +226,96 @@ export default {
composition: `
<template>
<div class="card flex justify-content-center">
<Menu :model="items">
<Menu :model="items" class="w-full md:w-15rem">
<template #start>
<button @click="profileClick" class="w-full p-link flex align-items-center p-2 pl-3 text-color hover:surface-200 border-noround">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<div class="flex flex-column align">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Agent</span>
</div>
</button>
<span class="inline-flex align-items-center gap-1 px-2 py-2">
<svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-2rem">
<path
d="M25.87 18.05L23.16 17.45L25.27 20.46V29.78L32.49 23.76V13.53L29.18 14.73L25.87 18.04V18.05ZM25.27 35.49L29.18 31.58V27.67L25.27 30.98V35.49ZM20.16 17.14H20.03H20.17H20.16ZM30.1 5.19L34.89 4.81L33.08 12.33L24.1 15.67L30.08 5.2L30.1 5.19ZM5.72 14.74L2.41 13.54V23.77L9.63 29.79V20.47L11.74 17.46L9.03 18.06L5.72 14.75V14.74ZM9.63 30.98L5.72 27.67V31.58L9.63 35.49V30.98ZM4.8 5.2L10.78 15.67L1.81 12.33L0 4.81L4.79 5.19L4.8 5.2ZM24.37 21.05V34.59L22.56 37.29L20.46 39.4H14.44L12.34 37.29L10.53 34.59V21.05L12.42 18.23L17.45 26.8L22.48 18.23L24.37 21.05ZM22.85 0L22.57 0.69L17.45 13.08L12.33 0.69L12.05 0H22.85Z"
fill="var(--primary-color)"
/>
<path
d="M30.69 4.21L24.37 4.81L22.57 0.69L22.86 0H26.48L30.69 4.21ZM23.75 5.67L22.66 3.08L18.05 14.24V17.14H19.7H20.03H20.16H20.2L24.1 15.7L30.11 5.19L23.75 5.67ZM4.21002 4.21L10.53 4.81L12.33 0.69L12.05 0H8.43002L4.22002 4.21H4.21002ZM21.9 17.4L20.6 18.2H14.3L13 17.4L12.4 18.2L12.42 18.23L17.45 26.8L22.48 18.23L22.5 18.2L21.9 17.4ZM4.79002 5.19L10.8 15.7L14.7 17.14H14.74H15.2H16.85V14.24L12.24 3.09L11.15 5.68L4.79002 5.2V5.19Z"
fill="var(--text-color)"
/>
</svg>
<span class="font-medium text-xl font-semibold">PRIME<span class="text-primary">APP</span></span>
</span>
</template>
<template #item="{ item, label, props }">
<a class="flex" v-bind="props.action">
<span v-bind="props.icon" />
<span v-bind="props.label">{{ label }}</span>
<template #submenuheader="{ item }">
<span class="text-primary font-bold">{{ item.label }}</span>
</template>
<template #item="{ item, props }">
<a v-ripple class="flex align-items-center" v-bind="props.action">
<span :class="item.icon" />
<span class="ml-2">{{ item.label }}</span>
<Badge v-if="item.badge" class="ml-auto" :value="item.badge" />
<span v-if="item.shortcut" class="ml-auto border-1 surface-border border-round surface-100 text-sm p-1">{{ item.shortcut }}</span>
</a>
</template>
<template #end>
<button class="w-full p-link flex align-items-center p-2 pl-4 text-color hover:surface-200 border-noround">
<i class="pi pi-sign-out" />
<span class="ml-2">Log Out</span>
<button v-ripple class="relative overflow-hidden w-full p-link flex align-items-center p-2 pl-3 text-color hover:surface-200 border-noround">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<span class="inline-flex flex-column">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Admin</span>
</span>
</button>
</template>
</Menu>
<Toast />
</div>
</template>
<script setup>
import { ref } from "vue";
import { useToast } from "primevue/usetoast";
const items = ref([
{ separator: true },
{
separator: true
},
{
label: 'Documents',
items: [
{
label: 'New',
icon: 'pi pi-plus',
shortcut: '⌘+N'
},
{
label: 'Search',
icon: 'pi pi-search',
shortcut: '⌘+S'
}
]
},
{
label: 'Profile',
icon: 'pi pi-fw pi-user'
},
items: [
{
label: 'Settings',
icon: 'pi pi-fw pi-cog',
icon: 'pi pi-cog',
shortcut: '⌘+O'
},
{
label: 'Messages',
icon: 'pi pi-inbox',
badge: 2
},
{ separator: true }
]);
const toast = useToast();
const profileClick = () => {
toast.add({ severity: 'info', summary: 'Info', detail: 'Item Selected', life: 3000 });
{
label: 'Logout',
icon: 'pi pi-sign-out',
shortcut: '⌘+Q'
}
]
},
{
separator: true
}
]);
<\/script>
`
}
};
},
methods: {
profileClick() {
this.toast.add({ severity: 'info', summary: 'Info', detail: 'Item Selected', life: 3000 });
}
}
};
</script>

View File

@ -1,18 +1,11 @@
<template>
<DocComponent
title="Vue Menu Component"
header="Menu"
description="Menu is a navigation/command component that supports dynamic and static positioning."
:componentDocs="docs"
:apiDocs="['Menu', 'MenuItem']"
:ptTabComponent="ptComponent"
:themingDocs="themingDoc"
/>
<DocComponent title="Vue Menu Component" header="Menu" description="Menu displays a list of items in vertical orientation." :componentDocs="docs" :apiDocs="['Menu', 'MenuItem']" :ptTabComponent="ptComponent" :themingDocs="themingDoc" />
</template>
<script>
import AccessibilityDoc from '@/doc/menu/AccessibilityDoc.vue';
import BasicDoc from '@/doc/menu/BasicDoc.vue';
import CommandDoc from '@/doc/menu/CommandDoc.vue';
import GroupDoc from '@/doc/menu/GroupDoc.vue';
import ImportDoc from '@/doc/menu/ImportDoc.vue';
import PopupDoc from '@/doc/menu/PopupDoc.vue';
@ -50,6 +43,11 @@ export default {
label: 'Template',
component: TemplateDoc
},
{
id: 'command',
label: 'Command',
component: CommandDoc
},
{
id: 'router',
label: 'Router',