# All files / src/components/agents AgentTabBar.tsx

0% Statements 0/64
100% Branches 1/1
100% Functions 1/1
0% Lines 0/64

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99

     /**
     * AgentTabBar — presentational tab bar for the agent detail page (#1419).
     * Renders Chat / Sessions / Schedules / Settings tabs, reusing AppNav styling.
     *
     * @module
     */

    import { useRef, type JSX, type KeyboardEvent } from "react";
    import { Activity, CalendarClock, MessageSquare, Settings } from "lucide-react";
    import { useAppNavigate, agentUrl, type AgentTab } from "../../utils/navigation.js";
    import navStyles from "../layout/AppNav.module.scss";

    const ICON_SIZE: number = 18;

    interface AgentTabDef {
      id: AgentTab;
      label: string;
      icon: JSX.Element;
    }

    const AGENT_TABS: AgentTabDef[] = [
      { id: "chat", label: "Chat", icon: <MessageSquare size={ICON_SIZE} /> },
      { id: "sessions", label: "Sessions", icon: <Activity size={ICON_SIZE} /> },
      { id: "schedules", label: "Schedules", icon: <CalendarClock size={ICON_SIZE} /> },
      { id: "settings", label: "Settings", icon: <Settings size={ICON_SIZE} /> },
    ];

    /** Props for {@link AgentTabBar}. */
    export interface AgentTabBarProps {
      /** The agent whose tabs are being rendered. */
      agentId: string;
      /** Which tab is currently active. */
      activeTab: AgentTab;
    }

    /** Horizontal tab bar for navigating between agent detail views. */
    export function AgentTabBar({ agentId, activeTab }: AgentTabBarProps): JSX.Element {
      const navigate = useAppNavigate();
      const navRef = useRef<HTMLElement>(null);

      const handleKeyDown = (e: KeyboardEvent<HTMLElement>): void => {
        const buttons = navRef.current?.querySelectorAll<HTMLButtonElement>('[role="tab"]');
        if (!buttons || buttons.length === 0) return;

        const currentIndex = AGENT_TABS.findIndex((t) => t.id === activeTab);
        let nextIndex = currentIndex;

        if (e.key === "ArrowRight" || e.key === "ArrowDown") {
          e.preventDefault();
          nextIndex = (currentIndex + 1) % AGENT_TABS.length;
        } else if (e.key === "ArrowLeft" || e.key === "ArrowUp") {
          e.preventDefault();
          nextIndex = (currentIndex - 1 + AGENT_TABS.length) % AGENT_TABS.length;
        } else if (e.key === "Home") {
          e.preventDefault();
          nextIndex = 0;
        } else if (e.key === "End") {
          e.preventDefault();
          nextIndex = AGENT_TABS.length - 1;
        } else {
          return;
        }

        const nextTab = AGENT_TABS[nextIndex];
        navigate(agentUrl(agentId, nextTab.id));
        buttons[nextIndex].focus();
      };

      return (
        <nav
          ref={navRef}
          className={navStyles.nav}
          role="tablist"
          aria-label="Agent navigation"
          aria-orientation="horizontal"
          onKeyDown={handleKeyDown}
          data-testid="agent-tab-bar"
        >
          {AGENT_TABS.map((tab) => {
            const isActive = tab.id === activeTab;
            return (
              <button
                key={tab.id}
                role="tab"
                aria-selected={isActive}
                tabIndex={isActive ? 0 : -1}
                className={`${navStyles.tab} ${isActive ? navStyles.tabActive : ""}`}
                onClick={() => navigate(agentUrl(agentId, tab.id))}
                data-testid={`agent-tab-${tab.id}`}
              >
                <span className={navStyles.tabIcon}>{tab.icon}</span>
                <span className={navStyles.tabLabel}>{tab.label}</span>
              </button>
            );
          })}
        </nav>
      );
    }