feat(DropdownMenu): new component (#37)

This commit is contained in:
Benjamin Canac
2024-03-29 13:42:02 +01:00
committed by GitHub
parent 2fbf47e1fc
commit 44033508a7
25 changed files with 735 additions and 215 deletions

View File

@@ -18,9 +18,10 @@ export interface NavigationMenuLink extends LinkProps {
icon?: IconProps['name']
avatar?: AvatarProps
badge?: string | number | BadgeProps
select? (e: MouseEvent): void
}
export interface NavigationMenuProps<T extends NavigationMenuLink> extends Omit<NavigationMenuRootProps, 'asChild' | 'dir'> {
export interface NavigationMenuProps<T> extends Omit<NavigationMenuRootProps, 'asChild' | 'dir'> {
links?: T[] | T[][]
class?: any
ui?: Partial<typeof navigationMenu.slots>
@@ -30,7 +31,7 @@ export interface NavigationMenuEmits extends NavigationMenuRootEmits {}
type SlotProps<T> = (props: { link: T, active: boolean }) => any
export interface NavigationMenuSlots<T extends NavigationMenuLink> {
export interface NavigationMenuSlots<T> {
leading: SlotProps<T>
default: SlotProps<T>
trailing: SlotProps<T>
@@ -59,30 +60,32 @@ const lists = computed(() => props.links?.length ? (Array.isArray(props.links[0]
<NavigationMenuRoot v-bind="rootProps" :class="ui.root({ class: props.class })">
<NavigationMenuList v-for="(list, index) in lists" :key="`list-${index}`" :class="ui.list()">
<NavigationMenuItem v-for="(link, linkIndex) in list" :key="`list-${index}-${linkIndex}`" :class="ui.item()">
<ULink v-slot="{ active, ...slotProps }" v-bind="omit(link, ['label', 'icon', 'avatar', 'badge'])" custom>
<NavigationMenuLink as-child :active="active">
<ULinkBase v-bind="slotProps" :class="ui.base({ active })">
<ULink v-slot="{ active, ...slotProps }" v-bind="omit(link, ['label', 'icon', 'avatar', 'badge', 'select'])" custom>
<NavigationMenuLink as-child :active="active" @select="link.select">
<ULinkBase v-bind="slotProps" :class="ui.link({ active })">
<slot name="leading" :link="link" :active="active">
<UAvatar v-if="link.avatar" size="2xs" v-bind="link.avatar" :class="ui.avatar({ active })" />
<UIcon v-else-if="link.icon" :name="link.icon" :class="ui.icon({ active })" />
<UAvatar v-if="link.avatar" size="2xs" v-bind="link.avatar" :class="ui.linkLeadingAvatar({ active })" />
<UIcon v-else-if="link.icon" :name="link.icon" :class="ui.linkLeadingIcon({ active })" />
</slot>
<span v-if="link.label || $slots.default" :class="ui.label()">
<span v-if="link.label || $slots.default" :class="ui.linkLabel()">
<slot :link="link" :active="active">
{{ link.label }}
</slot>
</span>
<slot name="trailing" :link="link" :active="active">
<UBadge
v-if="link.badge"
color="gray"
variant="solid"
size="xs"
v-bind="(typeof link.badge === 'string' || typeof link.badge === 'number') ? { label: link.badge } : link.badge"
:class="ui.badge()"
/>
</slot>
<span v-if="$slots.trailing || link.badge" :class="ui.linkTrailing()">
<slot name="trailing" :link="link" :active="active">
<UBadge
v-if="link.badge"
color="gray"
variant="solid"
size="xs"
v-bind="(typeof link.badge === 'string' || typeof link.badge === 'number') ? { label: link.badge } : link.badge"
:class="ui.linkTrailingBadge()"
/>
</slot>
</span>
</ULinkBase>
</NavigationMenuLink>
</ULink>