Tabs

One panel at a time out of several, each with its own heading. Different content per tab, which is what separates it from a Segmented.

Code

Tabs is installed into your project as a file you own. It takes the same props as Ant Design v6's Tabs, plus three more type values, a color and a ref. Both added props are marked antuikit in the API table.
Three changes do not show in the props table: the bar is neutral rather than primary by default, small also shrinks the label, and the overflow icon comes from the icon pack.

Install

npx antuikit@latest init
npx antuikit@latest add tabs
The first command installs AntuikitProvider and the theme tokens, the second adds this component.
Tabs brings in icon for its overflow icon.

Import

From @/components/ui/tabs, never from antd. The file lives in your project, so the import is a path, not a package.
import { Tabs } from "@/components/ui/tabs"
Declare tabs with items. Tabs.TabPane children are deprecated and warn.
1
<Tabs
2
defaultActiveKey="overview"
3
items={[
4
{ key: "overview", label: "Overview", children: <Overview /> },
5
{ key: "activity", label: "Activity", children: <Activity /> },
6
{ key: "settings", label: "Settings", children: <Settings />, disabled: true },
7
]}
8
/>

The axes

The props that take a value from a set, and what each value changes.
  • type takes antd's line (the default), card and editable-card, plus the kit's floating, padded and docked. Each addition is a line bar with a hover highlight: floating highlights the label, padded the padded tab, and docked the whole tab down to the rail.
  • color takes default and primary. default paints the indicator and the selected, hovered and pressed labels in the text color instead of the primary color. primary keeps antd's own look, and on the kit's three types it tints the hover highlight. Under either value a resting label uses the secondary text color, so the selected label reads as a step up. A disabled label keeps antd's own color.
  • size takes small, medium and large and applies to the bar, not the panel. middle is v5's spelling of medium and still typechecks. The kit also sets small labels in the small font size.
  • tabPlacement takes top, end, bottom and start, which follow the reading direction, so a bar mirrors under rtl on its own. It replaces tabPosition, whose values are top, right, bottom and left, so change the values when you migrate.
color replaces the inert HTML color attribute, so it never reaches the root element.
1
<Tabs type="docked" color="primary" size="small" tabPlacement="start" items={items} />

Flags

Each of these turns one behavior on, and each works as in Ant Design.
  • centered centers the tab list inside the bar.
  • hideAdd removes the built-in plus button. It only matters under editable-card: other types have no plus button to hide.
  • destroyOnHidden unmounts an inactive panel instead of hiding it. It works on the Tabs and on an individual item, and the value on the Tabs wins where both are set. An item's forceRender is the opposite lever: it mounts a panel before its tab is ever activated.
  • animated is a boolean or { inkBar, tabPane } and defaults to { inkBar: true, tabPane: false }: the indicator slides, panels do not cross-fade. animated={true} turns the panel motion on, animated={false} turns both off.

Slots

The props that take a node. Reach for them before a descendant selector.
  • addIcon and removeIcon come from AntuikitProvider, and your prop wins over them.
  • A ConfigProvider tabs.moreIcon wins over the moreIcon prop. antd reads the provider first for that one icon, so set it in one place. The kit's default is on the prop, so either one replaces it.
  • tabBarExtraContent takes a single node, which lands at the end, or an object with left and right, which swap sides in right-to-left layouts, so treat them as start and end.
  • renderTabBar hands you the bar's props and the default DefaultTabBar, so you can wrap the real bar rather than rebuild it. That is how a sticky tab bar is built, and rebuilding instead costs you the roving tabindex and the arrow-key handling.
  • An item's icon and label both take nodes. Keep a glyph in icon: the gap between icon and label only applies to the icon slot.

Events

  • onChange(activeKey) fires only when the active tab actually changes. Pair it with activeKey for the controlled form; defaultActiveKey is the uncontrolled one, and with neither the first item wins.
  • onTabClick(key, event) fires on every activation, including a click on the tab that is already active. That is the hook for “scroll the panel back to the top”, not onChange.
  • onEdit(target, action): target is the tab key for remove and the click event for add. It does not change the selection, so removing the active tab in a controlled bar means setting a new activeKey yourself.
  • onTabScroll({ direction }) fires when the overflowing list scrolls. It replaces onPrevClick and onNextClick, which warn.

Styling

classNames and styles take the same keys, one per part. Use them before a descendant selector: a part with a key keeps its name across versions.
1
<Tabs
2
classNames={{
3
root: "…",
4
item: "…",
5
remove: "…",
6
indicator: "…",
7
body: "…",
8
content: "…",
9
header: "…",
10
popup: {
11
root: "…",
12
},
13
}}
14
/>
Style the overflow menu through classNames.popup.root. The menu renders outside the tabs, so selectors written on the Tabs do not reach it. Inside it, the list is .ant-tabs-dropdown-menu, not .ant-dropdown-menu. It replaces the deprecated popupClassName.
indicator takes { size, align }, where size is a number or a function of the label width and align is start, center or end (logical, so it mirrors in RTL). It supersedes the deprecated indicatorSize. type="docked" sets a default size that spans the icon and label, and follows compact mode. Any key you set in your own indicator wins.

API Reference

Tabs
Tabs's props. Rows marked antuikit in the Version column are added by the kit.
TabItemType
The fields of an entry in items.
MoreProps
The fields of more, besides any Dropdown prop.