fix(ui): unify list hover and selection highlighting

This commit is contained in:
zipg authored and GitHub committed 2026-08-12 17:33:01 +08:00
1 parent d0b67ae795
commit fc2db2a17c
11 files changed
+142 -31

No files matched your search

@@ -381,8 +381,8 @@ function clearContextTarget() {
<div v-else>
<div v-for="(folder, fi) in folders" :key="folder.path" class="border-b last:border-b-0">
<div
class="flex cursor-default items-center gap-1 px-2 py-1.5 text-[11px] font-medium text-muted-foreground bg-muted/10 sticky top-0 select-none hover:bg-muted/30"
:class="selectedPath === folder.path ? 'bg-accent/60 text-accent-foreground' : ''"
class="flex cursor-default items-center gap-1 px-2 py-1.5 text-[11px] font-medium text-muted-foreground bg-muted/10 sticky top-0 select-none"
:class="selectedPath === folder.path ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40'"
@click="
toggleFolderCollapse(folder);
selectPath(folder.path);
@@ -429,8 +429,8 @@ function clearContextTarget() {
<div
v-for="{ entry, depth } in flatTree(folder.entries, folder.expanded)"
:key="entry.path"
class="flex cursor-default items-center gap-1 px-2 py-1 hover:bg-muted/60 text-sm"
:class="[entry.is_dir ? 'rounded-sm' : 'rounded-none', selectedPath === entry.path ? 'bg-accent text-accent-foreground' : '']"
class="flex cursor-default select-none items-center gap-1 px-2 py-1 text-sm"
:class="[entry.is_dir ? 'rounded-sm' : 'rounded-none', selectedPath === entry.path ? 'bg-accent text-accent-foreground' : 'hover:bg-accent/40']"
:style="{ paddingLeft: depth * 16 + 8 + 'px' }"
@click="
selectPath(entry.path);
@@ -517,22 +517,21 @@ function isFolderActive(folderId: string): boolean {
return activeItemType.value === "folder" && activeItemId.value === folderId;
}
function selectionRowClass(selected: boolean, active: boolean): string {
if (selected) return "bg-primary/10 text-foreground";
if (active) return "bg-primary/12 text-foreground";
return "hover:bg-accent";
function selectionRowClass(selected: boolean, active: boolean, contextOpen: boolean): string {
if (selected || active || contextOpen) return "bg-accent text-accent-foreground";
return "hover:bg-accent/40";
}
function fileRowClass(fileId: string): string {
return selectionRowClass(isFileSelected(fileId), isFileActive(fileId));
return selectionRowClass(isFileSelected(fileId), isFileActive(fileId), isContextFile(fileId));
}
function folderRowClass(folderId: string): string {
return selectionRowClass(isFolderSelected(folderId), isFolderActive(folderId));
return selectionRowClass(isFolderSelected(folderId), isFolderActive(folderId), isContextFolder(folderId));
}
function fileMetaClass(fileId: string): string {
return isFileSelected(fileId) || isFileActive(fileId) ? "text-foreground/70" : "text-muted-foreground";
return isFileSelected(fileId) || isFileActive(fileId) || isContextFile(fileId) ? "text-accent-foreground" : "text-muted-foreground";
}
function isFileDirty(file: SavedSqlFile): boolean {
@@ -798,6 +797,14 @@ function handleFolderClick(folder: SavedSqlFolder, event: MouseEvent) {
const contextTarget = ref<SavedSqlFolder | SavedSqlFile | "panel" | null>(null);
function isContextFile(fileId: string): boolean {
return contextTarget.value !== null && contextTarget.value !== "panel" && "sql" in contextTarget.value && contextTarget.value.id === fileId;
}
function isContextFolder(folderId: string): boolean {
return contextTarget.value !== null && contextTarget.value !== "panel" && !("sql" in contextTarget.value) && contextTarget.value.id === folderId;
}
function folderMoveMenuItems(fileIds: string[]): CtxMenuItem[] {
const files = [...new Set(fileIds)].map((id) => savedSqlStore.getFile(id)).filter((file): file is SavedSqlFile => Boolean(file));
const allInUnfiled = files.length > 0 && files.every((file) => !file.folderId);
@@ -0,0 +1,12 @@
import { readFileSync } from "node:fs";
import { describe, expect, it } from "vitest";
const panelSource = readFileSync(new URL("../SqlLibraryPanel.vue", import.meta.url), "utf8");
describe("SqlLibraryPanel selection contrast", () => {
it("uses the accent foreground for selected rows and their metadata", () => {
expect(panelSource).toContain('return "bg-accent text-accent-foreground";');
expect(panelSource).toMatch(/function fileMetaClass[\s\S]*\? "text-accent-foreground" : "text-muted-foreground";/);
expect(panelSource).not.toContain('contextFile(fileId) ? "text-foreground/70"');
});
});