Skip to content

NavigationRail with enlarged icons shows incorrect hover area in Material 3 #133799

@smith558

Description

@smith558

Is there an existing issue for this?

Steps to reproduce

[Almost] identical to #128005.

As you can see on the first destination there's a hover highlight that's off-center with the icon, while when the second destination is selected, the selected highlight is properly center-aligned with the icon. This makes a weird effect, especially when I hover my mouse over a selected destination.

Issues only with Material 3, Material 2 is working fine.

Example code with the issue shown in Flutter playground here https://dartpad.dev?id=5561be21023f4cc64cc4f0755191b30c.

Expected results

Both the selected and hovering highlighted areas should be centre-aligned.

Actual results

The hovering highlight is misaligned.
image
While the selected highlight is centre-aligned with the destination icon.
image

Code sample

Code sample
import 'package:english_words/english_words.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create: (context) => MyAppState(),
      child: MaterialApp(
        title: 'Namer App',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          useMaterial3: true,
          colorScheme: ColorScheme.fromSeed(seedColor: Colors.blueAccent),
        ),
        home: MyHomePage(),
      ),
    );
  }
}

class MyAppState extends ChangeNotifier {
  var current = WordPair.random();

  void getNext() {
    current = WordPair.random();
    notifyListeners();
  }

  var favorites = <WordPair>{};

  void toggleFavorite() {
    if (favorites.contains(current)) {
      favorites.remove(current);
    } else {
      favorites.add(current);
    }
    notifyListeners();
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  var selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Row(
        children: [
          SafeArea(
            child: NavigationRail(
              extended: false,
              destinations: [
                NavigationRailDestination(
                  icon: Icon(Icons.home, size: 50),
                  label: Text('Home'),
                  padding: EdgeInsets.symmetric(vertical: 8)
                ),
                NavigationRailDestination(
                  icon: Icon(Icons.favorite, size: 50),
                  label: Text('Favorites'),
                  padding: EdgeInsets.symmetric(vertical: 8)
                ),
              ],
              selectedIndex: selectedIndex,
              onDestinationSelected: (value) => setState(() {
                selectedIndex = value;
              }),
            ),
          ),
          Expanded(
            child: Container(
              color: Theme.of(context).colorScheme.primaryContainer,
              child: GeneratorPage(),
            ),
          ),
        ],
      ),
    );
  }
}

class GeneratorPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    var appState = context.watch<MyAppState>();
    var pair = appState.current;
    var theme = Theme.of(context);

    IconData icon;
    if (appState.favorites.contains(pair)) {
      icon = Icons.favorite;
    } else {
      icon = Icons.favorite_border;
    }

    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            'A random new word:',
            style: theme.textTheme.headlineSmall,
          ),
          SizedBox(height: 10),
          BigCard(pair: pair),
          SizedBox(height: 10),
          Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ElevatedButton.icon(
                  onPressed: () => appState.toggleFavorite(),
                  icon: Icon(icon),
                  label: Padding(
                    padding: const EdgeInsets.all(5.0),
                    child: Text('Like',
                        style: theme.textTheme.headlineSmall
                            ?.copyWith(color: theme.colorScheme.primary)),
                  )),
              SizedBox(width: 10),
              ElevatedButton(
                onPressed: () => appState.getNext(),
                child: Padding(
                  padding: const EdgeInsets.all(5.0),
                  child: Text('Next',
                      style: theme.textTheme.headlineSmall
                          ?.copyWith(color: theme.colorScheme.primary)),
                ),
              ),
            ],
          )
        ],
      ),
    );
  }
}

class BigCard extends StatelessWidget {
  const BigCard({
    super.key,
    required this.pair,
  });

  final WordPair pair;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return Card(
      color: theme.colorScheme.primary,
      elevation: 5,
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Text(
          pair.asPascalCase,
          style: theme.textTheme.displayMedium
              ?.copyWith(color: theme.colorScheme.onPrimary),
          semanticsLabel: '${pair.first} ${pair.second}',
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.13.2, on Ubuntu 23.04 6.2.0-31-generic, locale en_GB.UTF-8)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Chrome - develop for the web
[✓] Linux toolchain - develop for Linux desktop
[✓] Android Studio (version 2022.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2023.2)
[✓] VS Code (version unknown)
    ✗ Unable to determine VS Code version.
[✓] Connected device (2 available)
[✓] Network resources

• No issues found!

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work listf: material designflutter/packages/flutter/material repository.found in release: 3.13Found to occur in 3.13found in release: 3.14Found to occur in 3.14frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onr: fixedIssue is closed as already fixed in a newer versionteam-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

Type

No type

Projects

Status

Done (PR merged)

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions