+
+
+
+
-
+
+
);
}
diff --git a/packages/graph-explorer/src/routes/DataExplorer/DataExplorer.tsx b/packages/graph-explorer/src/routes/DataExplorer/DataExplorer.tsx
index 441cc33f6..2e33b7a30 100644
--- a/packages/graph-explorer/src/routes/DataExplorer/DataExplorer.tsx
+++ b/packages/graph-explorer/src/routes/DataExplorer/DataExplorer.tsx
@@ -20,13 +20,21 @@ import {
EmptyStateContent,
EmptyStateDescription,
EmptyStateTitle,
+ NavBar,
+ NavBarContent,
+ NavBarActions,
+ NavBarTitle,
+ NavBarVersion,
Panel,
PanelError,
+ PanelGroup,
PanelHeader,
PanelTitle,
SelectField,
SendIcon,
Spinner,
+ Workspace,
+ WorkspaceContent,
} from "@/components";
import { ExplorerIcon } from "@/components/icons";
import {
@@ -37,7 +45,6 @@ import {
type TabularInstance,
} from "@/components/Tabular";
import Tabular from "@/components/Tabular/Tabular";
-import Workspace from "@/components/Workspace/Workspace";
import { type KeywordSearchRequest, searchQuery } from "@/connector";
import { useVertexStyling } from "@/core/StateProvider/userPreferences";
import { useAddVertexToGraph, useHasVertexBeenAddedToGraph } from "@/hooks";
@@ -108,15 +115,15 @@ function DataExplorerContent({ vertexType }: ConnectionsProps) {
return (
-
-
-
- {__GRAPH_EXP_VERSION__}
-
-
+
+
+
+
+
+ {__GRAPH_EXP_VERSION__}
Open {LABELS.APP_NAME}
-
-
-
-
+
+
+
+
Back to all Data
-
-
+
+
-
-
-
-
-
-
- {displayTypeConfig.displayLabel}{" "}
- {query.isFetching ? : null}
-
-
-
-
- {query.isError ? (
-
- ) : null}
- {query.data?.vertices.length === 0 && (
-
-
- No Results
-
- {`No nodes found for "${displayTypeConfig.displayLabel}"`}
-
-
-
- )}
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {displayTypeConfig.displayLabel}{" "}
+ {query.isFetching ? : null}
+
+
+
+
+ {query.isError ? (
+
+ ) : null}
+ {query.data?.vertices.length === 0 && (
+
+
+ No Results
+
+ {`No nodes found for "${displayTypeConfig.displayLabel}"`}
+
+
+
+ )}
+
+
+
+
+
+
+
+
);
}
diff --git a/packages/graph-explorer/src/routes/GraphExplorer/GraphExplorer.tsx b/packages/graph-explorer/src/routes/GraphExplorer/GraphExplorer.tsx
index 5b623c7ee..80214c2ab 100644
--- a/packages/graph-explorer/src/routes/GraphExplorer/GraphExplorer.tsx
+++ b/packages/graph-explorer/src/routes/GraphExplorer/GraphExplorer.tsx
@@ -1,12 +1,10 @@
-import { Activity } from "react";
-import { cn, isVisible } from "@/utils";
+import { cn } from "@/utils";
import { Resizable } from "re-resizable";
import { Link } from "react-router";
import {
Button,
buttonStyles,
Divider,
- EdgeIcon,
EmptyState,
EmptyStateActions,
EmptyStateContent,
@@ -14,39 +12,29 @@ import {
EmptyStateIcon,
EmptyStateTitle,
IconButton,
- NamespaceIcon,
+ NavBar,
+ NavBarContent,
+ NavBarActions,
+ NavBarTitle,
+ NavBarVersion,
+ PanelGroup,
+ Workspace,
+ WorkspaceContent,
} from "@/components";
-import {
- DatabaseIcon,
- DetailsIcon,
- EmptyWidgetIcon,
- ExpandGraphIcon,
- FilterIcon,
- GraphIcon,
- SearchIcon,
-} from "@/components/icons";
+import { DatabaseIcon, EmptyWidgetIcon, GraphIcon } from "@/components/icons";
import GridIcon from "@/components/icons/GridIcon";
-import Workspace, { SidebarButton } from "@/components/Workspace";
import {
DEFAULT_TABLE_VIEW_HEIGHT,
useConfiguration,
- useSidebar,
useTableViewSize,
useViewToggles,
} from "@/core";
-import { totalFilteredCount } from "@/core/StateProvider/filterCount";
-import useTranslations from "@/hooks/useTranslations";
-import { EdgesStyling, EdgeStyleDialog } from "@/modules/EdgesStyling";
-import EntitiesFilter from "@/modules/EntitiesFilter";
+import { EdgeStyleDialog } from "@/modules/EdgesStyling";
import EntitiesTabular from "@/modules/EntitiesTabular/EntitiesTabular";
-import EntityDetails from "@/modules/EntityDetails";
-import Namespaces from "@/modules/Namespaces/Namespaces";
-import NodeExpand from "@/modules/NodeExpand";
-import { NodesStyling, NodeStyleDialog } from "@/modules/NodesStyling";
+import { NodeStyleDialog } from "@/modules/NodesStyling";
import { LABELS } from "@/utils/constants";
-import { SearchSidebarPanel } from "@/modules/SearchSidebar";
import GraphViewer from "@/modules/GraphViewer";
-import { useAtomValue } from "jotai";
+import { Sidebar } from "./Sidebar";
const RESIZE_ENABLE_TOP = {
top: true,
@@ -61,9 +49,6 @@ const RESIZE_ENABLE_TOP = {
const GraphExplorer = () => {
const config = useConfiguration();
- const t = useTranslations();
-
- const filteredEntitiesCount = useAtomValue(totalFilteredCount);
const {
isGraphVisible,
@@ -72,35 +57,40 @@ const GraphExplorer = () => {
toggleTableVisibility,
} = useViewToggles();
- const { activeSidebarItem, toggleSidebar, shouldShowNamespaces } =
- useSidebar();
-
const [tableViewHeight, setTableViewHeight] = useTableViewSize();
return (
-
-
-
- {__GRAPH_EXP_VERSION__}
-
-
- }
- onClick={toggleGraphVisibility}
+
+
+
- }
- onClick={toggleTableVisibility}
- />
-
+
+
+
+ {__GRAPH_EXP_VERSION__}
+
+
+ }
+ onClick={toggleGraphVisibility}
+ />
+ }
+ onClick={toggleTableVisibility}
+ />
+
+
{
Open Connections
-
-
+
+
-
-
-
-
-
-
-
- All Views Hidden
-
- To view your graph data show the graph view or table view
-
-
-
-
-
-
-
-
-
-
-
-
-
- setTableViewHeight(delta.height)
- }
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+ All Views Hidden
+
+ To view your graph data show the graph view or table view
+
+
+
+
+
+
+
+
+
+
+
+
+
+ setTableViewHeight(delta.height)
+ }
+ >
+
+
+
+
-
- }
- onPressedChange={() => toggleSidebar("search")}
- pressed={activeSidebarItem === "search"}
- />
- }
- onPressedChange={() => toggleSidebar("details")}
- pressed={activeSidebarItem === "details"}
- />
- }
- onPressedChange={() => toggleSidebar("filters")}
- badge={filteredEntitiesCount > 0}
- pressed={activeSidebarItem === "filters"}
- />
- }
- onPressedChange={() => toggleSidebar("expand")}
- pressed={activeSidebarItem === "expand"}
- />
- }
- onPressedChange={() => toggleSidebar("nodes-styling")}
- pressed={activeSidebarItem === "nodes-styling"}
- />
- }
- onPressedChange={() => toggleSidebar("edges-styling")}
- pressed={activeSidebarItem === "edges-styling"}
- />
- {shouldShowNamespaces && (
- }
- onPressedChange={() => toggleSidebar("namespaces")}
- pressed={activeSidebarItem === "namespaces"}
- />
- )}
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
);
};
diff --git a/packages/graph-explorer/src/routes/GraphExplorer/Sidebar.tsx b/packages/graph-explorer/src/routes/GraphExplorer/Sidebar.tsx
new file mode 100644
index 000000000..f92816335
--- /dev/null
+++ b/packages/graph-explorer/src/routes/GraphExplorer/Sidebar.tsx
@@ -0,0 +1,256 @@
+import { cn } from "@/utils";
+import {
+ useState,
+ type ComponentPropsWithRef,
+ type PropsWithChildren,
+} from "react";
+import { Resizable } from "re-resizable";
+import { Tabs as TabsPrimitive } from "radix-ui";
+import {
+ CLOSED_SIDEBAR_WIDTH,
+ DEFAULT_SIDEBAR_WIDTH,
+ useSidebar,
+ useSidebarSize,
+ type SidebarItems,
+} from "@/core";
+import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/Tooltip";
+import {
+ DetailsIcon,
+ EdgeIcon,
+ ExpandGraphIcon,
+ FilterIcon,
+ GraphIcon,
+ NamespaceIcon,
+ SearchIcon,
+} from "@/components";
+import { SearchSidebarPanel } from "@/modules/SearchSidebar";
+import EntityDetails from "@/modules/EntityDetails";
+import NodeExpand from "@/modules/NodeExpand";
+import EntitiesFilter from "@/modules/EntitiesFilter";
+import { NodesStyling } from "@/modules/NodesStyling";
+import { EdgesStyling } from "@/modules/EdgesStyling";
+import Namespaces from "@/modules/Namespaces/Namespaces";
+import { useAtomValue } from "jotai";
+import { totalFilteredCount } from "@/core/StateProvider/filterCount";
+import { useTranslations } from "@/hooks";
+
+export function Sidebar({
+ className,
+ ...props
+}: ComponentPropsWithRef
) {
+ const t = useTranslations();
+ const filteredEntitiesCount = useAtomValue(totalFilteredCount);
+ const { shouldShowNamespaces, activeSidebarItem } = useSidebar();
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 0}
+ >
+
+
+
+
+
+
+
+
+ {shouldShowNamespaces && (
+
+
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
+
+function ResizableSidebar({ children }: PropsWithChildren) {
+ const { isSidebarOpen } = useSidebar();
+ const [sidebarWidth, setSidebarWidth] = useSidebarSize();
+
+ // The transition animation used for opening and closing sidebar animation
+ // does not play well with the resizing behavior of the Resizable component.
+ // If the animation is not disabled, the resize will feel jerky.
+ const [enableAnimation, setEnableAnimation] = useState(true);
+
+ return (
+ setEnableAnimation(false)}
+ onResizeStop={(_e, _direction, _ref, delta) => {
+ setEnableAnimation(true);
+ setSidebarWidth(delta.width);
+ }}
+ className={cn(
+ enableAnimation &&
+ "transition-width min-h-0 transform duration-200 ease-in-out",
+ )}
+ >
+ {children}
+
+ );
+}
+
+function SidebarTabs({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+function SidebarTabsList({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+function SidebarTabsTrigger({
+ className,
+ title,
+ badge,
+ children,
+ value,
+ ...props
+}: React.ComponentProps & {
+ title: string;
+ badge?: boolean;
+}) {
+ const { toggleSidebar } = useSidebar();
+
+ const handleClick = () => {
+ toggleSidebar(value as SidebarItems);
+ };
+
+ return (
+
+
+
+
+
+ {children}
+ {title}
+
+
+
+ {title}
+
+
+ );
+}
+
+function SidebarTabsContent({
+ className,
+ ...props
+}: React.ComponentProps) {
+ return (
+
+ );
+}
+
+function BadgeIndicator({
+ children,
+ value,
+ ...props
+}: React.ComponentPropsWithoutRef<"div"> & { value?: boolean }) {
+ return (
+
+ {children}
+ {value ? (
+
+ ) : null}
+
+ );
+}
diff --git a/packages/graph-explorer/src/routes/Settings/SettingsRoot.tsx b/packages/graph-explorer/src/routes/Settings/SettingsRoot.tsx
index 07f028666..bf987cdf5 100644
--- a/packages/graph-explorer/src/routes/Settings/SettingsRoot.tsx
+++ b/packages/graph-explorer/src/routes/Settings/SettingsRoot.tsx
@@ -1,10 +1,17 @@
-import Workspace from "@/components/Workspace/Workspace";
import {
buttonStyles,
DatabaseIcon,
ForwardIcon,
+ NavBar,
+ NavBarContent,
+ NavBarActions,
+ NavBarTitle,
+ NavBarVersion,
Panel,
PanelContent,
+ PanelGroup,
+ Workspace,
+ WorkspaceContent,
} from "@/components";
import { Link, NavLink, Outlet, type To } from "react-router";
import { type PropsWithChildren, Suspense } from "react";
@@ -15,12 +22,13 @@ import { LABELS } from "@/utils/constants";
export default function SettingsRoot() {
return (
-
-
-
- {__GRAPH_EXP_VERSION__}
-
-
+
+
+
+
+
+
+ {__GRAPH_EXP_VERSION__}
Open Connections
-
-
-
-
-
-
-
-
-
-
- }>
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+ }>
+
+
+
+
+
+
);
}