Skip to content

[widget_preview] Do not leak ListTileTheme into previewed widgets - #194992

Merged
auto-submit[bot] merged 2 commits into
flutter:masterfrom
bkonyi:issue-194660
Oct 29, 2026
Merged

auto-submit[bot] merged 2 commits into
flutter:masterfrom
bkonyi:issue-194660

Conversation

@bkonyi

@bkonyi bkonyi commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

In the widget preview scaffold, WidgetPreviewGroupWidget wrapped ExpansionTile in a ListTileTheme. Because ListTileTheme is an InheritedTheme (InheritedWidget), it enclosed all previewed child widgets. Because MaterialApp and Theme do not insert a ListTileTheme boundary to reset ancestor inherited themes, previewed ListTile and SwitchListTile widgets inherited the scaffold's brightened tileColor (#201E24).

This removes the ListTileTheme and dead Theme(dividerColor: Colors.transparent) wrappers around ExpansionTile, removes unused listTileTheme from the scaffold's _baseTheme, and adds integration regression tests in theming_test.dart.

Fixes #194660

Visual Behavior

  • Before: SwitchListTile and ListTile rendered with an unintended dark tile background (#201E24).
  • After: SwitchListTile and ListTile render with the default transparent background.

Previous output:

00:01 +4: Previewed MaterialApp ListTileTheme is not overridden
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: MaterialColor:<MaterialColor(primary value: Color(alpha: 1.0000, red: 0.9569, green:
0.2627, blue: 0.2118, colorSpace: ColorSpace.sRGB))>
  Actual: Color:<Color(alpha: 1.0000, red: 0.1245, green: 0.1171, blue: 0.1394, colorSpace:
ColorSpace.sRGB)>
════════════════════════════════════════════════════════════════════════════════════════════════════
00:02 +4 -1: Previewed MaterialApp ListTileTheme is not overridden [E]

00:02 +4 -1: ListTileTheme does not leak into previewed widgets without MaterialApp
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: null
  Actual: Color:<Color(alpha: 1.0000, red: 0.1245, green: 0.1171, blue: 0.1394, colorSpace:
ColorSpace.sRGB)>
════════════════════════════════════════════════════════════════════════════════════════════════════
00:02 +4 -2: ListTileTheme does not leak into previewed widgets without MaterialApp [E]

00:02 +4 -2: SwitchListTile in preview has transparent background by default
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: has `color` with value Color:<Color(alpha: 0.0000, red: 0.0000, green: 0.0000, blue:
0.0000, colorSpace: ColorSpace.extendedSRGB)>
  Actual: ShapeDecoration:<ShapeDecoration(color: Color(alpha: 1.0000, red: 0.1245, green: 0.1171,
blue: 0.1394, colorSpace: ColorSpace.sRGB), shape: RoundedRectangleBorder(BorderSide(none),
BorderRadius.circular(12.0)))>
   Which: has `color` with value Color:<Color(alpha: 1.0000, red: 0.1245, green: 0.1171, blue:
0.1394, colorSpace: ColorSpace.sRGB)>
════════════════════════════════════════════════════════════════════════════════════════════════════
00:03 +4 -3: SwitchListTile in preview has transparent background by default [E]

Current output:

00:00 +0: loading dev/integration_tests/widget_preview_scaffold/test/theming_test.dart
00:00 +0: Theming is correctly propagated down to the previewed widget
00:00 +1: Default theme is used if no preview theme is specified
00:00 +2: BrightnessToggleButton correctly toggles preview brightness
00:01 +3: Updated brightness property doesn't override state set by BrightnessToggleButton
00:01 +4: Previewed MaterialApp ListTileTheme is not overridden
00:01 +5: ListTileTheme does not leak into previewed widgets without MaterialApp
00:01 +6: SwitchListTile in preview has transparent background by default
00:01 +7: All tests passed!

In the widget preview scaffold, WidgetPreviewGroupWidget wrapped
ExpansionTile in a ListTileTheme. Because ListTileTheme is an
InheritedTheme (InheritedWidget), it enclosed ExpansionTile.children
(the previewed widgets). When previewed widgets build a ListTile or
SwitchListTile, ListTileTheme.of(context) resolved the ancestor
previewer's ListTileTheme because MaterialApp and Theme do not insert
a ListTileTheme boundary to reset ancestor inherited themes.

This caused previewed ListTiles and SwitchListTiles to render with an
unintended dark tileColor (#201E24), even when running inside a preview
with its own MaterialApp and ThemeData.

This change:
1. Removes the ListTileTheme wrapper around ExpansionTile in
   WidgetPreviewGroupWidget, passing dense: true directly to
   ExpansionTile and relying on expansionTileTheme for shape styling.
2. Removes the dead Theme(dividerColor: Colors.transparent) wrapper
   which also leaked into previews.
3. Removes the unused listTileTheme configuration from the scaffold's
   _baseTheme in theme.dart.
4. Adds automated integration regression tests in theming_test.dart.
5. Keeps template .tmpl files byte-identical to the scaffold source.

Previous output:
```
00:01 +4: Previewed MaterialApp ListTileTheme is not overridden
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: MaterialColor:<MaterialColor(primary value: Color(alpha: 1.0000, red: 0.9569, green:
0.2627, blue: 0.2118, colorSpace: ColorSpace.sRGB))>
  Actual: Color:<Color(alpha: 1.0000, red: 0.1245, green: 0.1171, blue: 0.1394, colorSpace:
ColorSpace.sRGB)>
════════════════════════════════════════════════════════════════════════════════════════════════════
00:02 +4 -1: Previewed MaterialApp ListTileTheme is not overridden [E]

00:02 +4 -1: ListTileTheme does not leak into previewed widgets without MaterialApp
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: null
  Actual: Color:<Color(alpha: 1.0000, red: 0.1245, green: 0.1171, blue: 0.1394, colorSpace:
ColorSpace.sRGB)>
════════════════════════════════════════════════════════════════════════════════════════════════════
00:02 +4 -2: ListTileTheme does not leak into previewed widgets without MaterialApp [E]

00:02 +4 -2: SwitchListTile in preview has transparent background by default
══╡ EXCEPTION CAUGHT BY FLUTTER TEST FRAMEWORK ╞════════════════════════════════════════════════════
The following TestFailure was thrown running a test:
Expected: has `color` with value Color:<Color(alpha: 0.0000, red: 0.0000, green: 0.0000, blue:
0.0000, colorSpace: ColorSpace.extendedSRGB)>
  Actual: ShapeDecoration:<ShapeDecoration(color: Color(alpha: 1.0000, red: 0.1245, green: 0.1171,
blue: 0.1394, colorSpace: ColorSpace.sRGB), shape: RoundedRectangleBorder(BorderSide(none),
BorderRadius.circular(12.0)))>
   Which: has `color` with value Color:<Color(alpha: 1.0000, red: 0.1245, green: 0.1171, blue:
0.1394, colorSpace: ColorSpace.sRGB)>
════════════════════════════════════════════════════════════════════════════════════════════════════
00:03 +4 -3: SwitchListTile in preview has transparent background by default [E]
```

Current output:
```
00:00 +0: loading dev/integration_tests/widget_preview_scaffold/test/theming_test.dart
00:00 +0: Theming is correctly propagated down to the previewed widget
00:00 +1: Default theme is used if no preview theme is specified
00:00 +2: BrightnessToggleButton correctly toggles preview brightness
00:01 +3: Updated brightness property doesn't override state set by BrightnessToggleButton
00:01 +4: Previewed MaterialApp ListTileTheme is not overridden
00:01 +5: ListTileTheme does not leak into previewed widgets without MaterialApp
00:01 +6: SwitchListTile in preview has transparent background by default
00:01 +7: All tests passed!
```

Fixes flutter#194660
@bkonyi bkonyi added the CICD Run CI/CD label Oct 21, 2026
@github-actions github-actions Bot added the tool Affects the "flutter" command-line tool. See also t: labels. label Oct 21, 2026
@bkonyi
bkonyi marked this pull request as ready for review October 26, 2026 19:17

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request removes the global 'listTileTheme' configuration and the 'ListTileTheme' and 'Theme' wrappers around 'ExpansionTile' in the widget preview scaffold, adding corresponding integration tests to verify theme isolation. The reviewer notes that removing the 'Theme' wrapper might cause unwanted divider lines to appear on the expanded 'ExpansionTile' and suggests explicitly setting 'shape' and 'collapsedShape' to 'const Border()' to prevent this visual regression.

@bkonyi
bkonyi requested a review from srawlins October 26, 2026 19:22
@bkonyi bkonyi added the autosubmit Merge PR when tree becomes green via auto submit App label Oct 29, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Oct 29, 2026
Merged via the queue into flutter:master with commit 5f2addd Oct 29, 2026
23 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Oct 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Widget Previewer] ListTileTheme leaks into previewed widgets, causing incorrect background colors

2 participants