The `ButtonBar` widget was deprecated in favor of the more efficient `OverflowBar` widget. As a result, `ThemeData.buttonBarTheme` and `ButtonBarTheme` were also deprecated.
Original behavior
The `ButtonBar` widget lays out its children in a row and in a column if there is not enough horizontal space. The `OverflowBar` widget does the same, but it's not tied to the Material library and is part of the core `widgets.dart` library.
New behavior
- Replace `ButtonBar` widget with `OverflowBar` widget. - By default, `ButtonBar` aligns its children to the end of the layout, while `OverflowBar` aligns its children to the start. To align the `OverflowBar` children to the end, set the `OverflowBar.alignment` property to `MainAxisAlignment.end`. - `ButtonBar.buttonPadding` provides spacing between buttons and padding around buttons. Replace it with `OverflowBar.spacing`, which provides spacing between buttons. Wrap the `OverflowBar` widget with `Padding` widget to provide padding around the buttons. - Replace `ButtonBar.overflowButtonSpacing
- Who is affected
- Code that still calls the deprecated API; it keeps working until removal but produces analyzer warnings. Code that uses ButtonBar, OverflowBar, ThemeData.buttonBarTheme and related APIs.
- Practical impact
- Warnings now; removal in a future release. Plan the migration but no immediate break.
- What action should I take?
- Follow the official migration guide below, update affected call sites, run `dart fix --apply` where a fix is available, then run your tests.
Before and after (from the official guide)
| 1 | − | ButtonBar( |
| 2 | − | buttonPadding: const EdgeInsets.all(8.0), |
| 3 | − | overflowButtonSpacing: 8.0, |
| 4 | − | children: <Widget>[ |
| 5 | − | TextButton(child: const Text('Button 1'), onPressed: () {}), |
| 6 | − | TextButton(child: const Text('Button 2'), onPressed: () {}), |
| 7 | − | TextButton(child: const Text('Button 3'), onPressed: () {}), |
| 8 | − | ], |
| 9 | ), |
| 1 | + | Padding( |
| 2 | + | padding: const EdgeInsets.all(8.0), |
| 3 | + | child: OverflowBar( |
| 4 | + | alignment: MainAxisAlignment.end, |
| 5 | + | spacing: 8.0, |
| 6 | + | overflowSpacing: 8.0, |
| 7 | + | children: <Widget>[ |
| 8 | + | TextButton(child: const Text('Button 1'), onPressed: () {}), |
| 9 | + | TextButton(child: const Text('Button 2'), onPressed: () {}), |
| 10 | + | TextButton(child: const Text('Button 3'), onPressed: () {}), |
| 11 | + | ], |
| 12 | + | ), |
| 13 | ), |
Raw before / after
ButtonBar(
buttonPadding: const EdgeInsets.all(8.0),
overflowButtonSpacing: 8.0,
children: <Widget>[
TextButton(child: const Text('Button 1'), onPressed: () {}),
TextButton(child: const Text('Button 2'), onPressed: () {}),
TextButton(child: const Text('Button 3'), onPressed: () {}),
],
),Padding(
padding: const EdgeInsets.all(8.0),
child: OverflowBar(
alignment: MainAxisAlignment.end,
spacing: 8.0,
overflowSpacing: 8.0,
children: <Widget>[
TextButton(child: const Text('Button 1'), onPressed: () {}),
TextButton(child: const Text('Button 2'), onPressed: () {}),
TextButton(child: const Text('Button 3'), onPressed: () {}),
],
),
),Official migration guide (excerpt, © The Flutter Authors, CC BY 3.0)
Replace ButtonBar with OverflowBar, override the default alignment if
necessary, replace ButtonBar.buttonPadding with Padding widget and
OverflowBar.spacing for spacing between and around buttons, and replace
ButtonBar.overflowButtonSpacing with OverflowBar.overflowSpacing for
spacing between buttons when the buttons are laid in a column when there is not
enough horizontal space.
Before:
ButtonBar(
buttonPadding: const EdgeInsets.all(8.0),
overflowButtonSpacing: 8.0,
children: <Widget>[
TextButton(child: const Text('Button 1'), onPressed: () {}),
TextButton(child: const Text('Button 2'), onPressed: () {}),
TextButton(child: const Text('Button 3'), onPressed: () {}),
],
),After:
Padding(
padding: const EdgeInsets.all(8.0),
child: OverflowBar(
alignment: MainAxisAlignment.end,
spacing: 8.0,
overflowSpacing: 8.0,
children: <Widget>[
TextButton(child: const Text('Button 1'), onPressed: () {}),
TextButton(child: const Text('Button 2'), onPressed: () {}),
TextButton(child: const Text('Button 3'), onPressed: () {}),
],
),
),If you specify a ThemeData.buttonBarTheme, remove it and
use the OverflowBar widget properties to customize the OverflowBar widget.
Before:
ThemeData(
buttonBarTheme: ButtonBarThemeData(
alignment: MainAxisAlignment.center,
),
),After:
ThemeData(
// ...
),If you use the ButtonBarTheme widget, remove it and
use the OverflowBar widget properties to customize the OverflowBar widget.
Before:
ButtonBarTheme(
data: ButtonBarThemeData(
alignment: MainAxisAlignment.center,
),
child: ButtonBar(
children: <Widget>[
// ...
],
),
),After:
OverflowBar(
alignment: MainAxisAlignment.center,
children: <Widget>[
// ...
],
),AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.Listed in the official breaking-changes index; title states deprecation.
An official announcement or migration guide documents an intended behaviour or API change. A verified source change (git diff) shows code changed but does not by itself prove a public API is breaking. AI interpretations are labelled and never used to classify a change.
- Official migration guide
- OverflowBar
- Issue #127955
- Deprecate ButtonBar, ButtonBarThemeData, and ThemeData.buttonBarTheme
- Source commit
- b3045439b7c0
- Source last updated
- Oct 21, 2026
- Last synchronized
- Oct 21, 2026
- Publication status
- published
Publication history
- Oct 21, 2026, 8:31 PM: new → published (ingestion) — Backed by an official breaking-change/migration guide.
AI_PROVIDER (for example to openai-compatible with a local Ollama or LM Studio endpoint) to enable grounded explanations. Everything else on this page works without an AI provider.