Portal Community

TabDescriptor Interface

// flow-observer-core/src/types/panel.types.ts
export interface TabDescriptor {
  id: string;                        // unique key, e.g. 'execution-status'
  label: string;                     // display name in tab bar
  icon?: string;                     // Font Awesome class, e.g. 'fa-solid fa-circle-check'
  component: React.ComponentType;    // the tab's React component
  badge?: number | null;             // numeric badge shown on the tab (e.g. pending HIL count)
  order?: number;                    // display order (lower = leftmost)
  isVisible?: boolean;               // hide without unregistering (default: true)
  onActivate?: () => void;           // called when user switches to this tab
  onDeactivate?: () => void;         // called when user switches away
}

Built-In Tab IDs

IDLabelOrderBadge
execution-statusExecution Status10None
node-listNode List20None
logsLogs30Unread error count
node-inspectorNode Inspector40None
log-detailLog Detail50None (hidden by default)

TabBar Component

The TabBar component renders the horizontal list of tabs from the current registered tab list. It reads from flowObserverPanelStore.tabs and calls engine.activateTab(id) on click:

// TabBar.tsx (simplified)
export function TabBar() {
  const { tabs, activeTabId } = useFlowObserverPanelStore();
  const engine = useFlowObserverPanelEngine();

  return (
    <div className="tab-bar">
      {tabs
        .filter(t => t.isVisible !== false)
        .sort((a, b) => (a.order ?? 99) - (b.order ?? 99))
        .map(tab => (
          <button
            key={tab.id}
            className={tab.id === activeTabId ? 'active' : ''}
            onClick={() => engine.activateTab(tab.id)}
          >
            {tab.icon && <i className={tab.icon} />}
            {tab.label}
            {tab.badge != null && <span className="badge">{tab.badge}</span>}
          </button>
        ))}
    </div>
  );
}

Programmatic Tab Switching

Any component can switch the active tab by calling the engine directly:

// Clicking a node in the Node List tab opens the Node Inspector
const engine = useFlowObserverPanelEngine();
engine.activateTab('node-inspector');

// Or via the store directly
flowObserverPanelStore.getState().setActiveTabId('node-inspector');
Log Detail Tab Auto-Navigate The Log Detail tab is hidden by default (isVisible: false). It becomes visible when the user clicks "Expand" on a log entry in the Logs tab. The engine calls engine.activateTab('log-detail') and sets the selected log entry in the store before switching.