feat(ui): add copy action to error banners

This commit is contained in:
t8y2 2026-06-15 12:47:54 +08:00
parent aab30d7c44
commit 1a91cb7c77
2 changed files with 14 additions and 5 deletions

View File

@ -7267,10 +7267,7 @@ const gridContextMenuItems = computed<ContextMenuItem[]>(() => {
</div>
<!-- Error bar -->
<div v-if="saveError" class="px-3 py-1.5 border-t bg-destructive/10 text-destructive text-xs shrink-0 flex items-center gap-2">
<span class="flex-1">{{ saveError }}</span>
<button class="hover:underline" @click="saveError = ''">{{ t("grid.dismiss") }}</button>
</div>
<ErrorBanner v-if="saveError" :message="saveError" copy-mode="label" dismissible @dismiss="saveError = ''" />
<!-- Bottom status bar -->
<div v-if="!isErrorResult" class="grid grid-cols-[minmax(0,1fr)_minmax(0,38%)_minmax(0,1fr)] items-center gap-2 px-3 py-1 border-t text-xs text-muted-foreground bg-muted/30 shrink-0">

View File

@ -14,12 +14,20 @@ const props = withDefaults(
message: string;
variant?: "banner" | "centered";
title?: string;
dismissible?: boolean;
copyMode?: "icon" | "label";
}>(),
{
variant: "banner",
dismissible: false,
copyMode: "icon",
},
);
const emit = defineEmits<{
dismiss: [];
}>();
const displayTitle = computed(() => props.title ?? t("grid.queryError"));
async function copy() {
@ -36,9 +44,13 @@ async function copy() {
<!-- banner: 紧凑内联横幅 -->
<div v-if="variant === 'banner'" class="flex items-center gap-2 px-3 py-1.5 border-t bg-destructive/10 text-destructive text-xs shrink-0">
<span class="flex-1 min-w-0 break-all">{{ message }}</span>
<Button variant="ghost" size="icon-sm" class="h-5 w-5 shrink-0 text-destructive/70 hover:text-destructive" :aria-label="t('grid.copy')" @click.stop="copy">
<button v-if="copyMode === 'label'" type="button" class="shrink-0 hover:underline" :aria-label="t('grid.copy')" @click.stop="copy">
{{ t("grid.copy") }}
</button>
<Button v-else variant="ghost" size="icon-sm" class="h-5 w-5 shrink-0 text-destructive/70 hover:text-destructive" :aria-label="t('grid.copy')" @click.stop="copy">
<Copy class="h-3 w-3" />
</Button>
<button v-if="dismissible" type="button" class="shrink-0 hover:underline" @click.stop="emit('dismiss')">{{ t("grid.dismiss") }}</button>
</div>
<!-- centered: 居中占满 -->