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() { data() {
return { return {
items: [ items: [
{ label: 'New', icon: 'pi pi-fw pi-plus' }, { label: 'New', icon: 'pi pi-plus' },
{ label: 'Delete', icon: 'pi pi-fw pi-trash' } { label: 'Search', icon: 'pi pi-search' }
], ],
code: { code: {
basic: ` basic: `
@ -32,8 +32,8 @@ export default {
data() { data() {
return { return {
items: [ items: [
{ label: 'New', icon: 'pi pi-fw pi-plus' }, { label: 'New', icon: 'pi pi-plus' },
{ label: 'Delete', icon: 'pi pi-fw pi-trash' } { label: 'Search', icon: 'pi pi-search' }
] ]
}; };
} }
@ -51,8 +51,8 @@ export default {
import { ref } from "vue"; import { ref } from "vue";
const items = ref([ const items = ref([
{ label: 'New', icon: 'pi pi-fw pi-plus' }, { label: 'New', icon: 'pi pi-plus' },
{ label: 'Delete', icon: 'pi pi-fw pi-trash' } { label: 'Search', icon: 'pi pi-search' }
]); ]);
<\/script> <\/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> <template>
<DocSectionText v-bind="$attrs"> <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> </DocSectionText>
<div class="card flex justify-content-center"> <div class="card flex justify-content-center">
<Menu :model="items" /> <Menu :model="items" />
@ -14,21 +14,28 @@ export default {
return { return {
items: [ items: [
{ {
label: 'Options', label: 'Documents',
items: [ items: [
{ {
label: 'Update', label: 'New',
icon: 'pi pi-refresh', icon: 'pi pi-plus'
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
}, },
{ {
label: 'Delete', label: 'Search',
icon: 'pi pi-times', icon: 'pi pi-search'
command: () => { }
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 }); ]
} },
{
label: 'Profile',
items: [
{
label: 'Settings',
icon: 'pi pi-cog'
},
{
label: 'Logout',
icon: 'pi pi-sign-out'
} }
] ]
} }
@ -36,13 +43,11 @@ export default {
code: { code: {
basic: ` basic: `
<Menu :model="items" /> <Menu :model="items" />
<Toast />
`, `,
options: ` options: `
<template> <template>
<div class="card flex justify-content-center"> <div class="card flex justify-content-center">
<Menu :model="items" /> <Menu :model="items" />
<Toast />
</div> </div>
</template> </template>
@ -52,21 +57,28 @@ export default {
return { return {
items: [ items: [
{ {
label: 'Options', label: 'Documents',
items: [ items: [
{ {
label: 'Update', label: 'New',
icon: 'pi pi-refresh', icon: 'pi pi-plus'
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
}, },
{ {
label: 'Delete', label: 'Search',
icon: 'pi pi-times', icon: 'pi pi-search'
command: () => { }
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 }); ]
} },
{
label: 'Profile',
items: [
{
label: 'Settings',
icon: 'pi pi-cog'
},
{
label: 'Logout',
icon: 'pi pi-sign-out'
} }
] ]
} }
@ -80,32 +92,36 @@ export default {
<template> <template>
<div class="card flex justify-content-center"> <div class="card flex justify-content-center">
<Menu :model="items" /> <Menu :model="items" />
<Toast />
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue";
import { useToast } from "primevue/usetoast";
const toast = useToast();
const items = ref([ const items = ref([
{ {
label: 'Options', label: 'Documents',
items: [ items: [
{ {
label: 'Update', label: 'New',
icon: 'pi pi-refresh', icon: 'pi pi-plus'
command: () => {
toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
}, },
{ {
label: 'Delete', label: 'Search',
icon: 'pi pi-times', icon: 'pi pi-search'
command: () => { }
toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 }); ]
} },
{
label: 'Profile',
items: [
{
label: 'Settings',
icon: 'pi pi-cog'
},
{
label: 'Logout',
icon: 'pi pi-sign-out'
} }
] ]
} }

View File

@ -1,9 +1,9 @@
<template> <template>
<DocSectionText v-bind="$attrs"> <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> </DocSectionText>
<div class="card flex justify-content-center"> <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" /> <Menu ref="menu" id="overlay_menu" :model="items" :popup="true" />
</div> </div>
<DocSectionCode :code="code" /> <DocSectionCode :code="code" />
@ -18,34 +18,26 @@ export default {
label: 'Options', label: 'Options',
items: [ items: [
{ {
label: 'Update', label: 'Refresh',
icon: 'pi pi-refresh', icon: 'pi pi-refresh'
command: () => {
this.$toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
}, },
{ {
label: 'Delete', label: 'Export',
icon: 'pi pi-times', icon: 'pi pi-upload'
command: () => {
this.$toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
}
} }
] ]
} }
], ],
code: { code: {
basic: ` 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" /> <Menu ref="menu" id="overlay_menu" :model="items" :popup="true" />
<Toast />
`, `,
options: ` options: `
<template> <template>
<div class="card flex justify-content-center"> <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" /> <Menu ref="menu" id="overlay_menu" :model="items" :popup="true" />
<Toast />
</div> </div>
</template> </template>
@ -55,23 +47,12 @@ export default {
return { return {
items: [ items: [
{ {
label: 'Options', label: 'Refresh',
items: [ icon: 'pi pi-refresh'
{ },
label: 'Update', {
icon: 'pi pi-refresh', label: 'Export',
command: () => { icon: 'pi pi-upload'
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 });
}
}
]
} }
] ]
}; };
@ -79,46 +60,34 @@ export default {
methods: { methods: {
toggle(event) { toggle(event) {
this.$refs.menu.toggle(event); this.$refs.menu.toggle(event);
},
save() {
this.$toast.add({ severity: 'success', summary: 'Success', detail: 'Data Saved', life: 3000 });
} }
}, }
}; };
<\/script> <\/script>
`, `,
composition: ` composition: `
<template> <template>
<div class="card flex justify-content-center"> <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" /> <Menu ref="menu" id="overlay_menu" :model="items" :popup="true" />
<Toast />
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue";
import { useToast } from "primevue/usetoast";
const toast = useToast();
const menu = ref(); const menu = ref();
const items = ref([ const items = ref([
{ {
label: 'Options', label: 'Options',
items: [ items: [
{ {
label: 'Update', label: 'Refresh',
icon: 'pi pi-refresh', icon: 'pi pi-refresh'
command: () => {
toast.add({ severity: 'success', summary: 'Updated', detail: 'Data Updated', life: 3000 });
}
}, },
{ {
label: 'Delete', label: 'Export',
icon: 'pi pi-times', icon: 'pi pi-upload'
command: () => {
toast.add({ severity: 'warn', summary: 'Delete', detail: 'Data Deleted', life: 3000 });
}
} }
] ]
} }
@ -127,10 +96,6 @@ const items = ref([
const toggle = (event) => { const toggle = (event) => {
menu.value.toggle(event); menu.value.toggle(event);
}; };
const save = () => {
toast.add({severity: 'success', summary: 'Success', detail: 'Data Saved', life: 3000});
};
<\/script> <\/script>
` `
} }

View File

@ -1,27 +1,24 @@
<template> <template>
<DocSectionText v-bind="$attrs"> <DocSectionText v-bind="$attrs">
<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>
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>
</DocSectionText> </DocSectionText>
<div class="card flex justify-content-center"> <div class="card flex justify-content-center">
<Menu :model="items"> <Menu :model="items">
<template #item="{ label, item, props }"> <template #item="{ item, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom> <router-link v-if="item.route" v-slot="{ href, navigate }" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="routerProps.navigate"> <a :href="href" v-bind="props.action" @click="navigate">
<span v-bind="props.icon" /> <span :class="item.icon" />
<span v-bind="props.label">{{ label }}</span> <span class="ml-2">{{ item.label }}</span>
</a> </a>
</router-link> </router-link>
<a v-else :href="item.url" :target="item.target" v-bind="props.action"> <a v-else v-ripple :href="item.url" :target="item.target" v-bind="props.action">
<span v-bind="props.icon" /> <span :class="item.icon" />
<span v-bind="props.label">{{ label }}</span> <span class="ml-2">{{ item.label }}</span>
</a> </a>
</template> </template>
</Menu> </Menu>
</div> </div>
<DocSectionCode :code="code" /> <DocSectionCode :code="code" hideStackBlitz hideCodeSandbox />
</template> </template>
<script> <script>
@ -29,38 +26,25 @@ export default {
data() { data() {
return { return {
items: [ 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', label: 'Navigate',
items: [ items: [
{ {
label: 'Vue Website', label: 'Router Link',
icon: 'pi pi-external-link', icon: 'pi pi-palette',
url: 'https://vuejs.org/', route: '/unstyled'
target: '_blank'
}, },
{ {
label: 'Upload', label: 'Programmatic',
icon: 'pi pi-upload', icon: 'pi pi-link',
route: '/fileupload' command: () => {
this.$router.push('/installation');
}
},
{
label: 'External',
icon: 'pi pi-external-link',
url: 'https://vuejs.org/'
} }
] ]
} }
@ -68,16 +52,16 @@ export default {
code: { code: {
basic: ` basic: `
<Menu :model="items"> <Menu :model="items">
<template #item="{ label, item, props }"> <template #item="{ item, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom> <router-link v-if="item.route" v-slot="{ href, navigate }" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="routerProps.navigate"> <a :href="href" v-bind="props.action" @click="navigate">
<span v-bind="props.icon" /> <span :class="item.icon" />
<span v-bind="props.label">{{ label }}</span> <span class="ml-2">{{ item.label }}</span>
</a> </a>
</router-link> </router-link>
<a v-else :href="item.url" v-bind="props.action"> <a v-else v-ripple :href="item.url" :target="item.target" v-bind="props.action">
<span v-bind="props.icon" /> <span :class="item.icon" />
<span v-bind="props.label">{{ label }}</span> <span class="ml-2">{{ item.label }}</span>
</a> </a>
</template> </template>
</Menu> </Menu>
@ -86,20 +70,19 @@ export default {
<template> <template>
<div class="card flex justify-content-center"> <div class="card flex justify-content-center">
<Menu :model="items"> <Menu :model="items">
<template #item="{ label, item, props }"> <template #item="{ item, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom> <router-link v-if="item.route" v-slot="{ href, navigate }" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action" @click="routerProps.navigate"> <a :href="href" v-bind="props.action" @click="navigate">
<span v-bind="props.icon" /> <span :class="item.icon" />
<span v-bind="props.label">{{ label }}</span> <span class="ml-2">{{ item.label }}</span>
</a> </a>
</router-link> </router-link>
<a v-else :href="item.url" v-bind="props.action"> <a v-else v-ripple :href="item.url" :target="item.target" v-bind="props.action">
<span v-bind="props.icon" /> <span :class="item.icon" />
<span v-bind="props.label">{{ label }}</span> <span class="ml-2">{{ item.label }}</span>
</a> </a>
</template> </template>
</Menu> </Menu>
<Toast />
</div> </div>
</template> </template>
@ -109,40 +92,21 @@ export default {
return { return {
items: [ items: [
{ {
label: 'Options', label: 'Router Link',
items: [ icon: 'pi pi-palette',
{ route: '/unstyled'
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', label: 'Programmatic',
items: [ icon: 'pi pi-link',
{ command: () => {
label: 'Vue Website', this.$router.push('/installation');
icon: 'pi pi-external-link', }
url: 'https://vuejs.org/', },
target: '_blank', {
}, label: 'External',
{ icon: 'pi pi-external-link',
label: 'Upload', url: 'https://vuejs.org/'
icon: 'pi pi-upload',
route: '/fileupload'
}
]
} }
] ]
}; };
@ -154,62 +118,45 @@ export default {
<template> <template>
<div class="card flex justify-content-center"> <div class="card flex justify-content-center">
<Menu :model="items"> <Menu :model="items">
<template #item="{ label, item, props }"> <template #item="{ item, props }">
<router-link v-if="item.route" v-slot="routerProps" :to="item.route" custom> <router-link v-if="item.route" v-slot="{ href, navigate }" :to="item.route" custom>
<a :href="routerProps.href" v-bind="props.action"> <a :href="href" v-bind="props.action" @click="navigate">
<span v-bind="props.icon" /> <span :class="item.icon" />
<span v-bind="props.label">{{ label }}</span> <span class="ml-2">{{ item.label }}</span>
</a> </a>
</router-link> </router-link>
<a v-else :href="item.url" v-bind="props.action"> <a v-else v-ripple :href="item.url" :target="item.target" v-bind="props.action">
<span v-bind="props.icon" /> <span :class="item.icon" />
<span v-bind="props.label">{{ label }}</span> <span class="ml-2">{{ item.label }}</span>
</a> </a>
</template> </template>
</Menu> </Menu>
<Toast />
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue";
import { useRouter } from "vue";
const router = useRouter();
const items = ref([ const items = ref([
{ {
label: 'Options', label: 'Router Link',
items: [ icon: 'pi pi-palette',
{ route: '/unstyled'
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', label: 'Programmatic',
items: [ icon: 'pi pi-link',
{ command: () => {
label: 'Vue Website', this.$router.push('/installation');
icon: 'pi pi-external-link', }
url: 'https://vuejs.org/', },
target: '_blank', {
}, label: 'External',
{ icon: 'pi pi-external-link',
label: 'Upload', url: 'https://vuejs.org/'
icon: 'pi pi-upload',
route: '/fileupload'
}
]
} }
]); ]);
<\/script> <\/script>

View File

@ -1,32 +1,45 @@
<template> <template>
<DocSectionText v-bind="$attrs"> <DocSectionText v-bind="$attrs">
<p> <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 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
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. 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> </p>
</DocSectionText> </DocSectionText>
<div class="card flex justify-content-center"> <div class="card flex justify-content-center">
<Menu :model="items"> <Menu :model="items" class="w-full md:w-15rem">
<template #start> <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"> <span class="inline-flex align-items-center gap-1 px-2 py-2">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" /> <svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-2rem">
<div class="flex flex-column align"> <path
<span class="font-bold">Amy Elsner</span> 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"
<span class="text-sm">Agent</span> fill="var(--primary-color)"
</div> />
</button> <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>
<template #item="{ item, label, props }"> <template #submenuheader="{ item }">
<a class="flex" v-bind="props.action"> <span class="text-primary font-bold">{{ item.label }}</span>
<span v-bind="props.icon" /> </template>
<span v-bind="props.label">{{ label }}</span> <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" /> <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> </a>
</template> </template>
<template #end> <template #end>
<button class="w-full p-link flex align-items-center p-2 pl-4 text-color hover:surface-200 border-noround"> <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">
<i class="pi pi-sign-out" /> <Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<span class="ml-2">Log Out</span> <span class="inline-flex flex-column">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Admin</span>
</span>
</button> </button>
</template> </template>
</Menu> </Menu>
@ -39,41 +52,78 @@ export default {
data() { data() {
return { return {
items: [ 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', label: 'Profile',
icon: 'pi pi-fw pi-user' items: [
{
label: 'Settings',
icon: 'pi pi-cog',
shortcut: '⌘+O'
},
{
label: 'Messages',
icon: 'pi pi-inbox',
badge: 2
},
{
label: 'Logout',
icon: 'pi pi-sign-out',
shortcut: '⌘+Q'
}
]
}, },
{ {
label: 'Settings', separator: true
icon: 'pi pi-fw pi-cog', }
badge: 2
},
{ separator: true }
], ],
code: { code: {
basic: ` basic: `
<Menu :model="items"> <Menu :model="items" class="w-full md:w-15rem">
<template #start> <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"> <span class="inline-flex align-items-center gap-1 px-2 py-2">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" /> <svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-2rem">
<div class="flex flex-column align"> <path d="..." fill="var(--primary-color)" />
<span class="font-bold">Amy Elsner</span> <path d="..." fill="var(--text-color)" />
<span class="text-sm">Agent</span> </svg>
</div> <span class="font-medium text-xl font-semibold">PRIME<span class="text-primary">APP</span></span>
</button> </span>
</template> </template>
<template #item="{ item, label, props }"> <template #submenuheader="{ item }">
<a class="flex" v-bind="props.action"> <span class="text-primary font-bold">{{ item.label }}</span>
<span v-bind="props.icon" /> </template>
<span v-bind="props.label">{{ label }}</span> <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" /> <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> </a>
</template> </template>
<template #end> <template #end>
<button class="w-full p-link flex align-items-center p-2 pl-4 text-color hover:surface-200 border-noround"> <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">
<i class="pi pi-sign-out" /> <Avatar image="/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<span class="ml-2">Log Out</span> <span class="inline-flex flex-column">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Admin</span>
</span>
</button> </button>
</template> </template>
</Menu> </Menu>
@ -81,31 +131,43 @@ export default {
options: ` options: `
<template> <template>
<div class="card flex justify-content-center"> <div class="card flex justify-content-center">
<Menu :model="items"> <Menu :model="items" class="w-full md:w-15rem">
<template #start> <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"> <span class="inline-flex align-items-center gap-1 px-2 py-2">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" /> <svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-2rem">
<div class="flex flex-column align"> <path
<span class="font-bold">Amy Elsner</span> 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"
<span class="text-sm">Agent</span> fill="var(--primary-color)"
</div> />
</button> <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>
<template #item="{ item, label, props }"> <template #submenuheader="{ item }">
<a class="flex" v-bind="props.action"> <span class="text-primary font-bold">{{ item.label }}</span>
<span v-bind="props.icon" /> </template>
<span v-bind="props.label">{{ label }}</span> <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" /> <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> </a>
</template> </template>
<template #end> <template #end>
<button class="w-full p-link flex align-items-center p-2 pl-4 text-color hover:surface-200 border-noround"> <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">
<i class="pi pi-sign-out" /> <Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<span class="ml-2">Log Out</span> <span class="inline-flex flex-column">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Admin</span>
</span>
</button> </button>
</template> </template>
</Menu> </Menu>
<Toast />
</div> </div>
</template> </template>
@ -114,24 +176,49 @@ export default {
data() { data() {
return { return {
items: [ 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', label: 'Profile',
icon: 'pi pi-fw pi-user' items: [
{
label: 'Settings',
icon: 'pi pi-cog',
shortcut: '⌘+O'
},
{
label: 'Messages',
icon: 'pi pi-inbox',
badge: 2
},
{
label: 'Logout',
icon: 'pi pi-sign-out',
shortcut: '⌘+Q'
}
]
}, },
{ {
label: 'Settings', separator: true
icon: 'pi pi-fw pi-cog', }
badge: 2
},
{ separator: true }
] ]
}; };
},
methods: {
profileClick() {
this.toast.add({ severity: 'info', summary: 'Info', detail: 'Item Selected', life: 3000 });
}
} }
}; };
<\/script> <\/script>
@ -139,66 +226,96 @@ export default {
composition: ` composition: `
<template> <template>
<div class="card flex justify-content-center"> <div class="card flex justify-content-center">
<Menu :model="items"> <Menu :model="items" class="w-full md:w-15rem">
<template #start> <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"> <span class="inline-flex align-items-center gap-1 px-2 py-2">
<Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" /> <svg width="35" height="40" viewBox="0 0 35 40" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-2rem">
<div class="flex flex-column align"> <path
<span class="font-bold">Amy Elsner</span> 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"
<span class="text-sm">Agent</span> fill="var(--primary-color)"
</div> />
</button> <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>
<template #item="{ item, label, props }"> <template #submenuheader="{ item }">
<a class="flex" v-bind="props.action"> <span class="text-primary font-bold">{{ item.label }}</span>
<span v-bind="props.icon" /> </template>
<span v-bind="props.label">{{ label }}</span> <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" /> <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> </a>
</template> </template>
<template #end> <template #end>
<button class="w-full p-link flex align-items-center p-2 pl-4 text-color hover:surface-200 border-noround"> <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">
<i class="pi pi-sign-out" /> <Avatar image="https://primefaces.org/cdn/primevue/images/avatar/amyelsner.png" class="mr-2" shape="circle" />
<span class="ml-2">Log Out</span> <span class="inline-flex flex-column">
<span class="font-bold">Amy Elsner</span>
<span class="text-sm">Admin</span>
</span>
</button> </button>
</template> </template>
</Menu> </Menu>
<Toast />
</div> </div>
</template> </template>
<script setup> <script setup>
import { ref } from "vue"; import { ref } from "vue";
import { useToast } from "primevue/usetoast";
const items = ref([ 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', label: 'Profile',
icon: 'pi pi-fw pi-user' items: [
{
label: 'Settings',
icon: 'pi pi-cog',
shortcut: '⌘+O'
},
{
label: 'Messages',
icon: 'pi pi-inbox',
badge: 2
},
{
label: 'Logout',
icon: 'pi pi-sign-out',
shortcut: '⌘+Q'
}
]
}, },
{ {
label: 'Settings', separator: true
icon: 'pi pi-fw pi-cog', }
badge: 2
},
{ separator: true }
]); ]);
const toast = useToast();
const profileClick = () => {
toast.add({ severity: 'info', summary: 'Info', detail: 'Item Selected', life: 3000 });
}
<\/script> <\/script>
` `
} }
}; };
},
methods: {
profileClick() {
this.toast.add({ severity: 'info', summary: 'Info', detail: 'Item Selected', life: 3000 });
}
} }
}; };
</script> </script>

View File

@ -1,18 +1,11 @@
<template> <template>
<DocComponent <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" />
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"
/>
</template> </template>
<script> <script>
import AccessibilityDoc from '@/doc/menu/AccessibilityDoc.vue'; import AccessibilityDoc from '@/doc/menu/AccessibilityDoc.vue';
import BasicDoc from '@/doc/menu/BasicDoc.vue'; import BasicDoc from '@/doc/menu/BasicDoc.vue';
import CommandDoc from '@/doc/menu/CommandDoc.vue';
import GroupDoc from '@/doc/menu/GroupDoc.vue'; import GroupDoc from '@/doc/menu/GroupDoc.vue';
import ImportDoc from '@/doc/menu/ImportDoc.vue'; import ImportDoc from '@/doc/menu/ImportDoc.vue';
import PopupDoc from '@/doc/menu/PopupDoc.vue'; import PopupDoc from '@/doc/menu/PopupDoc.vue';
@ -50,6 +43,11 @@ export default {
label: 'Template', label: 'Template',
component: TemplateDoc component: TemplateDoc
}, },
{
id: 'command',
label: 'Command',
component: CommandDoc
},
{ {
id: 'router', id: 'router',
label: 'Router', label: 'Router',