mirror of
https://github.com/t8y2/dbx.git
synced 2026-10-30 00:19:35 +00:00
feat: add persistent selected node highlight in sidebar tree
- Track selectedTreeNodeId in connection store - Highlight any clicked tree node with focused (blue) / unfocused (gray) styles - Use CSS :focus-within for automatic focus state switching
This commit is contained in:
@@ -273,7 +273,7 @@ defineExpose({ focusSearch });
|
||||
</div>
|
||||
<RecycleScroller
|
||||
v-if="flatNodes.length > 0 && useVirtualTree"
|
||||
class="connection-tree-scroller min-h-0 flex-1 overflow-y-auto overflow-x-auto"
|
||||
class="sidebar-tree connection-tree-scroller min-h-0 flex-1 overflow-y-auto overflow-x-auto"
|
||||
:items="flatNodes"
|
||||
:item-size="SIDEBAR_TREE_ROW_HEIGHT"
|
||||
:buffer="SIDEBAR_TREE_SCROLL_BUFFER"
|
||||
@@ -294,7 +294,7 @@ defineExpose({ focusSearch });
|
||||
/>
|
||||
</template>
|
||||
</RecycleScroller>
|
||||
<div v-else-if="flatNodes.length > 0" class="min-h-0 flex-1 overflow-y-auto overflow-x-auto">
|
||||
<div v-else-if="flatNodes.length > 0" class="sidebar-tree min-h-0 flex-1 overflow-y-auto overflow-x-auto">
|
||||
<TreeItem
|
||||
v-for="item in flatNodes"
|
||||
:key="item.id"
|
||||
|
||||
@@ -326,6 +326,7 @@ function runRowClickAction() {
|
||||
}
|
||||
|
||||
function onClick(event: MouseEvent) {
|
||||
connectionStore.selectedTreeNodeId = props.node.id;
|
||||
if (event.detail > 1) return;
|
||||
runRowClickAction();
|
||||
}
|
||||
@@ -1181,6 +1182,7 @@ const connectionColor = computed(() => {
|
||||
const isActiveConnectionScope = computed(
|
||||
() => !!props.node.connectionId && connectionStore.activeConnectionId === props.node.connectionId,
|
||||
);
|
||||
const isSelected = computed(() => connectionStore.selectedTreeNodeId === props.node.id);
|
||||
const rowStyle = computed(() => {
|
||||
const color = connectionColor.value;
|
||||
return {
|
||||
@@ -1374,14 +1376,16 @@ const isDragging = computed(() => dragState.active && dragState.draggedId === pr
|
||||
<ContextMenuTrigger as-child>
|
||||
<div>
|
||||
<div
|
||||
class="group flex min-w-0 items-center gap-1.5 py-1 px-2 cursor-pointer hover:bg-accent transition-colors relative"
|
||||
class="group flex min-w-0 items-center gap-1.5 py-1 px-2 cursor-pointer hover:bg-accent transition-colors relative outline-none"
|
||||
style="contain: layout style paint"
|
||||
:class="{
|
||||
'ring-1 ring-primary/50 bg-primary/5': showDropInside,
|
||||
'opacity-50': isDragging,
|
||||
'rounded-none': connectionColor,
|
||||
'rounded-sm': !connectionColor,
|
||||
'rounded-none': connectionColor && !isSelected,
|
||||
'rounded-sm': !connectionColor && !isSelected,
|
||||
'tree-item-active rounded-md': isSelected,
|
||||
}"
|
||||
:tabindex="isSelected ? 0 : -1"
|
||||
:style="rowStyle"
|
||||
@click="onClick"
|
||||
@dblclick="onDoubleClick"
|
||||
@@ -1966,3 +1970,21 @@ const isDragging = computed(() => dragState.active && dragState.draggedId === pr
|
||||
@confirm="confirmDropSchema"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
/* Unfocused: subtle gray */
|
||||
.tree-item-active {
|
||||
background-color: oklch(0.94 0 0) !important;
|
||||
}
|
||||
:root.dark .tree-item-active {
|
||||
background-color: oklch(0.26 0 0) !important;
|
||||
}
|
||||
|
||||
/* Focused: soft blue */
|
||||
.sidebar-tree:focus-within .tree-item-active {
|
||||
background-color: oklch(0.91 0.03 250) !important;
|
||||
}
|
||||
:root.dark .sidebar-tree:focus-within .tree-item-active {
|
||||
background-color: oklch(0.35 0.06 250) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -47,6 +47,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
const connections = ref<ConnectionConfig[]>([]);
|
||||
const isDesktop = isTauriRuntime();
|
||||
const activeConnectionId = ref<string | null>(!isDesktop ? localStorage.getItem("dbx-active-connection") : null);
|
||||
const selectedTreeNodeId = ref<string | null>(null);
|
||||
|
||||
watch(activeConnectionId, (id) => {
|
||||
if (isDesktop) return;
|
||||
@@ -1436,6 +1437,7 @@ export const useConnectionStore = defineStore("connection", () => {
|
||||
return {
|
||||
connections,
|
||||
activeConnectionId,
|
||||
selectedTreeNodeId,
|
||||
treeNodes,
|
||||
refreshAllTree,
|
||||
refreshSavedSqlTree,
|
||||
|
||||
Reference in New Issue
Block a user