Skip to content

Conversation

@TahaTesser
Copy link
Member

@TahaTesser TahaTesser commented Feb 7, 2025

Fixes Flutter 3.27 and later breaks past styling and theming of icon color on buttons with icons

Description

This PR fixes how the icon color is resolved in ButtonStyleButton. This was regressed in #143501.

Code Sample (taken from issue)

expand to view the code sample
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

final ButtonStyle filledButtonStyle = FilledButton.styleFrom(
  foregroundColor: Colors.red,
  backgroundColor: Colors.grey,
);

final ButtonStyle elevatedButtonStyle = ElevatedButton.styleFrom(
  foregroundColor: Colors.orange.shade600,
  backgroundColor: Colors.blueGrey,
);

final ButtonStyle outlinedButtonStyle = OutlinedButton.styleFrom(
  foregroundColor: Colors.lightBlue,
);

final ButtonStyle textButtonStyle = TextButton.styleFrom(
  foregroundColor: Colors.green,
);

final ButtonStyle segmentedButtonStyle = SegmentedButton.styleFrom(
  selectedForegroundColor: Colors.tealAccent.shade700,
);

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const HomePage(),
      theme: ThemeData(
        filledButtonTheme: FilledButtonThemeData(
          style: filledButtonStyle,
        ),
        elevatedButtonTheme: ElevatedButtonThemeData(
          style: elevatedButtonStyle,
        ),
        outlinedButtonTheme: OutlinedButtonThemeData(
          style: outlinedButtonStyle,
        ),
        textButtonTheme: TextButtonThemeData(
          style: textButtonStyle,
        ),
        segmentedButtonTheme: SegmentedButtonThemeData(
          style: segmentedButtonStyle,
        ),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Button Icon Color Issue')),
      body: Center(
        child: Column(
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                FilledButton.icon(
                  label: const Text('Filled Themed'),
                  icon: const Icon(Icons.add),
                  onPressed: () {},
                ),
                const SizedBox(width: 8),
                FilledButton.icon(
                  style: filledButtonStyle.copyWith(
                    foregroundColor: WidgetStateProperty.all(Colors.yellow),
                  ),
                  label: const Text('Filled Styled'),
                  icon: const Icon(Icons.add),
                  onPressed: () {},
                ),
              ],
            ),
            const SizedBox(height: 8),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton.icon(
                  label: const Text('Elevated Themed'),
                  icon: const Icon(Icons.add),
                  onPressed: () {},
                ),
                const SizedBox(width: 8),
                ElevatedButton.icon(
                  style: elevatedButtonStyle.copyWith(
                    foregroundColor: WidgetStateProperty.all(Colors.lime),
                  ),
                  label: const Text('Elevated Styled'),
                  icon: const Icon(Icons.add),
                  onPressed: () {},
                ),
              ],
            ),
            const SizedBox(height: 8),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                OutlinedButton.icon(
                  label: const Text('Outlined Themed'),
                  icon: const Icon(Icons.add),
                  onPressed: () {},
                ),
                const SizedBox(width: 8),
                OutlinedButton.icon(
                  style: outlinedButtonStyle.copyWith(
                    foregroundColor: WidgetStateProperty.all(Colors.deepOrange),
                  ),
                  label: const Text('Outlined Styled'),
                  icon: const Icon(Icons.add),
                  onPressed: () {},
                ),
              ],
            ),
            const SizedBox(height: 8),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                TextButton.icon(
                  label: const Text('Text Themed'),
                  icon: const Icon(Icons.add),
                  onPressed: () {},
                ),
                const SizedBox(width: 8),
                TextButton.icon(
                  style: textButtonStyle.copyWith(
                    foregroundColor: WidgetStateProperty.all(Colors.pink),
                  ),
                  label: const Text('Text Styled'),
                  icon: const Icon(Icons.add),
                  onPressed: () {},
                ),
              ],
            ),
            const SizedBox(height: 8),
            const SegmentedButtonShowcase(),
          ],
        ),
      ),
    );
  }
}

class SegmentedButtonShowcase extends StatefulWidget {
  const SegmentedButtonShowcase({this.showOutlinedButton, super.key});
  final bool? showOutlinedButton;

  @override
  State<SegmentedButtonShowcase> createState() =>
      _SegmentedButtonShowcaseState();
}

enum Calendar { day, week, month, year }

