add NavBarActionMenu.vue

This commit is contained in:
Timi
2026-08-22 15:33:58 +08:00
parent 189916b68d
commit e237b71f13
5 changed files with 186 additions and 111 deletions
+116
View File
@@ -0,0 +1,116 @@
<template>
<teleport v-if="navBarStore.customRightVisible && visibleActionList.length" to="#app-nav-right">
<div class="nav-actions">
<t-popover
v-model:visible="actionVisible"
placement="bottom-right"
theme="light"
>
<t-button
class="trigger"
variant="text"
:aria-label="triggerLabel"
type="button"
>
<template #icon>
<t-icon :name="triggerIcon" />
</template>
<span v-if="triggerText" v-text="triggerText" />
</t-button>
<template #content>
<div class="menu">
<t-button
v-for="action in visibleActionList"
:key="action.key"
class="menu-item"
variant="text"
type="button"
:theme="action.theme"
:loading="action.loading"
:disabled="action.disabled || action.loading"
@click="handleAction(action)"
>
<template v-if="action.icon" #icon>
<t-icon :name="action.icon" />
</template>
<span v-text="action.text" />
</t-button>
</div>
</template>
</t-popover>
</div>
</teleport>
</template>
<script setup lang="ts">
import { useNavBarStore } from "@/store/navBarStore";
import type { NavBarAction } from "@/types/NavBarAction";
defineOptions({
name: "NavBarActionMenu"
});
interface Props {
actions: readonly NavBarAction[];
triggerIcon?: string;
triggerLabel?: string;
triggerText?: string;
}
const props = withDefaults(defineProps<Props>(), {
triggerIcon: "ellipsis",
triggerLabel: "更多操作",
triggerText: ""
});
const navBarStore = useNavBarStore();
const actionVisible = ref(false);
const visibleActionList = computed(() => props.actions.filter(action => action.visible !== false));
async function handleAction(action: NavBarAction): Promise<void> {
actionVisible.value = false;
await action.action();
}
</script>
<style scoped lang="less">
.nav-actions {
--td-popover-padding: 0 .5rem;
:deep(.t-popover__content) {
border-radius: .875rem;
}
.trigger {
padding: 0;
}
.menu {
gap: .25rem;
display: grid;
padding: .5rem 0;
min-width: 9rem;
.menu-item {
--td-button-medium-height: 32px;
--td-button-medium-padding-horizontal: 10px;
gap: .25rem;
width: 100%;
font-weight: unset;
justify-content: flex-start;
}
}
}
:global(html.theme-dark) .nav-actions {
:deep(.t-popover__content) {
color: #e2e8f0;
background: rgba(30, 41, 59, .98);
}
.menu-item {
color: #e2e8f0;
}
}
</style>