forked from mirrors/material_3_expressive
Update NavigationRailM3E implementation; update FAB and navigation sections to adapt to changes.
This commit is contained in:
parent
1cb404b4df
commit
83f5a02943
49 changed files with 1651 additions and 661 deletions
|
|
@ -1,84 +1,51 @@
|
|||
# navigation_rail_m3e
|
||||
|
||||
Material 3 **Expressive** Navigation Rail for Flutter with badges, pill/stripe indicators, and token-driven styling.
|
||||
Material 3 **Expressive** Navigation Rail for Flutter — featuring **collapsed** & **expanded** variants,
|
||||
**modal** and **standard** presentation, **sections**, **badges**, **menu** and **FAB** slots, and smooth
|
||||
**expand/collapse transitions**. Built to match the M3 Expressive spec and integrate with the `m3e_design`
|
||||
token package.
|
||||
|
||||
- `NavigationRailM3E` — wrapper around Flutter's `NavigationRail` with M3E tokens
|
||||
- `RailDestinationM3E` — destination data (icon, selectedIcon, label, badge)
|
||||
- `RailBadgeM3E` — small badge/dot utility for icons
|
||||
<img src="https://raw.githubusercontent.com/EmilyMonestone/material_3_expressive/main/.github/images/nav_rail_m3e_cover.png" width="980"/>
|
||||
|
||||
All styling is driven by the `m3e_design` ThemeExtension (**M3ETheme**).
|
||||
## Highlights
|
||||
|
||||
## Monorepo Layout
|
||||
- Collapsed (96 dp) and Expanded (220–360 dp) rails with animated transition
|
||||
- Expanded **modal** presentation with scrim
|
||||
- Optional menu and FAB/Extended FAB slots
|
||||
- Item badges (large numeric & small dot)
|
||||
- Sections with headers; full-width hit targets
|
||||
- Token-driven colors, typography & shapes via `m3e_design` (with safe fallbacks)
|
||||
|
||||
```
|
||||
packages/
|
||||
m3e_design/
|
||||
navigation_rail_m3e/
|
||||
```
|
||||
|
||||
`pubspec.yaml` references `../m3e_design`.
|
||||
|
||||
## Usage
|
||||
## Quick start
|
||||
|
||||
```dart
|
||||
import 'package:navigation_rail_m3e/navigation_rail_m3e.dart';
|
||||
|
||||
final items = [
|
||||
const RailDestinationM3E(
|
||||
icon: Icon(Icons.inbox_outlined),
|
||||
selectedIcon: Icon(Icons.inbox),
|
||||
label: 'Inbox',
|
||||
),
|
||||
const RailDestinationM3E(
|
||||
icon: Icon(Icons.chat_bubble_outline),
|
||||
label: 'Chat',
|
||||
badgeCount: 5,
|
||||
),
|
||||
const RailDestinationM3E(
|
||||
icon: Icon(Icons.settings_outlined),
|
||||
label: 'Settings',
|
||||
badgeDot: true,
|
||||
),
|
||||
];
|
||||
|
||||
NavigationRailM3E(
|
||||
destinations: items,
|
||||
type: NavigationRailM3EType.expanded,
|
||||
modality: NavigationRailM3EModality.standard,
|
||||
selectedIndex: 0,
|
||||
onDestinationSelected: (i) {},
|
||||
labelBehavior: RailLabelBehavior.onlySelected, // none | onlySelected | alwaysShow
|
||||
indicatorStyle: RailIndicatorStyle.pill, // pill | stripe | none
|
||||
size: RailSize.regular, // compact | regular
|
||||
density: RailDensity.regular, // regular | compact
|
||||
shapeFamily: RailShapeFamily.round, // round | square
|
||||
extended: false, // true to show labels permanently (wide rail)
|
||||
groupAlignment: -1.0, // -1 top .. 1 bottom
|
||||
leading: const Padding(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
child: FlutterLogo(size: 24),
|
||||
),
|
||||
onDestinationSelected: (i) => setState(() => _index = i),
|
||||
onTypeChanged: (t) => setState(() => type = t),
|
||||
fab: NavigationRailM3EFabSlot(icon: const Icon(Icons.add), label: 'New', onPressed: () {}),
|
||||
sections: [
|
||||
NavigationRailM3ESection(
|
||||
header: const Text('Main'),
|
||||
destinations: [
|
||||
NavigationRailM3EDestination(
|
||||
icon: const Icon(Icons.edit_outlined),
|
||||
selectedIcon: const Icon(Icons.edit),
|
||||
label: 'Edit',
|
||||
largeBadgeCount: 0,
|
||||
),
|
||||
NavigationRailM3EDestination(
|
||||
icon: const Icon(Icons.star_outline),
|
||||
selectedIcon: const Icon(Icons.star),
|
||||
label: 'Starred',
|
||||
smallBadge: true,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
```
|
||||
|
||||
## Tokens mapping
|
||||
|
||||
- **Container**: `surfaceContainerHigh`
|
||||
- **Indicator**: `secondaryContainer` (color). `pill` uses NavigationRail's indicator; `stripe` draws a left border on the selected icon.
|
||||
- **Selected**: `onSecondaryContainer` (icon/label)
|
||||
- **Unselected**: `onSurfaceVariant`
|
||||
- **Label style**: `labelMedium`
|
||||
- **Widths**: compact **≈64dp**, regular **≈80dp**, extended min **≈256dp**
|
||||
- **Icon size**: **24dp**
|
||||
- **Item padding**: from `spacing.sm/md`
|
||||
|
||||
## Badges
|
||||
|
||||
Use `badgeCount` for numeric badges or `badgeDot: true` for a small dot. Colors default to `errorContainer / onErrorContainer` and can be overridden via `RailBadgeM3E`.
|
||||
|
||||
## Accessibility
|
||||
|
||||
- Provide `semanticLabel` per destination (used as tooltip) or on the rail (`semanticLabel` on the widget).
|
||||
- Choose the label behavior to balance density with readability.
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
See the `/example` app for a runnable demo.
|
||||
Loading…
Add table
Add a link
Reference in a new issue