fix(tabs): 未分组横版标签保留用户配置的连接底色 (#12756)

Co-authored-by: zipg <4047349+zipg@users.noreply.github.com>
This commit is contained in:
zipg
2026-10-19 20:01:39 +08:00
committed by GitHub
co-authored by zipg
parent e327f5f6de
commit b81f18e4f5
2 changed files with 68 additions and 7 deletions
@@ -103,7 +103,20 @@ import {
createSaveAllTabsMenuItem,
} from "@/lib/tabs/tabMenu";
import { formatShortcut } from "@/lib/editor/shortcutRegistry";
import { findTabWithSameTitleSuffix, joinTabTitleParts, TAB_TITLE_SUFFIX_MAX_LENGTH, tabConnectionColor, dirtyTabTitleStyle, tabColorStyle as sharedTabColorStyle, tabDatabaseIconType, tabDisplayTitle, tabDisplayTitleParts, tabIconClass, tabTooltipLines } from "@/lib/tabs/tabPresentation";
import {
connectionColor,
findTabWithSameTitleSuffix,
joinTabTitleParts,
TAB_TITLE_SUFFIX_MAX_LENGTH,
tabConnectionColor,
dirtyTabTitleStyle,
tabColorStyle as sharedTabColorStyle,
tabDatabaseIconType,
tabDisplayTitle,
tabDisplayTitleParts,
tabIconClass,
tabTooltipLines,
} from "@/lib/tabs/tabPresentation";
import { activeTabSidebarTarget } from "@/lib/sidebar/sidebarActiveTabTarget";
import "./appTabBar.css";
import type { QueryTab } from "@/types/database";
@@ -1112,9 +1125,9 @@ const stripSections = computed(() => {
});
function tabColorStyle(tab: QueryTab): CSSProperties | undefined {
// Keep ungrouped sidebar tabs aligned with the horizontal tab strip: every
// tab gets a connection-colored wash, while the active tab gets the stronger
// border and leading accent.
// Grouped sidebar tabs rely on the tree rails; ungrouped ones keep a
// connection-colored wash (configured or generated), with a stronger border
// and leading accent on the active tab.
if (isVerticalLayout.value) {
if (settingsStore.editorSettings.tabGroupMode !== "none" || !settingsStore.editorSettings.colorizeConnectionTabs) return undefined;
const active = isTabActive(tab);
@@ -1130,10 +1143,15 @@ function tabColorStyle(tab: QueryTab): CSSProperties | undefined {
: { borderColor: hexToRgba(color, 0.18) }),
} as CSSProperties;
}
// Keep horizontal tabs quiet by default; group headers and rails already
// provide the connection identity, while the selected tab gets the wash.
if (!isTabActive(tab)) {
return undefined;
// Grouped horizontal tabs already show the group identity on the header
// and rail (the connection color when grouping by connection), so keep
// their washes quiet to make the active tab easy to spot (issue #12485).
// Ungrouped tabs have no rail: a color the user configured in the
// connection settings still marks them, while the auto-generated hue stays
// quiet.
const grouped = settingsStore.editorSettings.tabGroupMode !== "none";
if (grouped || !connectionColor(tab.connectionId)) return undefined;
}
return sharedTabColorStyle(tab, isTabActive(tab), isClassicLayout.value);
}
@@ -222,6 +222,49 @@ describe("EditorGroupTabBar group behavior", () => {
}
});
it.each(["classic", "separated"] as const)("keeps configured connection colors on inactive horizontal tabs when grouping is off in %s layout", async (layout) => {
const store = useQueryStore();
const settings = useSettingsStore();
const connectionStore = useConnectionStore();
connectionStore.connections = [{ id: "pg-1", name: "Postgres", db_type: "postgres", driver_profile: "postgres", color: "#3b82f6" } as ConnectionConfig, { id: "pg-2", name: "Auto", db_type: "postgres", driver_profile: "postgres", color: "" } as ConnectionConfig];
settings.editorSettings.appLayout = layout;
settings.editorSettings.tabGroupMode = "none";
settings.editorSettings.tabPlacement = "top";
settings.editorSettings.colorizeConnectionTabs = true;
const activeTabId = store.createTab("pg-1", "app", "PG 1", "query");
const configuredTabId = store.createTab("pg-1", "app", "PG 2", "query");
const autoTabId = store.createTab("pg-2", "app", "PG 3", "query");
const { app, host } = mountBar(store.groups[0]!.id, store.tabs.slice(), activeTabId, pinia);
try {
for (const placement of ["top", "bottom"] as const) {
settings.editorSettings.tabPlacement = placement;
await settle();
const activeTab = host.querySelector<HTMLElement>(`[data-tab-id="${activeTabId}"]`)!;
const configuredTab = host.querySelector<HTMLElement>(`[data-tab-id="${configuredTabId}"]`)!;
const autoTab = host.querySelector<HTMLElement>(`[data-tab-id="${autoTabId}"]`)!;
const activeBackground = activeTab.style.getPropertyValue("--app-tab-background");
const configuredBackground = configuredTab.style.getPropertyValue("--app-tab-background");
expect(configuredTab.getAttribute("data-active-tab")).toBe("false");
// A color the user picked in the connection settings keeps marking its
// tabs when no group header/rail carries it; auto-generated hues stay
// quiet and the active tab still reads stronger than its peers.
expect(configuredBackground).toBe(layout === "classic" ? "rgba(59, 130, 246, 0.07)" : "rgba(59, 130, 246, 0.09)");
expect(autoTab.style.getPropertyValue("--app-tab-background")).toBe("");
expect(activeBackground).toBe("rgba(59, 130, 246, 0.24)");
}
// Turning the connection-tab colors off must silence the inactive wash
// even for a configured connection color.
settings.editorSettings.colorizeConnectionTabs = false;
await settle();
expect(host.querySelector<HTMLElement>(`[data-tab-id="${configuredTabId}"]`)!.style.getPropertyValue("--app-tab-background")).toBe("");
} finally {
app.unmount();
host.remove();
}
});
it("renders one header per connection cluster and collapses it to a count badge", async () => {
const store = useQueryStore();
const settings = useSettingsStore();