mirror of
https://github.com/vatesfr/xen-orchestra.git
synced 2026-11-09 17:06:13 -06:00
Compare commits
2 Commits
326c152fac
...
web-core/u
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d239d4b5af | ||
|
|
67d03991b4 |
19
@xen-orchestra/web-core/lib/components/menu/VtsMenuItem.vue
Normal file
19
@xen-orchestra/web-core/lib/components/menu/VtsMenuItem.vue
Normal file
@@ -0,0 +1,19 @@
|
||||
<template>
|
||||
<li>
|
||||
<VtsMenuTrigger v-bind="{ ...props, ...attrs }">
|
||||
<slot />
|
||||
</VtsMenuTrigger>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import VtsMenuTrigger, { type MenuTriggerProps } from '@core/components/menu/VtsMenuTrigger.vue'
|
||||
import { useAttrs } from 'vue'
|
||||
|
||||
defineOptions({
|
||||
inheritAttrs: false,
|
||||
})
|
||||
|
||||
const props = defineProps<MenuTriggerProps>()
|
||||
const attrs = useAttrs()
|
||||
</script>
|
||||
42
@xen-orchestra/web-core/lib/components/menu/VtsMenuList.vue
Normal file
42
@xen-orchestra/web-core/lib/components/menu/VtsMenuList.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<ul :class="{ horizontal, border }" class="menu-list">
|
||||
<slot />
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { IK_MENU_HORIZONTAL } from '@core/utils/injection-keys.util'
|
||||
import { computed, provide } from 'vue'
|
||||
|
||||
const { horizontal, border } = defineProps<{
|
||||
horizontal?: boolean
|
||||
border?: boolean
|
||||
}>()
|
||||
|
||||
provide(
|
||||
IK_MENU_HORIZONTAL,
|
||||
computed(() => horizontal ?? false)
|
||||
)
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.menu-list {
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0.4rem;
|
||||
cursor: default;
|
||||
color: var(--color-neutral-txt-primary);
|
||||
border-radius: 0.4rem;
|
||||
background-color: var(--color-neutral-background-primary);
|
||||
gap: 0.2rem;
|
||||
|
||||
&.horizontal {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
&.border {
|
||||
border: 0.1rem solid var(--color-neutral-border);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,83 @@
|
||||
<!-- v1.0 -->
|
||||
<template>
|
||||
<component
|
||||
:is="as"
|
||||
v-tooltip="tooltip ?? false"
|
||||
:class="{ selected, disabled }"
|
||||
class="vts-menu-trigger typo-body-regular"
|
||||
>
|
||||
<VtsIcon :busy :icon accent="current" />
|
||||
<slot />
|
||||
<VtsIcon v-if="submenu" :fixed-width="false" :icon="submenuIcon" accent="current" class="submenu-icon" />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import VtsIcon from '@core/components/icon/VtsIcon.vue'
|
||||
import { type TooltipDirectiveContent, vTooltip } from '@core/directives/tooltip.directive'
|
||||
import { IK_MENU_HORIZONTAL } from '@core/utils/injection-keys.util'
|
||||
import type { IconDefinition } from '@fortawesome/fontawesome-common-types'
|
||||
import { faAngleDown, faAngleRight } from '@fortawesome/free-solid-svg-icons'
|
||||
import { type Component, computed, inject } from 'vue'
|
||||
|
||||
export type MenuTriggerProps = {
|
||||
as: string | Component
|
||||
tooltip?: TooltipDirectiveContent
|
||||
selected?: boolean
|
||||
busy?: boolean
|
||||
disabled?: boolean
|
||||
icon?: IconDefinition
|
||||
submenu?: boolean
|
||||
}
|
||||
|
||||
defineProps<MenuTriggerProps>()
|
||||
|
||||
defineSlots<{
|
||||
default(): any
|
||||
}>()
|
||||
|
||||
const isParentHorizontal = inject(IK_MENU_HORIZONTAL, undefined)
|
||||
|
||||
const submenuIcon = computed(() => (isParentHorizontal?.value ? faAngleDown : faAngleRight))
|
||||
</script>
|
||||
|
||||
<style lang="postcss" scoped>
|
||||
.vts-menu-trigger {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
align-items: center;
|
||||
height: 4.4rem;
|
||||
padding-right: 1.5rem;
|
||||
padding-left: 1.5rem;
|
||||
white-space: nowrap;
|
||||
border-radius: 0.8rem;
|
||||
gap: 1rem;
|
||||
color: var(--color-neutral-txt-primary);
|
||||
background-color: var(--color-neutral-background-primary);
|
||||
border: none;
|
||||
text-decoration: none;
|
||||
|
||||
&.disabled {
|
||||
color: var(--color-neutral-txt-secondary);
|
||||
}
|
||||
|
||||
&:not(.disabled) {
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: var(--color-neutral-txt-primary);
|
||||
background-color: var(--color-info-background-selected);
|
||||
}
|
||||
|
||||
&:active,
|
||||
&.selected {
|
||||
color: var(--color-neutral-txt-primary);
|
||||
background-color: var(--color-info-background-hover);
|
||||
}
|
||||
}
|
||||
|
||||
.submenu-icon {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -6,18 +6,18 @@ A menu system for Vue applications supporting props binding for actions, links,
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<MenuList>
|
||||
<li><MenuTrigger v-bind="menu.save">Save</MenuTrigger></li>
|
||||
<li><MenuTrigger v-bind="menu.doc">Documentation</MenuTrigger></li>
|
||||
<li><MenuTrigger v-bind="menu.profile">Profile</MenuTrigger></li>
|
||||
<VtsMenuList>
|
||||
<VtsMenuItem v-bind="menu.save">Save</VtsMenuItem>
|
||||
<VtsMenuItem v-bind="menu.doc">Documentation</VtsMenuItem>
|
||||
<VtsMenuItem v-bind="menu.profile">Profile</VtsMenuItem>
|
||||
<li>
|
||||
<MenuTrigger v-bind="menu.more.$trigger">More...</MenuTrigger>
|
||||
<MenuList v-bind="menu.more.$target">
|
||||
<MenuTrigger v-bind="menu.more.settings">Settings</MenuTrigger>
|
||||
<MenuTrigger v-bind="menu.more.logout">Logout</MenuTrigger>
|
||||
</MenuList>
|
||||
<VtsMenuTrigger v-bind="menu.more.$trigger">More...</VtsMenuTrigger>
|
||||
<VtsMenuList v-bind="menu.more.$target">
|
||||
<VtsMenuItem v-bind="menu.more.settings">Settings</VtsMenuItem>
|
||||
<VtsMenuItem v-bind="menu.more.logout">Logout</VtsMenuItem>
|
||||
</VtsMenuList>
|
||||
</li>
|
||||
</MenuList>
|
||||
</VtsMenuList>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
@@ -166,15 +166,15 @@ type Props = {
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<MenuTrigger v-bind="menu.save">Save</MenuTrigger>
|
||||
<MenuTrigger v-bind="menu.docs">Documentation</MenuTrigger>
|
||||
<MenuTrigger v-bind="menu.profile">Profile</MenuTrigger>
|
||||
<VtsMenuTrigger v-bind="menu.save">Save</VtsMenuTrigger>
|
||||
<VtsMenuTrigger v-bind="menu.docs">Documentation</VtsMenuTrigger>
|
||||
<VtsMenuTrigger v-bind="menu.profile">Profile</VtsMenuTrigger>
|
||||
|
||||
<!-- Toggle/Dropdown menu -->
|
||||
<MenuTrigger v-bind="menu.more.$trigger">More</MenuTrigger>
|
||||
<VtsMenuTrigger v-bind="menu.more.$trigger">More</VtsMenuTrigger>
|
||||
<div v-bind="menu.more.$target">
|
||||
<MenuTrigger v-bind="menu.more.settings">Settings</MenuTrigger>
|
||||
<MenuTrigger v-bind="menu.more.logout">Logout</MenuTrigger>
|
||||
<VtsMenuTrigger v-bind="menu.more.settings">Settings</VtsMenuTrigger>
|
||||
<VtsMenuTrigger v-bind="menu.more.logout">Logout</VtsMenuTrigger>
|
||||
</div>
|
||||
</template>
|
||||
```
|
||||
|
||||
@@ -69,7 +69,7 @@ export function parseConfigHolder<TConfigHolder extends ConfigHolder>(
|
||||
$target: target.props,
|
||||
$isOpen: trigger.isOpen,
|
||||
[MENU_SYMBOL]: trigger.subMenu,
|
||||
...parseStructure(trigger.subMenu, configHolder.config.items),
|
||||
...parseStructure(trigger.subMenu, configHolder.config.items ?? {}),
|
||||
} as ParseConfigHolder<TConfigHolder>
|
||||
}
|
||||
|
||||
|
||||
@@ -37,8 +37,6 @@ export class MenuToggleTarget {
|
||||
|
||||
get props(): MenuToggleTargetProps {
|
||||
return reactive({
|
||||
as: 'button',
|
||||
type: 'button',
|
||||
ref: (element: HTMLElement | null | undefined) => {
|
||||
const newElement = unrefElement(element)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user