mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-20 15:01:46 +01:00
feat(ContextMenu/DropdownMenu/NavigationMenu): add external-icon prop
Resolves #2996
This commit is contained in:
@@ -51,6 +51,12 @@ export interface ContextMenuProps<T> extends Omit<ContextMenuRootProps, 'dir'> {
|
||||
* @defaultValue appConfig.ui.icons.loading
|
||||
*/
|
||||
loadingIcon?: string
|
||||
/**
|
||||
* The icon displayed when the item is an external link.
|
||||
* Set to `false` to hide the external icon.
|
||||
* @defaultValue appConfig.ui.icons.external
|
||||
*/
|
||||
externalIcon?: boolean | string
|
||||
/** The content of the menu. */
|
||||
content?: Omit<ContextMenuContentProps, 'as' | 'asChild' | 'forceMount'>
|
||||
/**
|
||||
@@ -152,6 +158,7 @@ import UContextMenuContent from './ContextMenuContent.vue'
|
||||
const props = withDefaults(defineProps<ContextMenuProps<T>>(), {
|
||||
portal: true,
|
||||
modal: true,
|
||||
externalIcon: true,
|
||||
labelKey: 'label'
|
||||
})
|
||||
const emits = defineEmits<ContextMenuEmits>()
|
||||
@@ -182,6 +189,7 @@ const ui = computed(() => contextMenu({
|
||||
:label-key="labelKey"
|
||||
:checked-icon="checkedIcon"
|
||||
:loading-icon="loadingIcon"
|
||||
:external-icon="externalIcon"
|
||||
>
|
||||
<template v-for="(_, name) in proxySlots" #[name]="slotData: any">
|
||||
<slot :name="name" v-bind="slotData" />
|
||||
|
||||
@@ -13,6 +13,7 @@ interface ContextMenuContentProps<T> extends Omit<RekaContextMenuContentProps, '
|
||||
labelKey: string
|
||||
checkedIcon?: string
|
||||
loadingIcon?: string
|
||||
externalIcon?: boolean | string
|
||||
class?: any
|
||||
ui: typeof _contextMenu
|
||||
uiOverride?: any
|
||||
@@ -42,7 +43,7 @@ const emits = defineEmits<ContextMenuContentEmits>()
|
||||
const slots = defineSlots<ContextMenuSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'class', 'ui', 'uiOverride'), emits)
|
||||
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'externalIcon', 'class', 'ui', 'uiOverride'), emits)
|
||||
const proxySlots = omit(slots, ['default']) as Record<string, ContextMenuSlots<T>[string]>
|
||||
|
||||
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: ContextMenuItem, active?: boolean, index: number }>()
|
||||
@@ -64,7 +65,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
|
||||
{{ get(item, props.labelKey as string) }}
|
||||
</slot>
|
||||
|
||||
<UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
|
||||
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
|
||||
</span>
|
||||
|
||||
<span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
|
||||
@@ -112,6 +113,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
|
||||
:label-key="labelKey"
|
||||
:checked-icon="checkedIcon"
|
||||
:loading-icon="loadingIcon"
|
||||
:external-icon="externalIcon"
|
||||
v-bind="item.content"
|
||||
>
|
||||
<template v-for="(_, name) in proxySlots" #[name]="slotData: any">
|
||||
|
||||
@@ -51,6 +51,12 @@ export interface DropdownMenuProps<T> extends Omit<DropdownMenuRootProps, 'dir'>
|
||||
* @defaultValue appConfig.ui.icons.loading
|
||||
*/
|
||||
loadingIcon?: string
|
||||
/**
|
||||
* The icon displayed when the item is an external link.
|
||||
* Set to `false` to hide the external icon.
|
||||
* @defaultValue appConfig.ui.icons.external
|
||||
*/
|
||||
externalIcon?: boolean | string
|
||||
/**
|
||||
* The content of the menu.
|
||||
* @defaultValue { side: 'bottom', sideOffset: 8, collisionPadding: 8 }
|
||||
@@ -149,6 +155,7 @@ import UDropdownMenuContent from './DropdownMenuContent.vue'
|
||||
const props = withDefaults(defineProps<DropdownMenuProps<T>>(), {
|
||||
portal: true,
|
||||
modal: true,
|
||||
externalIcon: true,
|
||||
labelKey: 'label'
|
||||
})
|
||||
const emits = defineEmits<DropdownMenuEmits>()
|
||||
@@ -180,6 +187,7 @@ const ui = computed(() => dropdownMenu({
|
||||
:label-key="labelKey"
|
||||
:checked-icon="checkedIcon"
|
||||
:loading-icon="loadingIcon"
|
||||
:external-icon="externalIcon"
|
||||
>
|
||||
<template v-for="(_, name) in proxySlots" #[name]="slotData: any">
|
||||
<slot :name="name" v-bind="slotData" />
|
||||
|
||||
@@ -14,6 +14,7 @@ interface DropdownMenuContentProps<T> extends Omit<RekaDropdownMenuContentProps,
|
||||
labelKey: string
|
||||
checkedIcon?: string
|
||||
loadingIcon?: string
|
||||
externalIcon?: boolean | string
|
||||
class?: any
|
||||
ui: typeof _dropdownMenu
|
||||
uiOverride?: any
|
||||
@@ -48,7 +49,7 @@ const emits = defineEmits<DropdownMenuContentEmits>()
|
||||
const slots = defineSlots<DropdownMenuContentSlots<T>>()
|
||||
|
||||
const appConfig = useAppConfig()
|
||||
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'class', 'ui', 'uiOverride'), emits)
|
||||
const contentProps = useForwardPropsEmits(reactiveOmit(props, 'sub', 'items', 'portal', 'labelKey', 'checkedIcon', 'loadingIcon', 'externalIcon', 'class', 'ui', 'uiOverride'), emits)
|
||||
const proxySlots = omit(slots, ['default']) as Record<string, DropdownMenuContentSlots<T>[string]>
|
||||
|
||||
const [DefineItemTemplate, ReuseItemTemplate] = createReusableTemplate<{ item: DropdownMenuItem, active?: boolean, index: number }>()
|
||||
@@ -70,7 +71,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
|
||||
{{ get(item, props.labelKey as string) }}
|
||||
</slot>
|
||||
|
||||
<UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
|
||||
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.itemLabelExternalIcon({ class: uiOverride?.itemLabelExternalIcon, color: item?.color, active })" />
|
||||
</span>
|
||||
|
||||
<span :class="ui.itemTrailing({ class: uiOverride?.itemTrailing })">
|
||||
@@ -121,6 +122,7 @@ const groups = computed(() => props.items?.length ? (Array.isArray(props.items[0
|
||||
:label-key="labelKey"
|
||||
:checked-icon="checkedIcon"
|
||||
:loading-icon="loadingIcon"
|
||||
:external-icon="externalIcon"
|
||||
v-bind="item.content"
|
||||
>
|
||||
<template v-for="(_, name) in proxySlots" #[name]="slotData: any">
|
||||
|
||||
@@ -53,6 +53,12 @@ export interface NavigationMenuProps<T> extends Pick<NavigationMenuRootProps, 'm
|
||||
* @defaultValue appConfig.ui.icons.chevronDown
|
||||
*/
|
||||
trailingIcon?: string
|
||||
/**
|
||||
* The icon displayed when the item is an external link.
|
||||
* Set to `false` to hide the external icon.
|
||||
* @defaultValue appConfig.ui.icons.external
|
||||
*/
|
||||
externalIcon?: boolean | string
|
||||
items?: T
|
||||
color?: NavigationMenuVariants['color']
|
||||
variant?: NavigationMenuVariants['variant']
|
||||
@@ -161,6 +167,7 @@ import UCollapsible from './Collapsible.vue'
|
||||
const props = withDefaults(defineProps<NavigationMenuProps<I>>(), {
|
||||
orientation: 'horizontal',
|
||||
contentOrientation: 'horizontal',
|
||||
externalIcon: true,
|
||||
delayDuration: 0,
|
||||
unmountOnHide: true,
|
||||
labelKey: 'label'
|
||||
@@ -222,7 +229,7 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
|
||||
{{ get(item, props.labelKey as string) }}
|
||||
</slot>
|
||||
|
||||
<UIcon v-if="item.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: props.ui?.linkLabelExternalIcon, active })" />
|
||||
<UIcon v-if="item.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.linkLabelExternalIcon({ class: props.ui?.linkLabelExternalIcon, active })" />
|
||||
</span>
|
||||
|
||||
<span v-if="(!collapsed || orientation !== 'vertical') && (item.badge || (orientation === 'horizontal' && (item.children?.length || !!slots[item.slot ? `${item.slot}-content` : 'item-content'])) || (orientation === 'vertical' && item.children?.length) || item.trailingIcon || !!slots[item.slot ? `${item.slot}-trailing` : 'item-trailing'])" :class="ui.linkTrailing({ class: props.ui?.linkTrailing })">
|
||||
@@ -281,7 +288,7 @@ const lists = computed(() => props.items?.length ? (Array.isArray(props.items[0]
|
||||
<p :class="ui.childLinkLabel({ class: props.ui?.childLinkLabel, active: childActive })">
|
||||
{{ get(childItem, props.labelKey as string) }}
|
||||
|
||||
<UIcon v-if="childItem.target === '_blank'" :name="appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
|
||||
<UIcon v-if="childItem.target === '_blank' && externalIcon !== false" :name="typeof externalIcon === 'string' ? externalIcon : appConfig.ui.icons.external" :class="ui.childLinkLabelExternalIcon({ class: props.ui?.childLinkLabelExternalIcon, active: childActive })" />
|
||||
</p>
|
||||
<p v-if="childItem.description" :class="ui.childLinkDescription({ class: props.ui?.childLinkDescription, active: childActive })">
|
||||
{{ childItem.description }}
|
||||
|
||||
Reference in New Issue
Block a user