react-splitkit
API Reference

TabList

Headless tab bar component with keyboard navigation and ARIA built in.

TabList renders the tab bar for a single panel. It is fully headless — you supply the markup for each tab via renderTab. Keyboard navigation (←/→, Home/End, Delete), roving tabindex, and ARIA roles are handled automatically.

import { TabList } from 'react-splitkit';
 
<TabList
  panelId={panel.id}
  className="flex h-9 border-b"
  renderTab={({ tab, isActive, tabProps, label, closable, close }) => (
    <button
      {...tabProps}
      type="button"
      className={isActive ? 'font-bold px-3' : 'px-3'}
    >
      {label}
      {closable && (
        <span onClick={(e) => { e.stopPropagation(); close(); }}>×</span>
      )}
    </button>
  )}
/>

Props

panelId (required)

panelId: string

The ID of the panel this tab list belongs to. Must match a PanelNode id in the layout tree.


renderTab (required)

renderTab: (props: RenderTabProps) => ReactNode

Called once per tab in the panel. Render whatever markup you want — just spread tabProps onto your interactive element.

interface RenderTabProps {
  tab: TabDescriptor;        // the raw tab data (id, tabType, title, meta…)
  isActive: boolean;         // whether this tab is currently selected
  tabProps: {
    role: 'tab';
    id: string;              // DOM id — linked to the TabPanel via aria-controls
    tabIndex: 0 | -1;        // roving tabindex (0 = focusable, -1 = skip)
    'aria-selected': boolean;
    'aria-controls': string; // points to the matching tabpanel element
    onClick: () => void;
    onKeyDown: (e: KeyboardEvent) => void;
  };
  label: ReactNode;          // from registry.renderLabel or tab.title
  closable: boolean;         // from registry.closable or tab.closable (default true)
  close: () => void;         // removes this tab from the panel
}

Always spread tabProps — it carries the ARIA attributes, click handler, and keyboard handler that make the tab bar accessible.


leading

leading?: ReactNode

Slot rendered before the tab items — useful for a "new tab" button or a panel icon:

<TabList
  panelId={panel.id}
  leading={<AddTabButton panelId={panel.id} />}
  renderTab={...}
/>

trailing

trailing?: ReactNode

Slot rendered after the tab items — useful for a "more options" menu or close-panel button:

<TabList
  panelId={panel.id}
  trailing={<MoreMenu panelId={panel.id} />}
  renderTab={...}
/>

aria-label

'aria-label'?: string
// default: 'Tabs'

Accessible label for the role="tablist" container. When multiple panels exist on the same page, give each tablist a unique label so screen readers can distinguish them:

<TabList
  panelId={panel.id}
  aria-label={`${panel.id} tabs`}
  renderTab={...}
/>

className / style

Applied to the role="tablist" container div.


Keyboard navigation

KeyAction
/ Focus previous tab
/ Focus next tab
HomeFocus first tab
EndFocus last tab
DeleteClose focused tab (if closable)

See Keyboard reference for the full map.

On this page