Fix collapsed mode bug and update navigation rail theme properties

This commit is contained in:
Emily Pauli 2025-10-26 15:39:17 +01:00
commit 27b1dfd9ef
9 changed files with 47 additions and 24 deletions

View file

@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:m3e_design/m3e_design.dart';
import 'app_bar_m3e_enums.dart';
@immutable
@ -24,7 +25,8 @@ class _AppBarMetrics {
_AppBarMetrics metricsFor(BuildContext context, AppBarM3EDensity density) {
final theme = Theme.of(context);
final m3e = theme.extension<M3ETheme>() ?? M3ETheme.defaults(theme.colorScheme);
final m3e =
theme.extension<M3ETheme>() ?? M3ETheme.defaults(theme.colorScheme);
final sp = m3e.spacing;
// Heights (approx per M3 specs; can be tuned via Theme extension in m3e_design if desired)
@ -54,21 +56,26 @@ _AppBarMetrics metricsFor(BuildContext context, AppBarM3EDensity density) {
Color backgroundFor(BuildContext context) {
final theme = Theme.of(context);
final m3e = theme.extension<M3ETheme>() ?? M3ETheme.defaults(theme.colorScheme);
final m3e =
theme.extension<M3ETheme>() ?? M3ETheme.defaults(theme.colorScheme);
// Prefer container surfaces for bars
return m3e.colors.surfaceContainerHigh;
}
TextStyle titleStyleFor(BuildContext context, {bool collapsed = true}) {
final theme = Theme.of(context);
final m3e = theme.extension<M3ETheme>() ?? M3ETheme.defaults(theme.colorScheme);
final m3e =
theme.extension<M3ETheme>() ?? M3ETheme.defaults(theme.colorScheme);
return collapsed ? m3e.type.titleLarge : m3e.type.headlineSmallEmphasized;
}
ShapeBorder shapeFor(BuildContext context, AppBarM3EShapeFamily family) {
final theme = Theme.of(context);
final m3e = theme.extension<M3ETheme>() ?? M3ETheme.defaults(theme.colorScheme);
final set = family == AppBarM3EShapeFamily.round ? m3e.shapes.round : m3e.shapes.square;
final m3e =
theme.extension<M3ETheme>() ?? M3ETheme.defaults(theme.colorScheme);
final set = family == AppBarM3EShapeFamily.round
? m3e.shapes.round
: m3e.shapes.square;
// Use medium size radius for the bar container by default
return RoundedRectangleBorder(borderRadius: set.md);
return RoundedRectangleBorder(borderRadius: set.sm);
}

View file

@ -1,6 +1,6 @@
name: app_bar_m3e
description: Expressive App Bar (Material 3 Expressive) with small/medium/large variants and Sliver integration.
version: 0.1.1
version: 0.1.2
repository: https://github.com/EmilyMoonstone/material_3_expressive/tree/main/packages/app_bar_m3e
issue_tracker: https://github.com/EmilyMonestone/material_3_expressive/issues

View file

@ -20,7 +20,7 @@ dependencies:
m3e_design: ^0.2.1
material_new_shapes: ^1.0.0
navigation_bar_m3e: ^0.1.1
navigation_rail_m3e: ^0.3.4
navigation_rail_m3e: ^0.3.5
progress_indicator_m3e: ^0.1.1
slider_m3e: ^0.1.1
split_button_m3e: ^0.2.1

View file

@ -1,3 +1,6 @@
## 0.3.5
- fix bug with collapsed mode
## 0.3.4
- add optional background parameter to NavigationRailM3E

View file

@ -441,8 +441,11 @@ class _NavigationRailM3EState extends State<NavigationRailM3E>
final all = widget.sections.expand((s) => s.destinations).toList();
for (int i = 0; i < all.length; i++) {
children.add(Padding(
padding: const EdgeInsetsDirectional.only(
start: 16.0, end: 16.0, top: 8.0, bottom: 8.0),
padding: EdgeInsetsDirectional.only(
start: 16.0,
end: 16.0,
top: theme.itemVerticalGap,
bottom: theme.itemVerticalGap),
child: RailItem(
destination: all[i],
selected: i == widget.selectedIndex,

View file

@ -36,9 +36,8 @@ class RailItem extends StatelessWidget {
Widget build(BuildContext context) {
final theme = Theme.of(context).extension<NavigationRailM3ETheme>() ??
const NavigationRailM3ETheme();
final height = destination.short
? theme.itemCollapsedHeight
: theme.itemExpandedHeight;
final height =
expanded ? theme.itemExpandedHeight : theme.itemCollapsedHeight;
final Widget button = RailItemButtonM3E(
icon: destination.icon,

View file

@ -20,6 +20,7 @@ class RailItemButtonM3E extends StatelessWidget {
this.semanticLabel,
this.suppressInk = false,
this.badgeCount,
this.heightOverride,
});
/// Icon to display.
@ -52,16 +53,22 @@ class RailItemButtonM3E extends StatelessWidget {
/// Optional numeric badge value to show.
final int? badgeCount;
/// Optional min height to enforce for the tap target. When null, defaults
/// to the theme's [NavigationRailM3ETheme.itemExpandedHeight] or
/// [itemCollapsedHeight] depending on [expanded].
final double? heightOverride;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context).extension<NavigationRailM3ETheme>() ??
const NavigationRailM3ETheme();
final tokens = NavigationRailTokensAdapter(context);
final double height =
expanded ? theme.itemCollapsedHeight : theme.itemCollapsedHeight;
final bool selected = isSelected;
final double defaultHeight =
expanded ? theme.itemExpandedHeight : theme.itemCollapsedHeight;
final double height = heightOverride ?? defaultHeight;
final bool selected = isSelected;
// Colors and shape per state.
final Color fg =
selected ? tokens.activeIconAndLabel : tokens.inactiveIconAndLabel;
@ -76,8 +83,10 @@ class RailItemButtonM3E extends StatelessWidget {
Widget content;
if (expanded) {
final textExpended = Flexible(
final textExpanded = Flexible(
child: DefaultTextStyle.merge(
// Use a readable style in expanded mode.
style: Theme.of(context).textTheme.labelLarge!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
child: Text(label, semanticsLabel: semanticLabel ?? label),
@ -95,7 +104,7 @@ class RailItemButtonM3E extends StatelessWidget {
child: effectiveIcon,
),
SizedBox(width: theme.iconLabelGap),
textExpended,
textExpanded,
],
),
),
@ -138,15 +147,17 @@ class RailItemButtonM3E extends StatelessWidget {
);
}
// Material/Ink wrapper. Respect [suppressInk] to avoid flicker during transitions.
final bool noInk = suppressInk || !expanded;
final Material material = Material(
color: bg,
shape: shape,
clipBehavior: Clip.antiAlias,
child: InkWell(
onTap: onPressed,
splashFactory: expanded ? null : NoSplash.splashFactory,
hoverColor: expanded ? null : Colors.transparent,
highlightColor: expanded ? null : Colors.transparent,
splashFactory: noInk ? NoSplash.splashFactory : null,
hoverColor: noInk ? Colors.transparent : null,
highlightColor: noInk ? Colors.transparent : null,
child: Padding(
// Horizontal padding similar to ButtonM3E sm; for collapsed, none.
padding: expanded

View file

@ -10,12 +10,12 @@ class NavigationRailM3ETheme extends ThemeExtension<NavigationRailM3ETheme> {
this.expandedMinWidth = 220.0,
this.expandedMaxWidth = 360.0,
this.itemExpandedHeight = 40.0,
this.itemCollapsedHeight = 56.0,
this.itemCollapsedHeight = 66.0,
this.iconSize = 24.0,
this.indicatorLeading = 16.0,
this.indicatorTrailing = 16.0,
this.iconLabelGap = 8.0,
this.itemVerticalGap = 6.0,
this.itemVerticalGap = 4.0,
this.headerMinSpace = 40.0,
this.sectionHeaderSpacingTop = 12.0,
this.sectionHeaderSpacingBottom = 8.0,

View file

@ -1,6 +1,6 @@
name: navigation_rail_m3e
description: Material 3 Expressive navigation rail (collapsed & expanded) with modal/standard modes, badges, sections, and m3e_design token integration.
version: 0.3.4
version: 0.3.5
homepage: https://github.com/EmilyMonestone/material_3_expressive
repository: https://github.com/EmilyMoonstone/material_3_expressive/tree/main/packages/navigation_rail_m3e
issue_tracker: https://github.com/EmilyMonestone/material_3_expressive/issues