-
Notifications
You must be signed in to change notification settings - Fork 29.1k
Description
Is there an existing issue for this?
- I have searched the existing issues
- I have read the guide to filing a bug
Use case
When making custom widgets, it is often useful to use default values from standard Material UI widgets as default fall-back values for the custom widget from its equivalent standard version's theme properties.
Doing that currently involves looking up the correct fallback value for such properties from its corresponding standard Material UI Widget in the source code from its private classes that implement these default values, and then add them as hard coded own constants for its own M2 and/or M3 mode values.
It would be very useful if we could access the private default values contained in Material UI component class files. They are typically found at the end of every UI widget having the name structure _ComponentDefaultsM2
and _ComponentDefaultsM3
, where Component
is the name of the Material UI widget in question.
Before Material3 was added, the UI widget default values where spread all over Widget build methods. Getting access to them was not feasible and even finding the default values was very difficult. However, the Material3 addition/migration cleaned up all this and extracted the default values into own private classes that the Material UI widgets access to get their defaults from. It would thus now easily be possible and very useful to offer these values also externally.
Proposal
One possible way of doing this would be to add a static default theme value getter to each UI widget. For example in the AppBar
class we could have a static themeDefaults
getter like:
static AppBarTheme themeDefaults(BuildContext context) =>
Theme.of(context).useMaterial3
? _AppBarDefaultsM3(context)
: _AppBarDefaultsM2(context);
When we need to know what default values an AppBar
widget uses, we could read that by getting the default values with:
final AppBarTheme defaults = AppBar.themeDefaults(context);
Current Material UI components typically do this in their build, e.g. AppBar
final AppBarTheme defaults = theme.useMaterial3 ? _AppBarDefaultsM3(context) : _AppBarDefaultsM2(context); |
They could use same static internally going forward:
final AppBarTheme defaults = themeDefaults(context);
This was just one example, it should be added to all Material UI components that have default values provided via the private default value classes.
NOTE: The name of the static might need some consideration. We do no want the devs to confuse the
defaults
with the effective component theme of context values. To methemeDefaults
work well, butthemeFallback
might be an alternative, or something else even, naming is hard 😄
EDIT: Add precedent info below
Precedent: DatePicker
There is already a precedent for this pattern. The DatePicker
already offers it. However, the DatePicker
also differs in implementation style from all other Material UI widgets. The DatePicker has the private default M2/M3 value classes in the component theme file date_picker_theme.dart
and not in the component file date_picker.dart
like all other Material component widgets do.
In the date_picker_theme.dart
it has a static defaults
in the DatePickerTheme
, like so:
static DatePickerThemeData defaults(BuildContext context) { |
/// A DatePickerThemeData used as the default properties for date pickers.
///
/// This is only used for properties not already specified in the ambient
/// [DatePickerTheme.of].
///
/// See also:
///
/// * [of], which will return [ThemeData.datePickerTheme] if it doesn't
/// find a [DatePickerTheme] ancestor, instead of returning null.
/// * [maybeOf], which returns null if it doesn't find a
/// [DatePickerTheme] ancestor.
static DatePickerThemeData defaults(BuildContext context) {
return Theme.of(context).useMaterial3
? _DatePickerDefaultsM3(context)
: _DatePickerDefaultsM2(context);
}
The DatePicker
component implementation then use this static from the DatePickerTheme
to get the defaults:
final DatePickerThemeData defaults = DatePickerTheme.defaults(context); |
Why is DatePicker
implementation different? Is the intent to migrate all Material UI components to this model?
The DatePickerTheme
is one of the newest theme additions in the framework, so it would make sense if it is a new design, but it does not make sense if it is the only one using this pattern.
The static defaults
certainly fits even better in the component theme class, than in the component class. Moving all the private default value classes to the theme classes certainly works very well too, even better. No objections there, as long as we can have access to them.
cc: @TahaTesser