WTabs
Controlled tabs widget. Renders a tab list and a content panel. The selected: state prefix activates on the currently active tab, so callers can supply tokens like selected:border-b-2 selected:text-blue-600 through tabClassName. This is a fully controlled widget: selectedIndex is managed by the caller.
Table of Contents
Basic Usage
WTabs(
tabs: const ['Overview', 'Details', 'Settings'],
selectedIndex: _selectedTab,
onChanged: (i) => setState(() => _selectedTab = i),
listClassName: 'flex flex-row border-b border-gray-200 dark:border-gray-700',
tabClassName: '''
px-4 py-2 text-sm text-gray-500 dark:text-gray-400
selected:text-blue-600 dark:selected:text-blue-400
selected:border-b-2 selected:border-blue-600 dark:selected:border-blue-400
''',
panelClassName: 'pt-4',
panelBuilder: (index) => _panels[index],
)
Props
| Prop | Type | Default | Description |
|---|---|---|---|
tabs |
List |
Required | The labels rendered for each tab, in display order. |
selectedIndex |
int |
Required | Zero-based index of the currently selected tab. |
panelBuilder |
Widget Function(int index) |
Required | Returns the panel content for the currently selected tab. |
onChanged |
ValueChanged |
null |
Called with the tapped tab's index. The caller updates selectedIndex in response. |
listClassName |
String? |
null |
Utility classes for the tab-list row container. Example: 'flex flex-row border-b border-gray-200 dark:border-gray-700'. |
tabClassName |
String? |
null |
Utility classes applied to every tab's inner WDiv. Supports selected: prefixed tokens: they activate only on the selected tab. |
selectedTabClassName |
String? |
null |
Extra utility classes appended to the active tab's WDiv only. Applied after tabClassName. |
panelClassName |
String? |
null |
Utility classes for the panel wrapper WDiv. Example: 'pt-4'. |
fullWidthList |
bool |
true |
When true, prepends w-full to the tab list so a border-b baseline spans the full container width (tabs stay content-sized, left-aligned). If listClassName already sets a width token (w-*), that width is respected and w-full is not prepended, so an explicit width wins. Set false for a content-width strip (centered pill tabs). |
Constructor
WTabs({
Key? key,
required List tabs,
required int selectedIndex,
required Widget Function(int index) panelBuilder,
ValueChanged? onChanged,
String? listClassName,
String? tabClassName,
String? selectedTabClassName,
String? panelClassName,
bool fullWidthList = true,
})
Styling Examples
Underline Tabs
Classic underline style: selected:border-b-2 on the active tab. Pair border and text colors with dark: variants:
WTabs(
tabs: const ['Overview', 'Activity', 'Settings'],
selectedIndex: _tab,
onChanged: (i) => setState(() => _tab = i),
listClassName: 'flex flex-row border-b border-gray-200 dark:border-gray-700',
tabClassName: '''
px-4 py-3 text-sm font-medium
text-gray-500 dark:text-gray-400
selected:text-rose-600 dark:selected:text-rose-400
selected:border-b-2 selected:border-rose-600 dark:selected:border-rose-400
''',
panelClassName: 'pt-4',
panelBuilder: (index) => panels[index],
)
Pill / Segmented Control
Background-based active tab with rounded container:
WTabs(
tabs: const ['All', 'Open', 'Resolved'],
selectedIndex: _tab,
onChanged: (i) => setState(() => _tab = i),
listClassName: 'flex flex-row gap-1 p-1 rounded-lg bg-gray-100 dark:bg-gray-800',
tabClassName: '''
px-3 py-1.5 rounded-md text-sm font-medium
text-gray-600 dark:text-gray-400
selected:bg-white dark:selected:bg-gray-700
selected:text-gray-900 dark:selected:text-white
selected:shadow-sm
''',
panelClassName: 'pt-4',
panelBuilder: (index) => panels[index],
)
selectedTabClassName for Active-Only Tokens
Use selectedTabClassName to append active-only classes without selected: prefixes:
WTabs(
tabs: const ['Profile', 'Security', 'Billing'],
selectedIndex: _tab,
onChanged: (i) => setState(() => _tab = i),
tabClassName: 'px-4 py-2 text-sm text-gray-500 dark:text-gray-400',
selectedTabClassName: 'text-blue-600 dark:text-blue-400 border-b-2 border-blue-600 dark:border-blue-400',
panelBuilder: (index) => panels[index],
)