Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co

- **Zustand** with persistence middleware manages tabs, key search, type filters, selections, and search history
- **React Query** handles server state (key lists, values, metadata)
- **Persistence:** Optional `RedisBrowserStorage` interface for localStorage/custom storage. Schema is at version 7 with automated migrations from earlier versions.
- **Persistence:** Optional `RedisBrowserStorage` interface for localStorage/custom storage. Schema is versioned (see `version` in `src/store.tsx`) with automated migrations from earlier versions.

### Key Source Locations

Expand Down
27 changes: 26 additions & 1 deletion src/components/databrowser/components/tab.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import type { TabId } from "@/store"
import { useDatabrowserStore } from "@/store"
import { useDatabrowserRootRef, useDatabrowserStore } from "@/store"
import { useTab } from "@/tab-provider"
import {
IconArrowsMinimize,
IconCopyPlus,
IconPin,
IconRestore,
IconSearch,
IconSquareX,
IconX,
Expand Down Expand Up @@ -34,12 +35,27 @@ export const Tab = ({ id, isList }: { id: TabId; isList?: boolean }) => {
duplicateTab,
closeOtherTabs,
closeAllButPinned,
closedTabs,
reopenClosedTab,
} = useDatabrowserStore()
const rootRef = useDatabrowserRootRef()

const hasPinnedTabs = tabs.some(([, data]) => data.pinned)

const { ref, isOverflow } = useOverflow()

const handleReopenClosedTab = () => {
const reopenedId = reopenClosedTab()
if (!reopenedId) return

setTimeout(() => {
const tab = rootRef?.current?.querySelector(`#tab-${reopenedId}`)
if (!tab) return

tab.scrollIntoView({ behavior: "smooth" })
}, 20)
}

const label = isValuesSearchSelected ? valuesSearch.index : search.key || selectedKey
const iconNode = isValuesSearchSelected ? (
<div className="flex h-[20px] w-[20px] items-center justify-center rounded-md bg-emerald-200 text-emerald-800">
Expand Down Expand Up @@ -125,6 +141,15 @@ export const Tab = ({ id, isList }: { id: TabId; isList?: boolean }) => {
<IconArrowsMinimize size={16} />
Close All But Pinned
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem
onSelect={handleReopenClosedTab}
className="gap-2"
disabled={closedTabs.length === 0}
>
<IconRestore size={16} />
Reopen Closed Tab
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
)
Expand Down
Loading
Loading