flex_color_scheme
flex_color_scheme copied to clipboard
NavigationDrawerDestination items do not follow theme background
The background color of NavigationDrawerDestination items do not follow the theme and the simulator.
This is how the them appears:
In the simlator it looks like this:
I took the theme code directly from the playground.
Example Code:
import 'package:flutter/material.dart';
import 'package:flex_color_scheme/flex_color_scheme.dart';
void main() {
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: theme(),
home: Scaffold(
appBar: AppBar(),
drawer: getNavDrawer(),
body: const Center(
child: Text('Hello World!'),
),
),
);
}
}
NavigationDrawer getNavDrawer() {
return const NavigationDrawer(children: [
NavigationDrawerDestination(icon: Icon(Icons.close), label: Text('Destination 1')),
NavigationDrawerDestination(icon: Icon(Icons.close), label: Text('Destination 2')),
NavigationDrawerDestination(icon: Icon(Icons.close), label: Text('Destination 3'))
]);
}
// Theme config for FlexColorScheme version 7.3.x. Make sure you use
// same or higher package version, but still same major version. If you
// use a lower package version, some properties may not be supported.
// In that case remove them after copying this theme to your app.
ThemeData theme() => FlexThemeData.light(
scheme: FlexScheme.materialBaseline,
surfaceMode: FlexSurfaceMode.levelSurfacesLowScaffold,
blendLevel: 7,
subThemesData: const FlexSubThemesData(
blendOnLevel: 10,
blendOnColors: false,
useTextTheme: true,
useM2StyleDividerInM3: true,
alignedDropdown: true,
useInputDecoratorThemeInDialogs: true,
),
visualDensity: FlexColorScheme.comfortablePlatformDensity,
useMaterial3: true,
swapLegacyOnMaterial3: true,
// To use the Playground font, add GoogleFonts package and uncomment
// fontFamily: GoogleFonts.notoSans().fontFamily,
);
Hi @mavriq-dev,
Thanks for this report. It is indeed a correct observation, it is also sadly expected behavior with current and latest Flutter version 3.19.2.
Let's study it and find out more.
We can repeat the same issue without FlexThemeData
with Flutter stable 3.19.2. Btw thanks for an excellent and to the point reproduction sample, that I can now easily change to vanilla Flutter and we get the same result:
import 'package:flutter/material.dart';
void main() {
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: theme(),
home: Scaffold(
appBar: AppBar(),
drawer: getNavDrawer(),
body: const Center(
child: Text('Hello World!'),
),
),
);
}
}
NavigationDrawer getNavDrawer() {
return const NavigationDrawer(children: [
NavigationDrawerDestination(
icon: Icon(Icons.close), label: Text('Destination 1')),
NavigationDrawerDestination(
icon: Icon(Icons.close), label: Text('Destination 2')),
NavigationDrawerDestination(
icon: Icon(Icons.close), label: Text('Destination 3'))
]);
}
ColorScheme scheme = ColorScheme.fromSeed(seedColor: Color(0xFF6750A4));
ThemeData theme() => ThemeData(
colorScheme: scheme,
navigationDrawerTheme: NavigationDrawerThemeData(
backgroundColor: scheme.surface,
),
);
And it looks the same:
So why does this happen?
It is because the Drawer
uses elevation
1 by default in M3 and the colorScheme.surface
color that it uses as background on the Material
it is built from, gets elevation tint based on elevation 1.
However, the NavigationDrawerDestination
now use the same background color colorScheme.surface
, but its items are not elevated, so they are using the closer to white version of unelevated colorScheme.surface
. If you set the NavigationDrawerThemeData.evelation
to 0, you can see that the colors match.
ThemeData theme() => ThemeData(
colorScheme: scheme,
navigationDrawerTheme: NavigationDrawerThemeData(
backgroundColor: scheme.surface,
elevation: 0,
),
);
The colors match:
But what if I want to use e.g. elevation 12? It would then look like this:
Not pretty and probably not what was expected either!
The simple workaround is to make the NavigationDrawerDestination
item backgrounds transparent
import 'package:flutter/material.dart';
void main() {
runApp(const MainApp());
}
class MainApp extends StatelessWidget {
const MainApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: theme(),
home: Scaffold(
appBar: AppBar(),
drawer: getNavDrawer(),
body: const Center(
child: Text('Hello World!'),
),
),
);
}
}
NavigationDrawer getNavDrawer() {
return const NavigationDrawer(children: [
NavigationDrawerDestination(
backgroundColor: Colors.transparent,
icon: Icon(Icons.close),
label: Text('Destination 1')),
NavigationDrawerDestination(
backgroundColor: Colors.transparent,
icon: Icon(Icons.close),
label: Text('Destination 2')),
NavigationDrawerDestination(
backgroundColor: Colors.transparent,
icon: Icon(Icons.close),
label: Text('Destination 3'))
]);
}
ColorScheme scheme = ColorScheme.fromSeed(seedColor: const Color(0xFF6750A4));
ThemeData theme() => ThemeData(
colorScheme: scheme,
navigationDrawerTheme: NavigationDrawerThemeData(
backgroundColor: scheme.surface,
elevation: 12,
),
);
But we are using themes and should not need to think about such things.
Here is a really interesting part. The published Themes Playground app does not do this with the NavigationDrawerDestination
items.
It looks like you showed:
and I double checked, I don't do any transparent color on the destinations in its code.
Wait, what is going on here?
Well Themes Playground live version was built back with Flutter SDK 3.13.1:
If I build it with latest Flutter SDK 3.19.2:
I get the same result and yes imo issue too!
As we already established this is what it looks like now with vanilla Flutter 3.19.2 as well. So it is not a FlexColorScheme issue.
What has happened?
Between Flutter version 3.13.1 and 3.19.2, somewhere along the way there was a change that caused this issue. It is perhaps an intentional change, but potentially also a regression.
The change has probably been caused by the color being transparent on the NavigationDrawerDestination
before, to it now being defined by the Material-3 spec token that has it at surface color.
https://m3.material.io/components/navigation-drawer/specs
Well actually the spec says it should be token md.sys.color.surface-container-low
as background when it is a modal Drawer. Which is a new color that does not exist in Flutter yet, but it is equivalent to the elevation level-1 tinted one.
All the elevation tints are going away in Material3 and Flutter too, in favor of precomputed surface shades for different usages. The token md.sys.color.surface-container-low
is one of those that should be on the modal Drawer and as background on its unselected items.
So if we would have that token color as background color and no elevation tint anymore, the new theme defaults would work and the colors would match, but since we don't, one gets elevation tint (drawer) and the destinations do not, and hence the colors do not match.
So yes, I think it is a Flutter bug/regression with too eager implementation of component theme behavior from token db, before Flutter actually support the needed new colors and behavior.
There is PR in Flutter SDK that is preparing the theme for massive changes. I tweeted about it here: https://x.com/RydMike/status/1761057220047909295?s=20
Conclusion
Sadly since this is a Flutter SDK issue and regression, there is not much I can do about it to fix it in FlexColorScheme. I will check if the issue has been reported in Flutter issues and report it as regression, if does not exist. I need to find the stable Flutter version where it broke.
I have not seen any breaking change notification about this, so it should at least be considered a regression.
BTW, thanks for the report, a very good find! 👍🏻 😄 💙
Even if this is "Flutter SDK" sourced and there is not much I can do about it here. I will keep it open so other can discover and learn about it too.
And I will link issue and progress in Flutter repo as well. I will also add it as known Flutter theming issues on my FlexColorScheme docs site.
Cool. At least I know why it happens and how to work around it. Thanks for the great explanation!