0
# Advanced Features
1
2
Extended functionality including extra content, dropdown overflow, custom rendering, and responsive behavior. These features enable sophisticated tab interfaces for complex applications and unique use cases.
3
4
## Capabilities
5
6
### Extra Content in Tab Bar
7
8
Additional content areas within the tab bar for actions, information, or custom controls.
9
10
```typescript { .api }
11
/**
12
* Extra content configuration for tab bar areas
13
* Content can be placed on left or right side of tabs
14
*/
15
type TabBarExtraContent = React.ReactNode | TabBarExtraMap;
16
17
/**
18
* Map defining content for specific positions in tab bar
19
*/
20
type TabBarExtraMap = Partial<Record<TabBarExtraPosition, React.ReactNode>>;
21
22
/**
23
* Available positions for extra content
24
*/
25
type TabBarExtraPosition = 'left' | 'right';
26
27
/**
28
* Tab bar styling and layout options
29
*/
30
interface TabBarConfig {
31
/** Extra content in the tab bar */
32
tabBarExtraContent?: TabBarExtraContent;
33
/** Gap between individual tabs in pixels */
34
tabBarGutter?: number;
35
/** Styles for the tab bar container */
36
tabBarStyle?: React.CSSProperties;
37
}
38
```
39
40
**Usage Examples:**
41
42
```typescript
43
import Tabs from "rc-tabs";
44
import { Button, Badge, Avatar } from "antd";
45
46
// Simple extra content
47
function TabsWithExtraContent() {
48
return (
49
<Tabs
50
items={tabItems}
51
tabBarExtraContent={
52
<Button type="primary" size="small">
53
Action
54
</Button>
55
}
56
/>
57
);
58
}
59
60
// Positioned extra content
61
function TabsWithPositionedContent() {
62
return (
63
<Tabs
64
items={tabItems}
65
tabBarExtraContent={{
66
left: (
67
<div style={{ marginRight: 16 }}>
68
<Badge count={5}>
69
<Avatar icon="user" />
70
</Badge>
71
</div>
72
),
73
right: (
74
<div>
75
<Button size="small" style={{ marginRight: 8 }}>
76
Save
77
</Button>
78
<Button size="small" type="primary">
79
Publish
80
</Button>
81
</div>
82
),
83
}}
84
/>
85
);
86
}
87
88
// Dynamic extra content
89
function DynamicExtraContent() {
90
const [hasUnsavedChanges, setHasUnsavedChanges] = useState(false);
91
92
return (
93
<Tabs
94
items={tabItems}
95
tabBarExtraContent={
96
hasUnsavedChanges ? (
97
<Badge status="warning" text="Unsaved changes" />
98
) : (
99
<Badge status="success" text="All saved" />
100
)
101
}
102
/>
103
);
104
}
105
```
106
107
### Overflow Handling and More Dropdown
108
109
Automatic handling of tab overflow with customizable dropdown for collapsed tabs.
110
111
```typescript { .api }
112
/**
113
* Configuration for overflow tabs dropdown
114
*/
115
interface MoreProps extends Omit<DropdownProps, 'children'> {
116
/** Custom icon for the more dropdown trigger */
117
icon?: React.ReactNode;
118
}
119
120
/**
121
* Dropdown properties from rc-dropdown
122
* Controls behavior of overflow tabs menu
123
*/
124
interface DropdownProps {
125
/** Dropdown trigger type */
126
trigger?: Array<'click' | 'hover' | 'contextMenu'>;
127
/** Dropdown placement */
128
placement?: 'topLeft' | 'topCenter' | 'topRight' | 'bottomLeft' | 'bottomCenter' | 'bottomRight';
129
/** Whether dropdown is visible */
130
visible?: boolean;
131
/** Custom dropdown container */
132
getPopupContainer?: (triggerNode: HTMLElement) => HTMLElement;
133
/** Dropdown overlay class name */
134
overlayClassName?: string;
135
/** Dropdown overlay style */
136
overlayStyle?: React.CSSProperties;
137
}
138
```
139
140
**Overflow Examples:**
141
142
```typescript
143
import { MoreOutlined, EllipsisOutlined } from "@ant-design/icons";
144
145
// Basic overflow handling
146
function TabsWithOverflow() {
147
const manyTabs = Array.from({ length: 20 }, (_, i) => ({
148
key: `tab-${i + 1}`,
149
label: `Tab ${i + 1}`,
150
children: <div>Content for tab {i + 1}</div>,
151
}));
152
153
return (
154
<Tabs
155
items={manyTabs}
156
more={{
157
icon: <MoreOutlined />,
158
trigger: ['click'],
159
}}
160
/>
161
);
162
}
163
164
// Custom overflow dropdown
165
function CustomOverflowTabs() {
166
return (
167
<Tabs
168
items={manyTabs}
169
more={{
170
icon: <EllipsisOutlined />,
171
trigger: ['hover'],
172
placement: 'bottomRight',
173
overlayClassName: 'custom-tabs-dropdown',
174
}}
175
getPopupContainer={(node) => node.parentElement || document.body}
176
/>
177
);
178
}
179
180
// Responsive overflow behavior
181
function ResponsiveOverflowTabs() {
182
const [containerWidth, setContainerWidth] = useState(800);
183
184
return (
185
<div style={{ width: containerWidth }}>
186
<input
187
type="range"
188
min="300"
189
max="1200"
190
value={containerWidth}
191
onChange={(e) => setContainerWidth(Number(e.target.value))}
192
/>
193
<Tabs
194
items={manyTabs}
195
more={{
196
icon: <span>···</span>,
197
}}
198
/>
199
</div>
200
);
201
}
202
```
203
204
### Custom Tab Bar Rendering
205
206
Complete customization of tab bar appearance and behavior through render functions.
207
208
```typescript { .api }
209
/**
210
* Custom tab bar render function
211
* Provides complete control over tab bar rendering
212
*/
213
type RenderTabBar = (
214
props: RenderTabBarProps,
215
DefaultTabBar: React.ComponentType<TabNavListProps>
216
) => React.ReactElement;
217
218
/**
219
* Properties passed to custom tab bar render function
220
*/
221
interface RenderTabBarProps {
222
id: string;
223
activeKey: string;
224
animated: AnimatedConfig;
225
tabPosition: TabPosition;
226
rtl: boolean;
227
mobile: boolean;
228
editable: EditableConfig;
229
locale: TabsLocale;
230
more: MoreProps;
231
tabBarGutter: number;
232
onTabClick: (key: string, e: React.MouseEvent | React.KeyboardEvent) => void;
233
onTabScroll: OnTabScroll;
234
extra: TabBarExtraContent;
235
style: React.CSSProperties;
236
}
237
238
/**
239
* Default tab bar component props
240
*/
241
interface TabNavListProps {
242
id: string;
243
tabPosition: TabPosition;
244
activeKey: string;
245
rtl: boolean;
246
animated?: AnimatedConfig;
247
extra?: TabBarExtraContent;
248
editable?: EditableConfig;
249
more?: MoreProps;
250
mobile: boolean;
251
tabBarGutter?: number;
252
className?: string;
253
style?: React.CSSProperties;
254
locale?: TabsLocale;
255
onTabClick: (activeKey: string, e: React.MouseEvent | React.KeyboardEvent) => void;
256
onTabScroll?: OnTabScroll;
257
}
258
```
259
260
**Custom Rendering Examples:**
261
262
```typescript
263
// Wrapped tab bar with additional controls
264
function TabsWithCustomBar() {
265
const renderTabBar = (props: RenderTabBarProps, DefaultTabBar: any) => (
266
<div className="custom-tab-bar-wrapper">
267
<div className="tab-bar-header">
268
<h3>Document Tabs</h3>
269
<Button size="small">Settings</Button>
270
</div>
271
<DefaultTabBar {...props} />
272
</div>
273
);
274
275
return (
276
<Tabs
277
items={tabItems}
278
renderTabBar={renderTabBar}
279
/>
280
);
281
}
282
283
// Completely custom tab bar
284
function TabsWithFullCustomBar() {
285
const [activeKey, setActiveKey] = useState('1');
286
287
const renderTabBar = (props: RenderTabBarProps) => (
288
<div className="custom-tabs-nav">
289
{tabItems.map(item => (
290
<button
291
key={item.key}
292
className={`custom-tab ${activeKey === item.key ? 'active' : ''}`}
293
onClick={(e) => {
294
setActiveKey(item.key);
295
props.onTabClick(item.key, e);
296
}}
297
>
298
{item.label}
299
{activeKey === item.key && <span className="active-indicator" />}
300
</button>
301
))}
302
</div>
303
);
304
305
return (
306
<Tabs
307
activeKey={activeKey}
308
items={tabItems}
309
renderTabBar={renderTabBar}
310
/>
311
);
312
}
313
314
// Conditional tab bar rendering
315
function ConditionalTabBar() {
316
const [isCompact, setIsCompact] = useState(false);
317
318
const renderTabBar = (props: RenderTabBarProps, DefaultTabBar: any) => {
319
if (isCompact) {
320
return (
321
<select
322
value={props.activeKey}
323
onChange={(e) => props.onTabClick(e.target.value, e as any)}
324
>
325
{tabItems.map(item => (
326
<option key={item.key} value={item.key}>
327
{item.label}
328
</option>
329
))}
330
</select>
331
);
332
}
333
334
return <DefaultTabBar {...props} />;
335
};
336
337
return (
338
<Tabs
339
items={tabItems}
340
renderTabBar={renderTabBar}
341
/>
342
);
343
}
344
```
345
346
### Tab Scrolling and Navigation
347
348
Control and respond to tab scrolling behavior in overflow scenarios.
349
350
```typescript { .api }
351
/**
352
* Tab scroll event handler
353
* Fired when tab bar is scrolled horizontally or vertically
354
*/
355
type OnTabScroll = (info: { direction: 'left' | 'right' | 'top' | 'bottom' }) => void;
356
357
/**
358
* Scroll behavior configuration
359
*/
360
interface TabScrollConfig {
361
/** Callback for tab scroll events */
362
onTabScroll?: OnTabScroll;
363
/** Whether to show scroll buttons in overflow */
364
showScrollArrows?: boolean;
365
/** Scroll speed and behavior settings */
366
scrollAnimated?: boolean;
367
}
368
```
369
370
**Scroll Examples:**
371
372
```typescript
373
// Tab scroll monitoring
374
function ScrollMonitoredTabs() {
375
const [scrollInfo, setScrollInfo] = useState('');
376
377
const handleTabScroll = (info: { direction: string }) => {
378
setScrollInfo(`Scrolled ${info.direction} at ${new Date().toLocaleTimeString()}`);
379
};
380
381
return (
382
<div>
383
<div>Scroll Status: {scrollInfo}</div>
384
<Tabs
385
items={manyTabs}
386
onTabScroll={handleTabScroll}
387
/>
388
</div>
389
);
390
}
391
392
// Programmatic tab scrolling
393
function ProgrammaticScrollTabs() {
394
const tabsRef = useRef<HTMLDivElement>(null);
395
396
const scrollToTab = (direction: 'left' | 'right') => {
397
const tabsElement = tabsRef.current?.querySelector('.rc-tabs-nav-wrap');
398
if (tabsElement) {
399
const scrollAmount = 200;
400
tabsElement.scrollBy({
401
left: direction === 'left' ? -scrollAmount : scrollAmount,
402
behavior: 'smooth',
403
});
404
}
405
};
406
407
return (
408
<div>
409
<div>
410
<Button onClick={() => scrollToTab('left')}>← Scroll Left</Button>
411
<Button onClick={() => scrollToTab('right')}>Scroll Right →</Button>
412
</div>
413
<Tabs
414
ref={tabsRef}
415
items={manyTabs}
416
/>
417
</div>
418
);
419
}
420
```
421
422
### Indicator Customization
423
424
Customization of the tab indicator (ink bar) appearance and behavior.
425
426
```typescript { .api }
427
/**
428
* Tab indicator configuration
429
* Controls the visual indicator showing active tab
430
*/
431
interface IndicatorConfig {
432
/** Function to calculate indicator size */
433
size?: GetIndicatorSize;
434
/** Alignment of indicator relative to tab */
435
align?: 'start' | 'center' | 'end';
436
}
437
438
/**
439
* Type for calculating indicator size
440
* Can be a number or function that takes origin size and returns new size
441
*/
442
type GetIndicatorSize = number | ((origin: number) => number);
443
```
444
445
**Indicator Examples:**
446
447
```typescript
448
// Fixed size indicator
449
function FixedSizeIndicatorTabs() {
450
return (
451
<Tabs
452
items={tabItems}
453
indicator={{
454
size: 3, // Fixed 3px indicator height/width
455
align: 'center',
456
}}
457
/>
458
);
459
}
460
461
// Dynamic indicator sizing
462
function DynamicIndicatorTabs() {
463
const calculateSize: GetIndicatorSize = (originalSize) => {
464
// Make indicator 80% of original size
465
return Math.floor(originalSize * 0.8);
466
};
467
468
return (
469
<Tabs
470
items={tabItems}
471
indicator={{
472
size: calculateSize,
473
align: 'center',
474
}}
475
/>
476
);
477
}
478
479
// Responsive indicator based on screen size
480
function ResponsiveIndicatorTabs() {
481
const [indicatorSize, setIndicatorSize] = useState<GetIndicatorSize>(2);
482
483
useEffect(() => {
484
const updateSize = () => {
485
setIndicatorSize(window.innerWidth < 768 ? 2 : 4);
486
};
487
488
updateSize();
489
window.addEventListener('resize', updateSize);
490
return () => window.removeEventListener('resize', updateSize);
491
}, []);
492
493
return (
494
<Tabs
495
items={tabItems}
496
indicator={{
497
size: indicatorSize,
498
align: 'start',
499
}}
500
/>
501
);
502
}
503
```
504
505
### Popup Container Control
506
507
Control where popups and dropdowns are rendered for proper z-index and positioning.
508
509
```typescript { .api }
510
/**
511
* Popup container configuration
512
* Controls where dropdown and popup elements are rendered
513
*/
514
interface PopupConfig {
515
/** Function to get container element for popups */
516
getPopupContainer?: (node: HTMLElement) => HTMLElement;
517
/** CSS class name for popup elements */
518
popupClassName?: string;
519
}
520
```
521
522
**Popup Container Examples:**
523
524
```typescript
525
// Custom popup container
526
function CustomPopupTabs() {
527
return (
528
<div className="tabs-container">
529
<Tabs
530
items={manyTabs}
531
getPopupContainer={(node) => {
532
// Render popups in specific container
533
return document.querySelector('.popup-container') || document.body;
534
}}
535
popupClassName="custom-tabs-popup"
536
more={{
537
icon: <MoreOutlined />,
538
}}
539
/>
540
<div className="popup-container" />
541
</div>
542
);
543
}
544
545
// Modal-safe popup rendering
546
function ModalSafeTabs({ inModal }: { inModal: boolean }) {
547
return (
548
<Tabs
549
items={manyTabs}
550
getPopupContainer={inModal ?
551
(node) => node.closest('.ant-modal-content') || document.body :
552
undefined
553
}
554
more={{
555
icon: <MoreOutlined />,
556
}}
557
/>
558
);
559
}
560
```