class _SegmentedButtonShowcaseState extends State<SegmentedButtonShowcase> {
  Calendar _selected = Calendar.day;

  @override
  Widget build(BuildContext context) {
    return SegmentedButton<Calendar>(
      segments: const <ButtonSegment<Calendar>>[
        ButtonSegment<Calendar>(
          value: Calendar.day,
          label: Text('Day'),
          icon: Icon(Icons.calendar_view_day),
        ),
        ButtonSegment<Calendar>(
          value: Calendar.week,
          icon: Icon(Icons.calendar_view_week),
          label: Text('Week'),
        ),
        ButtonSegment<Calendar>(
          value: Calendar.month,
          icon: Icon(Icons.calendar_view_month),
          label: Text('Mont'),
        ),
        ButtonSegment<Calendar>(
          value: Calendar.year,
          icon: Icon(Icons.calendar_today),
          label: Text('Year'),
        ),
      ],
      selected: <Calendar>{_selected},
      onSelectionChanged: (Set<Calendar> selected) {
        setState(() {
          _selected = selected.first;
        });
      },
    );
  }
}

Before

Screenshot 2025-02-07 at 17 45 46

After

Screenshot 2025-02-07 at 17 45 37

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@github-actions github-actions bot added a: text input Entering text in a text field or keyboard related problems framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Feb 7, 2025
@TahaTesser TahaTesser marked this pull request as ready for review February 7, 2025 15:48
@TahaTesser TahaTesser requested a review from QuncCccccc February 7, 2025 15:49
@TahaTesser TahaTesser force-pushed the button_icon_foregroundColor branch from 277be39 to b58e85e Compare February 7, 2025 16:17
@kishan-dhankecha
Copy link
Contributor

Related #161467

Copy link
Contributor

@QuncCccccc QuncCccccc left a comment

Choose a reason for hiding this comment

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

LGTM:) Thanks for the fix!

/// [ButtonStyle.iconColor] and [iconSize] is used to construct
/// [ButtonStyle.iconSize].
///
/// If [foregroundColor] is provided and [iconColor] is not provided, then the button icon will
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe something like: If [iconColor] is null, the button icon will use [foregroundColor]. If [foregroundColor] is also null, the button icon will use the default icon color.

@TahaTesser TahaTesser added the autosubmit Merge PR when tree becomes green via auto submit App label Feb 12, 2025
@TahaTesser TahaTesser removed the autosubmit Merge PR when tree becomes green via auto submit App label Feb 13, 2025
@TahaTesser TahaTesser force-pushed the button_icon_foregroundColor branch from 3d044e3 to cd0e466 Compare February 13, 2025 07:45
@TahaTesser TahaTesser added the autosubmit Merge PR when tree becomes green via auto submit App label Feb 13, 2025
@auto-submit auto-submit bot added this pull request to the merge queue Feb 13, 2025
Merged via the queue into flutter:master with commit 60d0bfc Feb 13, 2025
77 checks passed
@flutter-dashboard flutter-dashboard bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Feb 13, 2025
@TahaTesser TahaTesser deleted the button_icon_foregroundColor branch February 13, 2025 09:08
@TahaTesser TahaTesser added the cp: stable cherry pick this pull request to stable release candidate branch label Feb 13, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 13, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 13, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 13, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 15, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 16, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 16, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 17, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 17, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 17, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 18, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 18, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 18, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 19, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 19, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 19, 2025
auto-submit bot pushed a commit that referenced this pull request Feb 20, 2025
…163201)

