Skip to content

[material_ui] colors in the black/white parameters of Typography.material2021 are overwritten (this is not documented) #195200

Closed
flutter/packages
#13443

Description

@elliette

Under Material 3+, text color comes from the app's ColorScheme.

However, Typography.material2021 (the M3 factory constructor) takes both a ColorScheme parameter and black/white TextTheme parameters, and overwrites every color passed in via the black/white TextTheme parameters with the color scheme values (see code).

This means the colors a user passes via the black/white parameters in Typography.material2021() are silently discarded. Furthermore, this behavior is undocumented.

For example:

final typography = Typography.material2021(
  colorScheme: colorScheme,
  black: const TextTheme(bodyMedium: TextStyle(color: Colors.red)),
);
print(typography.black.bodyMedium!.color); // colorScheme.onSurface, not red!

Since we are currently implementing Material 3 Expressive, which also resolves text color by using the app's color scheme, I think we should decide now how we want to handle fixing this, so that we don't inadvertently introduce the same bug into our Material 3 Expressive implementation.

Part of this decision is determining whether changing the overwriting logic is a breaking change.

Is fixing the overwrite logic a breaking change?

We could update Typography.material2021 overwrite with colors from the color scheme only if the black/white parameters are null. However, will cause a visual change for apps currently specifying them, e.g.:

final typography = Typography.material2021(
  colorScheme: colorScheme,
  black: blackCupertino
);
print(typography.black.bodyMedium!.color); // blackCupertino.displayMedium.color, not colorScheme.onSurface!

Does this kind of visual change constitute a breaking change?

Options if it is a breaking change:

Option 1: Typography.material2025 (M3E) also overwrites the black/white parameters. Document this behavior in both constructors

Under this plan, we could remove the overwriting logic in both constructors in a future breaking change release.

Pros:

  • keeps the implementation of Typography.material2021 and Typography.material2025 consistent.

Cons:

  • material2025 inherits the same confusing API as material2021

Option 2: Typography.material2025 (M3E) does not overwrite the black/white parameters. Keep material2021 as-is but document the behavior.

Pros:

  • the new Typography.material2025 does not have this confusing API

Cons:

  • material2021 and material2025 now behave differently (introducing a separate realm of confusion)

If it is not a breaking change:

Then we can fix the overwriting logic in material2021 and the forthcoming material2025 factory constructor.

Activity

  1. QuncCccccc commented on Oct 24, 2026

    @QuncCccccc
    Contributor

    It's surprising that we don't have any issue filed related to this since we introduced material2021😅 Probably few apps rely on passing colors through black/white.

    I think these black/white parameters look like an M2 leftover that was carried over into the M3 API. The new default looks intended: #116125 made every M3 text style use onSurface, which is what the spec asks for ("The default color for typography is on surface"). But overwriting the text themes that developers pass in doesn't look intentional. The black and white parameters were added earlier: #97829 copied them from the M2 constructors when it added material2021, and their colors were kept until #116125, whose description and tests only cover the defaults.

    Even though this is a bug, fixing it would visibly change apps that pass these parameters. So I doubt it's still worth fixing. Instead, maybe we can:

    • Deprecate the black and white parameters of Typography.material2021, and remove them when we remove M2 (useMaterial3). The Typography.black/white fields and the M2 constructors stay as they are.
    • Don't add black/white to Typography.material2025. This avoids the downsides of both options in the issue description: material2025 doesn't inherit the confusing parameters, and both constructors still resolve colors the same way. The M3E baseline type scale is the same as 2021's and only the emphasized styles are new, so apps that don't pass black/white see no difference when they move to 2025.
    • partial option 1, Document the current behavior in material2021 until the parameters are removed.

    Developers who really want their own black/white text themes can still use Typography.copyWith(). Merging them into the generated themes keeps the styles they don't override:

    final base = Typography.material2025(platform: platform, colorScheme: colorScheme);
    final typography = base.copyWith(
      black: base.black.merge(myBlack),
      white: base.white.merge(myWhite),
    );

    In the longer term, since material2025 would produce the same baseline styles as material2021, we could also consider deprecating material2021 in favor of material2025. Deprecating just the parameters doesn't need to wait for that, though.

    What do you think?

  2. github-actions commented on Nov 10, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  3. locked as resolved and limited conversation to collaborators on Nov 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    p: material_uimaterial_ui package in flutter/packagesteam-ecosystemOwned by Ecosystem team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions