react-splitkit
API Reference

TabPanel

Renders the content area for the active tab in a panel.

TabPanel renders the content region for a panel's tabs. By default it only mounts the active tab's content. The mode prop lets you keep all tab contents mounted (hidden but in the DOM) to preserve local state across tab switches.

import { TabPanel } from 'react-splitkit';
 
<TabPanel
  panelId={panel.id}
  style={{ position: 'absolute', inset: 0 }}
  className="flex flex-col"
/>

Props

panelId (required)

panelId: string

ID of the panel whose active tab content should be rendered.


mode

mode?: 'mount-all-hide-inactive'
// default: undefined (only active tab is mounted)

Controls the mounting strategy for tab content:

ModeBehaviourWhen to use
undefined (default)Only the active tab's content is mounted and rendered. Switching tabs unmounts the previous content.Stateless content, registry-driven renders, most cases.
'mount-all-hide-inactive'All tab contents are mounted on first activation. Inactive tabs are hidden (display: none) but stay in the DOM.When tabs hold stateful content (a code editor with cursor position, a video, scroll offset) that you don't want reset on tab switch.
<TabPanel
  panelId={panel.id}
  mode="mount-all-hide-inactive"
  style={{ position: 'absolute', inset: 0 }}
/>

renderContent

renderContent?: (tab: TabDescriptor, ctx: TabRenderContext) => ReactNode

Override the default render path (looking up registry[tab.tabType].render). Useful when a single panel needs custom handling for specific tab types:

<TabPanel
  panelId={panel.id}
  style={{ position: 'absolute', inset: 0 }}
  renderContent={(tab, ctx) => {
    if (tab.tabType === 'new-tab') {
      return <NewTabChooser panelId={ctx.panelId} placeholderId={tab.id} />;
    }
    return registry[tab.tabType]?.render(tab, ctx) ?? null;
  }}
/>

TabRenderContext contains { panelId: string }.


className / style

Applied to each individual tab content wrapper. Use style with position: absolute; inset: 0 when the panel uses a relative-positioned container — this is the standard pattern for filling the panel body:

<div className="flex-1 min-h-0 relative">
  <TabPanel
    panelId={panel.id}
    style={{ position: 'absolute', inset: 0 }}
    className="flex flex-col overflow-hidden"
  />
</div>

ARIA

Each tab content region receives:

  • role="tabpanel"
  • aria-labelledby pointing to its corresponding tab button
  • A unique id used by the tab button's aria-controls

These ids are auto-prefixed per LayoutProvider instance so multiple providers on the same page never produce duplicates.

On this page