Skip to content

Commit a53aea9

Browse files
committed
feat: enhance MenuLink component to support external URLs and new tab option
1 parent 67b4d9b commit a53aea9

2 files changed

Lines changed: 35 additions & 7 deletions

File tree

adminforth/spa/src/components/MenuLink.vue

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
<template>
2-
<RouterLink
3-
:to="item.url || { name: item.resourceId ? 'resource-list' : item.path, params: item.resourceId ? { resourceId: item.resourceId }: {}}"
2+
<component
3+
:is="isExternalUrl(item.url) ? 'a' : RouterLink"
4+
v-bind="isExternalUrl(item.url)
5+
? { href: item.url }
6+
: { to: item.url || { name: item.resourceId ? 'resource-list' : item.path, params: item.resourceId ? { resourceId: item.resourceId }: {} } }"
47
:target="item.isOpenInNewTab ? '_blank' : '_self'"
5-
class="af-menu-link flex group relative items-center w-full py-2 text-lightSidebarText dark:text-darkSidebarText rounded-default transition-all duration-200 ease-in-out"
6-
:class="{
8+
class="af-menu-link flex group relative items-center w-full py-2 text-lightSidebarText dark:text-darkSidebarText rounded-default transition-all duration-200 ease-in-out"
9+
:class="{
710
'hover:bg-lightSidebarItemHover hover:text-lightSidebarTextHover dark:hover:bg-darkSidebarItemHover dark:hover:text-darkSidebarTextHover active:bg-lightSidebarActive dark:active:bg-darkSidebarHover': !['divider', 'gap', 'heading'].includes(item.type),
811
'pl-6 pr-3.5': (isChild && !isSidebarIconOnly && !isSidebarHovering) || (isChild && isSidebarIconOnly && isSidebarHovering),
912
'px-3.5 ': !isChild || (isSidebarIconOnly && !isSidebarHovering),
@@ -51,7 +54,7 @@
5154
<div v-if="(item.badge || item.badge === 0) && isSidebarIconOnly && !isSidebarHovering" class="af-badge absolute right-0.5 bottom-1 -translate-y-1/2 inline-flex items-center justify-center h-2 w-2 text-sm font-medium rounded-full bg-lightAnnouncementBG dark:bg-darkAnnouncementBG
5255
fill-lightAnnouncementText dark:fill-darkAccent text-lightAnnouncementText dark:text-darkAccent">
5356
</div>
54-
</RouterLink>
57+
</component>
5558
</template>
5659

5760
<script setup lang="ts">
@@ -60,13 +63,15 @@ import { Tooltip } from '@/afcl';
6063
import { ref, watch, computed } from 'vue';
6164
import { useCoreStore } from '@/stores/core';
6265
import { IconFileImageOutline } from '@iconify-prerendered/vue-flowbite';
63-
import { useRoute } from 'vue-router';
66+
import { useRoute, RouterLink } from 'vue-router';
67+
68+
const isExternalUrl = (url: string ) => /^https?:\/\//.test(url || '');
6469
6570
const route = useRoute();
6671
6772
const isItemActive = (item: any) => {
6873
if (item.url) {
69-
return route.fullPath === item.url;
74+
return !isExternalUrl(item.url) && route.fullPath === item.url;
7075
}
7176
7277
if (item.resourceId) {

adminforth/types/Common.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1177,8 +1177,31 @@ export interface AdminForthConfigMenuItem {
11771177
* Item id will be automatically generated from hashed resourceId+Path+label
11781178
*/
11791179
itemId?: string, // todo move to runtime type
1180+
1181+
1182+
/**
1183+
* If set, menu item will be rendered as external link with this URL. Supported for AdminForthMenuTypes.PAGE and AdminForthMenuTypes.RESOURCE only!
1184+
* If URL starts with `http://` or `https://`, it will be treated as absolute URL. Otherwise, it will be treated as relative to admin panel base URL.
1185+
* Example of absolute URL:
1186+
*
1187+
* ```ts
1188+
* url: 'https://google.com',
1189+
* ```
1190+
*
1191+
* Example of relative URL:
1192+
*
1193+
* ```ts
1194+
* url: '/custom-page',
1195+
* ```
1196+
*/
11801197

11811198
url?: string
1199+
1200+
1201+
/**
1202+
* If true, link will be opened in new tab.
1203+
*/
1204+
isOpenInNewTab?: boolean,
11821205
}
11831206

11841207

0 commit comments

Comments
 (0)