TabBar: a rounded surfaceElevated track with a surfaceBg indicator that slides between tabs. Source: styled_tab_bar.dart.
API
This is a controlled component: it doesn’t own selection state. Internally (it’s a
HookWidget) a useTabController plus two useEffects keep things in sync — one animates the controller when selectedIndex changes externally, the other listens to the controller and calls onChanged when the user taps (skipping intermediate indexIsChanging frames).
Visual anatomy
- Track:
surfaceElevated, radius 32, 4 px padding - Indicator:
surfaceBg, radius 24, soft black-26 shadow, sized to the tab - Labels:
buttonMedium/contrastBoldfor both states — selection is communicated by the indicator, not label color - 40 px tab height; no splash/overlay (selection is the feedback)
Tokens consumed
surfaceElevated, surfaceBg, contrastBold; typography buttonMedium.
One of only two hook-based widgets in the design system (the other is app-level
CarouselListView) — components stay StatelessWidget unless they genuinely need local state. See Conventions.