Skip to content

Commit 8bd3cc8

Browse files
committed
refactor: update navigation menus and form themes
This commit refactors the top navigation to use `DropdownMenu` and `MenuButton` for sub-items, enhancing the visual feedback for the active route. It also introduces a global theme for `MenuButton` and updates form component examples. ### Key Changes: * **Top Navigation (`top_navigation.dart`):** * Replaced the manual `Column` of `LightButton` widgets with a `DropdownMenu` containing `MenuButton` components. * Added visual indicators for the current active route within the dropdown, including a `mapPin` icon and specific text coloring (using `Colors.gray[400]`). * Enabled `enablePress` on the popover for better interactivity. * **Theme Overrides (`form_themes.dart`):** * Added a `MenuButtonTheme` to the global `ComponentTheme`. * Defined custom decorations for `MenuButton` based on widget states, specifically handling `disabled` and `hovered` states using the theme's muted color scheme. * **Form Components (`forms_screen.dart`):** * Updated the `Popover` example to include `enablePress: true`. * Added `autoClose: false` to a sub-menu button example. * Applied code formatting to improve readability of code snippets within the UI.
1 parent ff835c4 commit 8bd3cc8

3 files changed

Lines changed: 72 additions & 20 deletions

File tree

lib/screens/components/forms/forms_screen.dart

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,13 +51,16 @@ class _FormsScreenState extends State<FormsScreen> {
5151
label: const Text('Text-Feld'),
5252
validator: const LengthValidator(
5353
min: 3,
54-
message: 'Der Text muss mindestens 3 Zeichen lang sein',
54+
message:
55+
'Der Text muss mindestens 3 Zeichen lang sein',
5556
),
5657
showErrors: {
5758
FormValidationMode.changed,
5859
FormValidationMode.submitted,
5960
},
60-
child: const TextField(placeholder: Text('Ihr Text ...')),
61+
child: const TextField(
62+
placeholder: Text('Ihr Text ...'),
63+
),
6164
),
6265
onSubmit: (context, values) {},
6366
),
@@ -76,13 +79,17 @@ class _FormsScreenState extends State<FormsScreen> {
7679
CodeTextLine(" label: const Text('Text-Feld'),"),
7780
CodeTextLine(" validator: const LengthValidator("),
7881
CodeTextLine(" min: 3,"),
79-
CodeTextLine(" message: 'Der Text muss mindestens 3 Zeichen lang sein',"),
82+
CodeTextLine(
83+
" message: 'Der Text muss mindestens 3 Zeichen lang sein',",
84+
),
8085
CodeTextLine(" ),"),
8186
CodeTextLine(" showErrors: {"),
8287
CodeTextLine(" FormValidationMode.changed,"),
8388
CodeTextLine(" FormValidationMode.submitted,"),
8489
CodeTextLine(" },"),
85-
CodeTextLine(" child: const TextField(placeholder: Text('Ihr Text ...')),"),
90+
CodeTextLine(
91+
" child: const TextField(placeholder: Text('Ihr Text ...')),",
92+
),
8693
CodeTextLine(" ),"),
8794
CodeTextLine(" onSubmit: (context, values) {},"),
8895
CodeTextLine("),"),
@@ -123,7 +130,8 @@ class _FormsScreenState extends State<FormsScreen> {
123130
CodeTextLine(" label: const Text('Email'),"),
124131
CodeCommentLine(" # Validierung: Gültige Email-Adresse"),
125132
CodeTextLine(" validator: const EmailValidator("),
126-
CodeTextLine(" message: 'Bitte geben Sie eine gültige Email-Adresse ein',",
133+
CodeTextLine(
134+
" message: 'Bitte geben Sie eine gültige Email-Adresse ein',",
127135
),
128136
CodeTextLine(" ),"),
129137
CodeTextLine(" child: const TextField("),
@@ -168,7 +176,9 @@ class _FormsScreenState extends State<FormsScreen> {
168176
CodeTextLine(" key: birthdayKey,"),
169177
CodeTextLine(" label: const Text('Datum'),"),
170178
CodeTextLine(" validator: const NonNullValidator("),
171-
CodeTextLine(" message: 'Bitte geben Sie ein Datum ein',"),
179+
CodeTextLine(
180+
" message: 'Bitte geben Sie ein Datum ein',",
181+
),
172182
CodeTextLine(" ),"),
173183
CodeTextLine(" child: ControlledDatePicker("),
174184
CodeTextLine(" onChanged: (value) {},"),
@@ -236,6 +246,7 @@ class _FormsScreenState extends State<FormsScreen> {
236246
subMenu: [
237247
MenuButton(child: Text('Untermenü Option 2.1')),
238248
],
249+
autoClose: false,
239250
child: Text('Option 2'),
240251
),
241252
MenuDivider(),
@@ -245,6 +256,7 @@ class _FormsScreenState extends State<FormsScreen> {
245256
},
246257
anchorPlacement: Alignment.bottomCenter,
247258
placement: Alignment.topCenter,
259+
enablePress: true,
248260
hoverCloseDelay: const Duration(milliseconds: 500),
249261
),
250262
],
@@ -267,6 +279,7 @@ class _FormsScreenState extends State<FormsScreen> {
267279
" MenuButton(child: Text('Untermenü Option 2.1')),",
268280
),
269281
CodeTextLine(" ],"),
282+
CodeTextLine(" autoClose: false,"),
270283
CodeTextLine(" child: Text('Option 2'),"),
271284
CodeTextLine(" ),"),
272285
CodeTextLine(" MenuDivider(),"),
@@ -279,6 +292,7 @@ class _FormsScreenState extends State<FormsScreen> {
279292
CodeCommentLine(" # Wo am Menü der Ankerpunkt ist"),
280293
CodeTextLine(" placement: Alignment.topCenter,"),
281294
CodeCommentLine(" # Dauer, bis das Menü geschlossen wird"),
295+
CodeTextLine(" enablePress: true,"),
282296
CodeTextLine(
283297
" hoverCloseDelay: const Duration(milliseconds: 500),",
284298
),

lib/screens/widgets/layouts/widgets/top_navigation.dart

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -79,30 +79,51 @@ class TopNavigation extends StatelessWidget {
7979
),
8080
).withPopover(
8181
enabled: item.children.isNotEmpty,
82+
enablePress: true,
8283
offset: const Offset(0, -4),
8384
builder: (context) {
8485
return ModalContainer(
8586
padding: const EdgeInsets.symmetric(vertical: 8),
86-
child: Column(
87-
mainAxisSize: MainAxisSize.min,
87+
child: DropdownMenu(
8888
children: item.children
8989
.map(
90-
(subItem) => SizedBox(
91-
width: double.infinity,
92-
child: LightButton(
93-
onPressed: () => _onPressed(context, subItem),
94-
isIcon: false,
95-
isActive:
90+
(subItem) => MenuButton(
91+
onPressed: (context) {
92+
_onPressed(context, subItem);
93+
},
94+
enabled: subItem.index !=
95+
navigationShell.currentIndex,
96+
leading:
97+
subItem.index ==
98+
navigationShell.currentIndex
99+
? IconTheme(
100+
data: IconThemeData(
101+
color: Colors.gray[400],
102+
size: 16,
103+
),
104+
child: subItem.icon!,
105+
)
106+
: subItem.icon,
107+
trailing:
108+
subItem.index ==
109+
navigationShell.currentIndex
110+
? Icon(
111+
LucideIcons.mapPin,
112+
color: Colors.gray[400],
113+
)
114+
: null,
115+
child: Text(
116+
subItem.title,
117+
style:
96118
subItem.index ==
97-
navigationShell.currentIndex,
98-
borderRadius: 0,
99-
leading: subItem.icon,
100-
child: Text(subItem.title),
119+
navigationShell.currentIndex
120+
? TextStyle(color: Colors.gray[400])
121+
: null,
101122
),
102123
),
103124
)
104125
.toList(),
105-
).gap(5),
126+
),
106127
).intrinsicWidth();
107128
},
108129
)),

lib/screens/widgets/overrides/form_themes.dart

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,24 @@ class FormThemes extends StatelessWidget {
4545
inactiveColor: isDark ? Colors.gray[500] : Colors.gray[200],
4646
inactiveThumbColor: isDark ? Colors.gray[200] : Colors.blue[900],
4747
),
48-
child: child,
48+
child: ComponentTheme(
49+
data: MenuButtonTheme(
50+
decoration: (context, states, defaultDecoration) {
51+
var themeData = Theme.of(context);
52+
if (states.contains(WidgetState.hovered)) {
53+
return BoxDecoration(
54+
color: themeData.colorScheme.muted.scaleAlpha(0.8),
55+
borderRadius: BorderRadius.circular(themeData.radiusMd),
56+
);
57+
}
58+
return BoxDecoration(
59+
color: themeData.colorScheme.muted.withValues(alpha: 0),
60+
borderRadius: BorderRadius.circular(themeData.radiusMd),
61+
);
62+
},
63+
),
64+
child: child,
65+
),
4966
),
5067
),
5168
),

0 commit comments

Comments
 (0)