Files
backnotprop__plannotator/packages/ui/hooks/useSidebar.ts
T
Michael Ramos e5f3cfffbb feat: Obsidian vault browser sidebar tab (#209)
* feat: add Obsidian vault browser sidebar tab (#207)

Add a third sidebar tab that lets users browse their Obsidian vault's
file tree, click any markdown file to open and annotate it as part of
plan feedback. Includes wikilink support for navigating between vault
files.

- New /api/reference/obsidian/files and /api/reference/obsidian/doc endpoints
- useVaultBrowser hook and VaultBrowser sidebar component
- Wikilink [[filename]] and [[filename|display]] detection in Viewer
- "Vault Browser" toggle in Settings > Obsidian
- Bare filename search for wikilink resolution within vault

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: update docs and clear vault state on disable

- Add new reference endpoints to CLAUDE.md API table
- Update stale doc comments referencing "two tabs" in sidebar files
- Clear vaultPath and activeFile when vault browser is disabled

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* refactor: simplify vault browser prop passing and derived state

- Move VaultNode to packages/ui/types.ts (shared type location)
- Pass useVaultBrowser return as single object prop through SidebarContainer
- Replace showVaultTab/vaultPath useState with useMemo derivations
- Extract buildVaultDocUrl helper to deduplicate URL template
- Wrap onVaultFetchTree in useCallback
- Fix toggle switch size to match existing toggles (h-6 w-11)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:32:59 -08:00

57 lines
1.5 KiB
TypeScript

/**
* Sidebar Hook
*
* Manages the shared left sidebar state: open/close and active tab (TOC, Versions, or Vault).
* The sidebar is shared between the Table of Contents, Version Browser, and Vault Browser views.
*/
import { useState, useCallback } from "react";
export type SidebarTab = "toc" | "versions" | "vault";
export interface UseSidebarReturn {
isOpen: boolean;
activeTab: SidebarTab;
/** Open the sidebar, optionally switching to a specific tab */
open: (tab?: SidebarTab) => void;
/** Close the sidebar */
close: () => void;
/**
* Toggle a tab:
* - If sidebar is closed → open to that tab
* - If sidebar is open and same tab → close
* - If sidebar is open and different tab → switch to that tab
*/
toggleTab: (tab: SidebarTab) => void;
}
export function useSidebar(initialOpen: boolean): UseSidebarReturn {
const [isOpen, setIsOpen] = useState(initialOpen);
const [activeTab, setActiveTab] = useState<SidebarTab>("toc");
const open = useCallback((tab?: SidebarTab) => {
setIsOpen(true);
if (tab) setActiveTab(tab);
}, []);
const close = useCallback(() => {
setIsOpen(false);
}, []);
const toggleTab = useCallback(
(tab: SidebarTab) => {
if (!isOpen) {
setIsOpen(true);
setActiveTab(tab);
} else if (activeTab === tab) {
setIsOpen(false);
} else {
setActiveTab(tab);
}
},
[isOpen, activeTab]
);
return { isOpen, activeTab, open, close, toggleTab };
}