Tabs
In ProgressDark modeRTLTabbed content panels for organizing information.
Installation
Copy the component into your project using the CLI:
$ronakcn add tabs
Usage
Import and use the component in your Flutter widget tree:
lib/pages/example.dart
import 'package:flutter/material.dart';
import '../components/tabs/tabs.dart';
class ExamplePage extends StatelessWidget {
const ExamplePage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('RcnTabs Example')),
body: Center(
child: RcnTabs(
// Configure props here
),
),
);
}
}Variants
Tabs ships with the following variants:
default
Standard underline tab bar.
with-icon
Tabs with icons alongside labels.
scrollable
Horizontally scrollable tab bar.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
tabs* | List<TabItem> | — | List of tab definitions. |
activeIndex | int | 0 | Currently active tab index. |
onChanged* | ValueChanged<int> | — | Called when tab changes. |
Source files
lib/components/ui/tabs.dart
import 'package:flutter/material.dart';
class TabItem {
const TabItem({required this.label, required this.content, this.icon});
final String label;
final Widget content;
final IconData? icon;
}
class RcnTabs extends StatefulWidget {
const RcnTabs({super.key, required this.tabs, this.activeIndex = 0, required this.onChanged});
final List<TabItem> tabs;
final int activeIndex;
final ValueChanged<int> onChanged;
@override
State<RcnTabs> createState() => _RcnTabsState();
}
class _RcnTabsState extends State<RcnTabs> {
late int _active;
@override
void initState() { super.initState(); _active = widget.activeIndex; }
@override
Widget build(BuildContext context) {
final colors = Theme.of(context).colorScheme;
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: List.generate(widget.tabs.length, (i) {
final isActive = i == _active;
return GestureDetector(
onTap: () { setState(() => _active = i); widget.onChanged(i); },
child: Padding(
padding: const EdgeInsets.only(right: 16, bottom: 8),
child: Column(
children: [
Text(widget.tabs[i].label,
style: TextStyle(fontSize: 14, fontWeight: isActive ? FontWeight.w600 : FontWeight.normal,
color: isActive ? colors.onSurface : colors.onSurface.withOpacity(0.5))),
const SizedBox(height: 4),
if (isActive) Container(height: 2, width: 40, color: colors.onSurface),
],
),
),
);
}),
),
widget.tabs[_active].content,
],
);
}
}Version
0.1.0 · navigation category