or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdanimation-transitions.mdcore-interface.mdeditable-tabs.mdindex.mdtab-configuration.md

advanced-features.mddocs/

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

```