This pull request is created by [automatic cherry pick workflow](https://github.com/flutter/flutter/blob/main/docs/releases/Flutter-Cherrypick-Process.md#automatically-creates-a-cherry-pick-request)
Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request.

### Issue Link:
What is the link to the issue this cherry-pick is addressing?

PR: #162880
Issue: #162839

### Changelog Description:
Explain this cherry pick in one line that is accessible to most Flutter developers. See [best practices](https://github.com/flutter/flutter/blob/main/docs/releases/Hotfix-Documentation-Best-Practices.md) for examples

Fixes buttons with icons ignore `foregroundColor`.

### Impact Description:
What is the impact (ex. visual jank on Samsung phones, app crash, cannot ship an iOS app)? Does it impact development (ex. flutter doctor crashes when Android Studio is installed), or the shipping production app (the app crashes on launch)

It impacts how buttons with icons render color when using `foregroundColor`.

### Workaround:
Is there a workaround for this issue?

Provide additional property such as `iconColor`  along with `foregroundColor` to match colors for button label and icon.

### Risk:
What is the risk level of this cherry-pick?

### Test Coverage:
Are you confident that your fix is well-tested by automated tests?

### Validation Steps:
What are the steps to validate that this fix works?

Testing and samples.
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request Feb 20, 2025
7h30n3 added a commit to OPENER-next/OpenStop that referenced this pull request Mar 7, 2025
Due to an upstream fix some lines of code could be removed
flutter/flutter#162880
7h30n3 added a commit to OPENER-next/OpenStop that referenced this pull request Mar 10, 2025
Due to an upstream fix some lines of code could be removed
flutter/flutter#162880
CodixNinja pushed a commit to CodixNinja/flutter that referenced this pull request May 15, 2025
…#163201)

This pull request is created by [automatic cherry pick workflow](https://github.com/flutter/flutter/blob/main/docs/releases/Flutter-Cherrypick-Process.md#automatically-creates-a-cherry-pick-request)
Please fill in the form below, and a flutter domain expert will evaluate this cherry pick request.

### Issue Link:
What is the link to the issue this cherry-pick is addressing?

PR: flutter/flutter#162880
Issue: flutter/flutter#162839

### Changelog Description:
Explain this cherry pick in one line that is accessible to most Flutter developers. See [best practices](https://github.com/flutter/flutter/blob/main/docs/releases/Hotfix-Documentation-Best-Practices.md) for examples

Fixes buttons with icons ignore `foregroundColor`.

### Impact Description:
What is the impact (ex. visual jank on Samsung phones, app crash, cannot ship an iOS app)? Does it impact development (ex. flutter doctor crashes when Android Studio is installed), or the shipping production app (the app crashes on launch)

It impacts how buttons with icons render color when using `foregroundColor`.

### Workaround:
Is there a workaround for this issue?

Provide additional property such as `iconColor`  along with `foregroundColor` to match colors for button label and icon.

### Risk:
What is the risk level of this cherry-pick?

### Test Coverage:
Are you confident that your fix is well-tested by automated tests?

### Validation Steps:
What are the steps to validate that this fix works?

Testing and samples.
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 20, 2025
engine-flutter-autoroll added a commit to engine-flutter-autoroll/packages that referenced this pull request May 21, 2025
777genius added a commit to 777genius/flutter that referenced this pull request Nov 18, 2025
Extended research with 2+ additional hours of deep analysis across theme
properties, widget enhancements, and Material 3 compliance issues.

New Issues Documented (Phase 2):
- flutter#117755: Divider color inconsistencies M2/M3 (30-45 min, P2, 90%)
- flutter#67409: TextField disabled errorText spacing (30-60 min, P2, 85%)

Additional Discoveries Added to Tier D:
- flutter#162585: SliverAppBar toolbarHeight theme (February 2025!)
- flutter#159565: RawWebImage missing properties (P2, web platform)
- flutter#159269: Radio fillColor theme (P2, under investigation)
- flutter#105887: Divider styling options (dashed/dotted)
- flutter#132214: DataTable dividerThickness: 0 bug
- flutter#123943: SliverAppBar.medium/large foreground color
- And 10+ more viable issues identified

Fixed Issues Found During Research:
- flutter#131690: ProgressIndicator properties (PR flutter#158104)
- flutter#165294: ProgressIndicator strokeWidth adaptive (PR flutter#165370)
- flutter#162839: Button icon color regression P1 (PR flutter#162880)

Updated Statistics:
- 700+ issues scanned (up from 600+)
- 90+ issues deeply analyzed (up from 80+)
- 180+ search queries (up from 150+)
- 140+ categories explored (up from 120+)
- 16 MD files with comprehensive documentation
- 6+ hours total research time
- ~80,000 words of documentation

Updated TOP_FLUTTER_ISSUES.md:
- Added new Tier A issues (flutter#117755, flutter#67409)
- Expanded Tier D with recent discoveries
- Updated recommended starting order (11 issues)
- Enhanced statistics and insights
- Added 10 fixed issues found during research
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: text input Entering text in a text field or keyboard related problems cp: stable cherry pick this pull request to stable release candidate branch f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flutter 3.27 and later breaks past styling and theming of icon color on buttons with icons

4 participants