How Chat2DB Manages Its User Interface: React, Zustand, and Ant Design

Chat2DB manages its user interface through a centralized Zustand store, React component hierarchy, and Ant Design theming, with all UI state persisted to local storage for a seamless cross-session experience.

Chat2DB is an open-source database management tool built by OtterMind as a modern React single-page application. The user interface architecture combines the Umi framework for routing, Ant Design for components, and Zustand for state management. This setup allows the application to maintain consistent theming, resizable layouts, and synchronized navigation across database chat, BI visualization, and table editing features.

Core Architecture of the Chat2DB User Interface

The interface follows a hierarchical component structure anchored by global layout containers and split-pane workspaces.

Technology Stack and Framework

The frontend is built on React with Umi handling route-based code splitting. Ant Design provides the underlying UI components, while Zustand (via useGlobalStore) manages cross-cutting concerns like theme preferences, panel widths, and shortcut configurations. All user interface settings are automatically persisted to browser local storage using Zustand's persistence middleware.

Layout Hierarchy

The top-level GlobalLayout component (chat2db-community-client/src/layouts/GlobalLayout/index.tsx) wraps the entire application. It injects the Ant Design ConfigProvider, renders the custom AppTheme wrapper, and displays a loading state while checking backend service status. Routed content renders inside this layout via Umi's <Outlet />.

Beneath the global wrapper sits the Workspace component (chat2db-community-client/src/pages/main/workspace/index.tsx), which implements a resizable split-pane layout using react-split-pane. This divides the screen into left and right panels whose widths are synchronized with the workspace store.

Global State Management for UI Consistency

All user interface state lives in a Zustand store defined in chat2db-community-client/src/store/global/store.ts.

Store Structure and Selectors

The store is organized into logical slices (common, settings, request, misc, hotUpdate). Components access UI settings through selectors like settingSelectors.currentBaseSetting, which extracts primaryColor, appearance, customFont, and customFontSize.

import { useGlobalStore } from '@/store/global';
import { settingSelectors } from '@/store/global/selectors';

const { appearance, primaryColor } = useGlobalStore(state => ({
  ...settingSelectors.currentBaseSetting(state),
}));

Persistence Strategy

UI preferences are persisted using zustand/middleware with a storage key defined by runtimeEditionConfig.globalStoreName. Only specific fields—mainPageActiveTab, loginType, baseSetting, and panel widths—are written to local storage, ensuring the user interface restores exactly as the user left it.

Theming and Dynamic Layout Components

AppTheme and Runtime Theming

The AppTheme component (chat2db-community-client/src/components/AppTheme/index.tsx) wraps Ant Design's ThemeProvider. It reads the current theme configuration from the global store and applies primaryColor, appearance (dark/light), and customFont settings without requiring a page reload. This enables instant theme switching across the entire user interface.

Resizable Workspace Panels

The workspace implements draggable splitters using SplitPane. Panel widths are stored in the workspace store (chat2db-community-client/src/store/workspace/store.ts) under panelLeftWidth. When users resize panels, the new dimensions propagate through the store and persist across sessions.

import SplitPane from 'react-split-pane';
import { useWorkspaceStore } from '@/store/workspace';

const WorkspaceLayout = () => {
  const { panelLeftWidth, setPanelLeftWidth } = useWorkspaceStore(s => ({
    panelLeftWidth: s.layout.panelLeftWidth,
    setPanelLeftWidth: s.setPanelLeftWidth,
  }));
  const [size, setSize] = React.useState(panelLeftWidth);

  return (
    <SplitPane
      split="vertical"
      size={size}
      minSize={200}
      onChange={(newSize) => {
        setSize(newSize);
        setPanelLeftWidth(newSize);
      }}
    >
      <WorkspaceLeft />
      <WorkspaceRight />
    </SplitPane>
  );
};

Theme Toggling Implementation

Components can modify the user interface theme by dispatching actions from the settings slice. This updates the global store and triggers a re-render of AppTheme with new Ant Design tokens.

import { useGlobalStore } from '@/store/global';
import { settingActions } from '@/store/global/slices/settings/action';

const ThemeToggle = () => {
  const setAppearance = useGlobalStore(state => settingActions.setAppearance(state));
  const current = useGlobalStore(state => state.baseSetting.appearance);

  const toggle = () => {
    setAppearance(current.includes('dark') ? 'light' : 'dark');
  };

  return <Button onClick={toggle}>Toggle Theme</Button>;
};

Feature Modules and Component Organization

Feature-specific user interface sections—such as Chat, BI, and TableEditor—are organized as lazy-loaded modules under src/pages/main/. Each module self-manages its internal state while consuming the global store for shared settings.

The chat interface (chat2db-community-client/src/pages/main/chat/index.tsx) demonstrates this pattern: it renders ChatHeader, ChatMessage, and ChatInput components while accessing global theme settings and workspace configurations from Zustand. This modular approach allows the user interface to load features on demand while maintaining visual consistency.

Summary

  • Chat2DB builds its user interface as a React SPA using Umi for routing and Ant Design for component primitives.
  • Zustand (useGlobalStore) centrally manages UI state including themes, fonts, and layout dimensions in chat2db-community-client/src/store/global/store.ts.
  • GlobalLayout and Workspace components provide the structural foundation with resizable split panes that persist their state via the workspace store.
  • AppTheme enables runtime theme switching by reading from the global store and wrapping Ant Design's ThemeProvider.
  • All user interface preferences are automatically persisted to local storage, ensuring a consistent experience across browser sessions.

Frequently Asked Questions

How does Chat2DB handle dark mode and custom themes?

Chat2DB implements runtime theme switching through the AppTheme component in chat2db-community-client/src/components/AppTheme/index.tsx. This component extracts appearance, primaryColor, and font settings from the Zustand global store and passes them to Ant Design's ThemeProvider. When users toggle themes via settingActions.setAppearance, the store updates instantly and the UI re-renders without reloading the page.

Where is the user interface state stored in Chat2DB?

All global UI state resides in the Zustand store defined at chat2db-community-client/src/store/global/store.ts. The store uses zustand/persist middleware to write specific fields—such as active tabs, theme preferences, and panel widths—to the browser's local storage under a key defined by runtimeEditionConfig.globalStoreName.

How are the resizable panels in the Chat2DB workspace implemented?

The workspace uses react-split-pane inside chat2db-community-client/src/pages/main/workspace/index.tsx. The splitter width is bound to panelLeftWidth in the workspace slice of the Zustand store (chat2db-community-client/src/store/workspace/store.ts). When users drag the splitter, the component calls setPanelLeftWidth to update the store, which both re-renders the UI and persists the new size for future sessions.

What framework does Chat2DB use for routing and layout?

Chat2DB uses the Umi framework to handle routing and layout. The GlobalLayout component serves as the root layout wrapper in chat2db-community-client/src/layouts/GlobalLayout/index.tsx, rendering a <Outlet /> where Umi injects route-matched components. This architecture enables code splitting and modular feature loading while maintaining consistent global UI elements like the title bar and theme provider.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →