fix(ui): fix sidebar tooltip placement and API for Nuxt UI v4

Nuxt UI v4 废弃 :popper="{ placement }",改为 :content="{ side }",
旧写法被忽略导致 tooltip 一律显示在下方。

- 展开态按钮(收起、搜索、排序、管理)→ side: bottom
- 折叠态元素(会话项、SidebarButton)→ side: right
- SidebarButton 重构:UTooltip 只包折叠态 div,避免 Reka UI as-child
  在 v-if/v-else 切换时 trigger 引用错乱导致 tooltip 位置错误

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
diguaandClaude Sonnet 4.6 committed 2026-05-31 16:56:08 +08:00
1 parent 69d887c7e2
commit 1b596d664f
3 files changed
+22 -23

No files matched your search

+4 -4
View File
@@ -266,7 +266,7 @@ function getAvatarColorClass(session: AnalysisSession, isActive: boolean) {
<UTooltip
v-if="!isCollapsed"
:text="t('layout.tooltip.collapse')"
:popper="{ placement: 'right' }"
:content="{ side: 'bottom' }"
style="-webkit-app-region: no-drag"
>
<UButton
@@ -298,7 +298,7 @@ function getAvatarColorClass(session: AnalysisSession, isActive: boolean) {
<SubTabs v-model="filterType" :items="filterTabItems" size="sm" :bordered="false">
<template #right>
<div class="flex items-center gap-0.5">
<UTooltip :text="t('layout.tooltip.search')" :popper="{ placement: 'right' }">
<UTooltip :text="t('layout.tooltip.search')" :content="{ side: 'bottom' }">
<UButton
:icon="showSearch ? 'i-heroicons-x-mark' : 'i-heroicons-magnifying-glass'"
color="neutral"
@@ -308,7 +308,7 @@ function getAvatarColorClass(session: AnalysisSession, isActive: boolean) {
/>
</UTooltip>
<SidebarSortPopover />
<UTooltip :text="t('layout.manage')" :popper="{ placement: 'right' }">
<UTooltip :text="t('layout.manage')" :content="{ side: 'bottom' }">
<UButton
icon="i-heroicons-rectangle-stack"
color="neutral"
@@ -353,7 +353,7 @@ function getAvatarColorClass(session: AnalysisSession, isActive: boolean) {
:items="getContextMenuItems(session)"
>
<!-- 侧边栏折叠时,hover 显示完整会话名称(Tooltip 需绑定到真实 DOM) -->
<UTooltip :text="session.name" :disabled="!isCollapsed || !session.name" :popper="{ placement: 'right' }">
<UTooltip :text="session.name" :disabled="!isCollapsed || !session.name" :content="{ side: 'right' }">
<div
class="group relative flex items-center text-left transition-all duration-200 cursor-pointer"
:class="[
+17 -18
View File
@@ -19,10 +19,9 @@ const { isSidebarCollapsed: isCollapsed } = storeToRefs(layoutStore)
</script>
<template>
<UTooltip :text="isCollapsed ? tooltip || title : ''" :popper="{ placement: 'right' }">
<!-- 收起状态:用原生 div 承载背景和尺寸,与会话列表项结构一致,避免 UButton 内部撑大 -->
<!-- 收起状态:UTooltip 只包收起态 div,避免 as-child 在 v-if/v-else 切换时引用错乱 -->
<UTooltip v-if="isCollapsed" :text="tooltip || title" :content="{ side: 'right' }">
<div
v-if="isCollapsed"
class="flex h-9 w-9 cursor-pointer items-center justify-center rounded-xl mx-auto transition-all duration-200"
:class="[
active
@@ -32,20 +31,20 @@ const { isSidebarCollapsed: isCollapsed } = storeToRefs(layoutStore)
>
<UIcon :name="icon" class="h-5 w-5 shrink-0" />
</div>
<!-- 展开状态:保持原有 UButton 样式 -->
<UButton
v-else
class="transition-all duration-200 rounded-xl hover:bg-gray-200/40 dark:hover:bg-gray-800/40 h-10 cursor-pointer justify-start pl-1.5 w-[calc(100%-8px)]"
:class="[
active
? 'bg-gray-200/50 dark:bg-gray-800/80 text-gray-900 dark:text-white font-medium'
: 'text-gray-600 dark:text-gray-300',
]"
color="gray"
variant="ghost"
>
<UIcon :name="icon" class="mr-2.5 h-5 w-5 shrink-0" />
<span class="truncate text-xs font-medium">{{ title }}</span>
</UButton>
</UTooltip>
<!-- 展开状态:直接渲染 UButton,标题已可见,无需 tooltip -->
<UButton
v-else
class="transition-all duration-200 rounded-xl hover:bg-gray-200/40 dark:hover:bg-gray-800/40 h-10 cursor-pointer justify-start pl-1.5 w-[calc(100%-8px)]"
:class="[
active
? 'bg-gray-200/50 dark:bg-gray-800/80 text-gray-900 dark:text-white font-medium'
: 'text-gray-600 dark:text-gray-300',
]"
color="gray"
variant="ghost"
>
<UIcon :name="icon" class="mr-2.5 h-5 w-5 shrink-0" />
<span class="truncate text-xs font-medium">{{ title }}</span>
</UButton>
</template>
@@ -32,7 +32,7 @@ function handleSortSelect(field: SortOption['value']) {
<template>
<UPopover v-model:open="isSortPopoverOpen" :ui="{ content: 'z-50 p-0' }">
<UTooltip :text="t('layout.tooltip.sort')" :popper="{ placement: 'right' }">
<UTooltip :text="t('layout.tooltip.sort')" :content="{ side: 'bottom' }">
<UButton
:icon="sortOrder === 'desc' ? 'i-heroicons-bars-arrow-down' : 'i-heroicons-bars-arrow-up'"
color="neutral"