Skip to content

(BUG) Drawer border radius in Material3 in an RTL locale is on the wrong side #117759

@rydmike

Description

@rydmike

Drawer in M3 Mode Does Not Use Directionality

The Drawer in MaterialApp when used in MaterialApp.drawer and MaterialApp.endDrawer should have a rounded edge on the visible side in Material 3 design.

This works correctly in locale with LTR, but if you use a locale with RTL directionality, the edge rounding is drawn on the wrong side.

Expected results

Expect to get M3 rounded drawers like this in LTR:

Drawer LTR End Drawer LTR
Screenshot 2022-12-29 at 0 32 26 Screenshot 2022-12-29 at 0 32 41

Actual results

Drawer RTL End Drawer RTL
image image

Issue demo code

Requires adding

  flutter_localizations:
    sdk: flutter

under dependencies: to pubspec yaml.

Code sample
// MIT License
//
// Copyright (c) 2022 Mike Rydstrom
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';

// A seed color for M3 ColorScheme.
const Color seedColor = Color(0xff386a20);

// Example theme
ThemeData demoTheme(Brightness mode, bool useMaterial3) {
  // Make an M3 ColorScheme.from seed
  final ColorScheme scheme = ColorScheme.fromSeed(
    brightness: mode,
    seedColor: seedColor,
  );
  return ThemeData.from(
    colorScheme: scheme,
    useMaterial3: useMaterial3,
  );
}

void main() {
  runApp(const IssueDemoApp());
}

class IssueDemoApp extends StatefulWidget {
  const IssueDemoApp({super.key});

  @override
  State<IssueDemoApp> createState() => _IssueDemoAppState();
}

class _IssueDemoAppState extends State<IssueDemoApp> {
  bool useMaterial3 = true;
  ThemeMode themeMode = ThemeMode.light;
  TextDirection textDirection = TextDirection.ltr;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      themeMode: themeMode,
      locale: textDirection == TextDirection.ltr
          ? const Locale('en')
          : const Locale('ar'),
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const [
        Locale('en', ''), // English, no country code
        Locale('ar', ''), // Arabic, no country code
      ],
      theme: demoTheme(Brightness.light, useMaterial3),
      darkTheme: demoTheme(Brightness.dark, useMaterial3),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Drawer M3 RTL Issue'),
          actions: [
            IconButton(
              icon: useMaterial3
                  ? const Icon(Icons.filter_3)
                  : const Icon(Icons.filter_2),
              onPressed: () {
                setState(() {
                  useMaterial3 = !useMaterial3;
                });
              },
              tooltip: "Switch to Material ${useMaterial3 ? 2 : 3}",
            ),
            IconButton(
              icon: themeMode == ThemeMode.dark
                  ? const Icon(Icons.wb_sunny_outlined)
                  : const Icon(Icons.wb_sunny),
              onPressed: () {
                setState(() {
                  if (themeMode == ThemeMode.light) {
                    themeMode = ThemeMode.dark;
                  } else {
                    themeMode = ThemeMode.light;
                  }
                });
              },
              tooltip: "Toggle brightness",
            ),
            Builder(builder: (context) {
              return IconButton(
                icon: const Icon(Icons.menu),
                onPressed: () {
                  Scaffold.of(context).openEndDrawer();
                },
              );
            }),
          ],
        ),
        body: HomePage(
          textDirection: textDirection,
          onChanged: (TextDirection value) {
            setState(() {
              textDirection = value;
            });
          },
        ),
        drawer: const Drawer(
          child: Center(child: Text('Drawer')),
        ),
        endDrawer: const Drawer(
          child: Center(child: Text('End Drawer')),
        ),
      ),
    );
  }
}

class HomePage extends StatelessWidget {
  const HomePage({super.key, this.textDirection, this.onChanged});
  final TextDirection? textDirection;
  final ValueChanged<TextDirection>? onChanged;

  @override
  Widget build(BuildContext context) {
    final String materialType =
        Theme.of(context).useMaterial3 ? "Material 3" : "Material 2";
    return ListView(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      children: [
        const SizedBox(height: 8),
        Text(
          'Issue Demo - $materialType',
          style: Theme.of(context).textTheme.headlineSmall,
        ),
        const SizedBox(height: 16),
        const Text('Toggle to RTL locale in M3 and check Drawer'),
        const SizedBox(height: 16),
        LocaleButtons(
          textDirection: textDirection,
          onChanged: onChanged,
        ),
        const SizedBox(height: 16),
        const Text('The M3 edge border radius is on wrong side'),
      ],
    );
  }
}

class LocaleButtons extends StatelessWidget {
  const LocaleButtons({
    super.key,
    this.textDirection,
    this.onChanged,
  });
  final TextDirection? textDirection;
  final ValueChanged<TextDirection>? onChanged;

  @override
  Widget build(BuildContext context) {
    final List<bool> isSelected = <bool>[
      textDirection == TextDirection.rtl,
      textDirection == TextDirection.ltr,
    ];
    return ToggleButtons(
      isSelected: isSelected,
      onPressed: onChanged == null
          ? null
          : (int newIndex) {
              onChanged?.call(TextDirection.values[newIndex]);
            },
      children: const <Widget>[
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 16.0),
          child: Text('RTL'),
        ),
        Padding(
          padding: EdgeInsets.symmetric(horizontal: 16.0),
          child: Text('LTR'),
        ),
      ],
    );
  }
}

Flutter version

Channel master, 3.7.0-13.0.pre.104

Flutter doctor
 flutter doctor -v
[!] Flutter (Channel master, 3.7.0-13.0.pre.104, on macOS 13.0.1 22A400 darwin-arm64, locale en-US)
    • Flutter version 3.7.0-13.0.pre.104 on channel master at /Users/rydmike/fvm/versions/master
    • Upstream repository https://github.com/flutter/flutter.git
    • Framework revision 2783d31688 (2 hours ago), 2022-12-28 15:45:19 -0500
    • Engine revision 3655bf981d
    • Dart version 3.0.0 (build 3.0.0-70.0.dev)
    • DevTools version 2.20.0
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform
      update checks and upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
    • Android SDK at /Users/rydmike/Library/Android/sdk
    • Platform android-33, build-tools 33.0.0
    • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 14C18
    • CocoaPods version 1.11.3

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2021.3)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 11.0.13+0-b1751.21-8125866)

[✓] IntelliJ IDEA Community Edition (version 2022.3.1)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 71.2.6
    • Dart plugin version 223.8214.16

[✓] VS Code (version 1.73.1)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.54.0

[✓] Connected device (2 available)
    • macOS (desktop) • macos  • darwin-arm64   • macOS 13.0.1 22A400 darwin-arm64
    • Chrome (web)    • chrome • web-javascript • Google Chrome 108.0.5359.124

[✓] HTTP Host Availability
    • All required HTTP hosts are available


ping @TahaTesser another M3 issue, this one with Drawer and RTL.

Metadata

Metadata

Assignees

Labels

P2Important issues not at the top of the work lista: qualityA truly polished experiencef: material designflutter/packages/flutter/material repository.found in release: 3.7Found to occur in 3.7frameworkflutter/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 version

Type

No type

Projects

Status

Done (PR merged)

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions