1. 28 Feb, 2024 2 commits
  2. 27 Feb, 2024 2 commits
  3. 23 Feb, 2024 1 commit
  4. 22 Feb, 2024 1 commit
  5. 20 Feb, 2024 1 commit
  6. 06 Feb, 2024 1 commit
  7. 24 Jan, 2024 2 commits
  8. 22 Jan, 2024 2 commits
    • Jesús S Guerrero's avatar
      Revert "Remove hack from PageView." (#141977) · a3cd05c6
      Jesús S Guerrero authored
      Reverts flutter/flutter#141533
      
       b/321743868
      a3cd05c6
    • Hassan Toor's avatar
      [web] - Fix broken `TextField` in semantics mode when it's a sibling of `Navigator` (#138446) · 59e892d3
      Hassan Toor authored
      When a `TextField` is rendered before a `Navigator`, it breaks in semantics mode.  This is because the framework generates the incorrect semantics tree (excludes the TextField) and when that tree gets sent to the engine, we don't get the signal to create the corresponding `<input>` element.
      
      This happens for a few reasons:
      * `ModalBarrier` uses `BlockSemantics` to drop the semantics of routes beneath the current route in `Navigator`
      * `ModalBarrier` mistakenly recognizes the widget outside of the `Navigator` to be its sibling
      *  So we end up dropping the semantics node of the `TextField` rendered before it. 
      
      The fix is to let `Navigator` generate a semantics node so that `ModalBarrier` doesn't mistakenly think widgets outside of `Navigator` are its siblings.  
      
      `Navigator` doesn't currently do this, which causes all the nodes generated from its widget subtree to be directly attached to the parent semantics node above `Navigator` - since this is also the parent of `TextField`, it considers them siblings. 
      
      Fixes https://github.com/flutter/flutter/issues/129324
      59e892d3
  9. 19 Jan, 2024 1 commit
  10. 18 Jan, 2024 2 commits
  11. 12 Jan, 2024 3 commits
  12. 05 Jan, 2024 1 commit
    • Taha Tesser's avatar
      Fix scrollable `TabBar` expands to full width when the divider is removed (#140963) · 88016c11
      Taha Tesser authored
      fixes [TabBar Expands to full width of the screen isScrollable: true after upgrading to flutter 3.16.4](https://github.com/flutter/flutter/issues/140338)
      
      ---
      
      ## Description
      
      Fixes the scrollable `TabBar` width when the divider is removed. (when the divider height is set to `0` or divider color is set to `Colors.transparent`)
      
      ### Code sample
      
      <details>
      <summary>expand to view the code sample</summary> 
      
      ```dart
      import 'package:flutter/material.dart';
      
      void main() => runApp(const MyApp());
      
      class MyApp extends StatelessWidget {
        const MyApp({super.key});
      
        @override
        Widget build(BuildContext context) {
          const int tabsCount = 2;
      
          return MaterialApp(
            home: DefaultTabController(
              initialIndex: 1,
              length: tabsCount,
              child: Scaffold(
                appBar: AppBar(
                  title: const Text('TabBar Sample'),
                  bottom: PreferredSize(
                    preferredSize: const Size.fromHeight(48.0),
                    child: ColoredBox(
                      color: Theme.of(context).colorScheme.secondaryContainer,
                      child:  TabBar(
                        // dividerColor: Theme.of(context).colorScheme.onSurface,
                        dividerColor: Colors.transparent, // remove divider
                        // dividerHeight: 0, // remove divider
                        isScrollable: true,
                        tabAlignment: TabAlignment.center,
                        tabs: <Widget>[
                          for (int i = 0; i < tabsCount; i++)
                            Tab(
                              text: 'Tab $i',
                            ),
                        ],
                      ),
                    ),
                  ),
                ),
              ),
            ),
          );
        }
      }
      ```
      
      </details>
      
      ### Before
      ![Simulator Screenshot - iPhone 15 Pro - 2024-01-04 at 15 16 15](https://github.com/flutter/flutter/assets/48603081/b776e7e6-e5f0-49df-8a79-55032eaad631)
      
      ### After
      ![Simulator Screenshot - iPhone 15 Pro - 2024-01-04 at 15 16 23](https://github.com/flutter/flutter/assets/48603081/9ad13793-43a9-4ae8-977e-7cf84cb59bb1)
      88016c11
  13. 20 Dec, 2023 2 commits
  14. 15 Dec, 2023 1 commit
  15. 26 Oct, 2023 1 commit
  16. 19 Oct, 2023 1 commit
  17. 11 Oct, 2023 1 commit
  18. 28 Sep, 2023 1 commit
  19. 12 Sep, 2023 1 commit
  20. 07 Sep, 2023 1 commit
    • Taha Tesser's avatar
      Fix `TabBar` doesn't use `labelStyle` & `unselectedLabelStyle` color (#133989) · f5355af4
      Taha Tesser authored
      Fixes [TabBar labelStyle.color and unselectedLabelStyle.color does not take effect](https://github.com/flutter/flutter/issues/109484)
      
      ### Code sample
      
      <details>
      <summary>expand to view the code sample</summary> 
      
      ```dart
      import 'package:flutter/material.dart';
      
      /// Flutter code sample for [TabBar].
      
      const Color labelColor = Color(0xFFFF0000);
      const Color unselectedLabelColor = Color(0x95FF0000);
      const TextStyle labelStyle = TextStyle(
        color: Color(0xff0000ff),
        fontWeight: FontWeight.bold,
      );
      const TextStyle unselectedLabelStyle = TextStyle(
        color: Color(0x950000ff),
        fontStyle: FontStyle.italic,
      );
      
      void main() => runApp(const TabBarApp());
      
      class TabBarApp extends StatelessWidget {
        const TabBarApp({super.key});
      
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            theme: ThemeData(useMaterial3: true),
            home: const TabBarExample(),
          );
        }
      }
      
      class TabBarExample extends StatelessWidget {
        const TabBarExample({super.key});
      
        @override
        Widget build(BuildContext context) {
          return DefaultTabController(
            initialIndex: 1,
            length: 3,
            child: Scaffold(
              appBar: AppBar(
                title: const Text('TabBar Sample'),
                bottom: const TabBar(
                  // labelColor: labelColor,
                  // unselectedLabelColor: unselectedLabelColor,
                  labelStyle: labelStyle,
                  unselectedLabelStyle: unselectedLabelStyle,
                  tabs: <Widget>[
                    Tab(
                      icon: Icon(Icons.cloud_outlined),
                      text: 'Cloudy',
                    ),
                    Tab(
                      icon: Icon(Icons.beach_access_sharp),
                      text: 'Sunny',
                    ),
                    Tab(
                      icon: Icon(Icons.brightness_5_sharp),
                      text: 'Rainy',
                    ),
                  ],
                ),
              ),
              body: const TabBarView(
                children: <Widget>[
                  Center(
                    child: Text("It's cloudy here"),
                  ),
                  Center(
                    child: Text("It's rainy here"),
                  ),
                  Center(
                    child: Text("It's sunny here"),
                  ),
                ],
              ),
            ),
          );
        }
      }
      ```
      
      </details>
      
      #### When `labelStyle` and `unselectedLabelStyle` are specified with a color.
      
      ### Before
      ![image](https://github.com/flutter/flutter/assets/48603081/4138f928-aa63-40bc-9d4e-4d2aeefe72c1)
      
      ### After
      
      ![image](https://github.com/flutter/flutter/assets/48603081/2ce552c5-3972-4b5d-9492-eb487764e58f)
      f5355af4
  21. 05 Sep, 2023 1 commit
  22. 30 Aug, 2023 1 commit
  23. 10 Aug, 2023 1 commit
  24. 08 Aug, 2023 1 commit
    • Taha Tesser's avatar
      Fix `TabBarTheme.indicatorColor` not applied in Material 2 (#132123) · ee47267d
      Taha Tesser authored
      fixes [[Proposal] Improve TabBarTheme styling API for indicator color ](https://github.com/flutter/flutter/issues/130392)
      
      ### Description
      
      This fixes an issue where the `TabBarTheme.indicator` isn't applied in Material 2 and also adds indicator color tests for both M3 and M2.
      
      ### Code sample
      
      <details> 
      <summary>expand to view the code sample</summary> 
      
      ```dart
      import 'package:flutter/material.dart';
      
      /// Flutter code sample for [TabBar].
      
      void main() => runApp(const TabBarApp());
      
      class TabBarApp extends StatelessWidget {
        const TabBarApp({super.key});
      
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            theme: ThemeData(
              useMaterial3: false,
              tabBarTheme: const TabBarTheme(
                indicatorColor: Colors.amber,
              )
            ),
            home: const TabBarExample(),
          );
        }
      }
      
      class TabBarExample extends StatelessWidget {
        const TabBarExample({super.key});
      
        @override
        Widget build(BuildContext context) {
          return DefaultTabController(
            initialIndex: 1,
            length: 3,
            child: Scaffold(
              appBar: AppBar(
                title: const Text('TabBar Sample'),
                bottom: const TabBar(
                  tabs: <Widget>[
                    Tab(
                      icon: Icon(Icons.cloud_outlined),
                      text: 'Cloudy',
                    ),
                    Tab(
                      icon: Icon(Icons.beach_access_sharp),
                      text: 'Sunny',
                    ),
                    Tab(
                      icon: Icon(Icons.brightness_5_sharp),
                      text: 'Rainy',
                    ),
                  ],
                ),
              ),
              body: const TabBarView(
                children: <Widget>[
                  Center(
                    child: Text("It's cloudy here"),
                  ),
                  Center(
                    child: Text("It's rainy here"),
                  ),
                  Center(
                    child: Text("It's sunny here"),
                  ),
                ],
              ),
            ),
          );
        }
      }
      ``` 
      	
      </details>
      
      ### Before
      ![Screenshot 2023-08-08 at 15 39 24](https://github.com/flutter/flutter/assets/48603081/9030e025-8615-45d0-a337-87ba2fdf6ca3)
      
      ### After
      ![Screenshot 2023-08-08 at 15 39 07](https://github.com/flutter/flutter/assets/48603081/4b98ac55-2d51-4a4c-93ba-7d36dc4be1d8)
      ee47267d
  25. 07 Aug, 2023 1 commit
  26. 02 Aug, 2023 1 commit
    • Taha Tesser's avatar
      Fix Scrollable `TabBar` for Material 3 (#131409) · 2c71881f
      Taha Tesser authored
      fixes [Material 3 `TabBar` does not take full width when `isScrollable: true`](https://github.com/flutter/flutter/issues/117722)
      
      ### Description
      1. Fixed the divider doesn't stretch to take all the available width in the scrollable tab bar in M3
      2. Added `dividerHeight` property.
      
      ### Code sample
      
      <details> 
      <summary>expand to view the code sample</summary> 
      
      ```dart
      import 'package:flutter/material.dart';
      
      /// Flutter code sample for [TabBar].
      
      void main() => runApp(const TabBarApp());
      
      class TabBarApp extends StatelessWidget {
        const TabBarApp({super.key});
      
        @override
        Widget build(BuildContext context) {
          return const MaterialApp(
            debugShowCheckedModeBanner: false,
            home: TabBarExample(),
          );
        }
      }
      
      class TabBarExample extends StatefulWidget {
        const TabBarExample({super.key});
      
        @override
        State<TabBarExample> createState() => _TabBarExampleState();
      }
      
      class _TabBarExampleState extends State<TabBarExample> {
        bool rtl = false;
        bool customColors = false;
        bool removeDivider = false;
        Color dividerColor = Colors.amber;
        Color indicatorColor = Colors.red;
      
        @override
        Widget build(BuildContext context) {
          return DefaultTabController(
            initialIndex: 1,
            length: 3,
            child: Directionality(
              textDirection: rtl ? TextDirection.rtl : TextDirection.ltr,
              child: Scaffold(
                appBar: AppBar(
                  title: const Text('TabBar Sample'),
                  actions: <Widget>[
                    IconButton.filledTonal(
                      tooltip: 'Switch direction',
                      icon: const Icon(Icons.swap_horiz),
                      onPressed: () {
                        setState(() {
                          rtl = !rtl;
                        });
                      },
                    ),
                    IconButton.filledTonal(
                      tooltip: 'Use custom colors',
                      icon: const Icon(Icons.color_lens),
                      onPressed: () {
                        setState(() {
                          customColors = !customColors;
                        });
                      },
                    ),
                    IconButton.filledTonal(
                      tooltip: 'Show/hide divider',
                      icon: const Icon(Icons.remove_rounded),
                      onPressed: () {
                        setState(() {
                          removeDivider = !removeDivider;
                        });
                      },
                    ),
                  ],
                ),
                body: Column(
                  children: <Widget>[
                    const Spacer(),
                    const Text('Scrollable - TabAlignment.start'),
                    TabBar(
                      isScrollable: true,
                      tabAlignment: TabAlignment.start,
                      dividerColor: customColors ? dividerColor : null,
                      indicatorColor: customColors ? indicatorColor : null,
                      dividerHeight: removeDivider ? 0 : null,
                      tabs: const <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    const Text('Scrollable - TabAlignment.startOffset'),
                    TabBar(
                      isScrollable: true,
                      tabAlignment: TabAlignment.startOffset,
                      dividerColor: customColors ? dividerColor : null,
                      indicatorColor: customColors ? indicatorColor : null,
                      dividerHeight: removeDivider ? 0 : null,
                      tabs: const <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    const Text('Scrollable - TabAlignment.center'),
                    TabBar(
                      isScrollable: true,
                      tabAlignment: TabAlignment.center,
                      dividerColor: customColors ? dividerColor : null,
                      indicatorColor: customColors ? indicatorColor : null,
                      dividerHeight: removeDivider ? 0 : null,
                      tabs: const <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    const Spacer(),
                    const Text('Non-scrollable - TabAlignment.fill'),
                    TabBar(
                      tabAlignment: TabAlignment.fill,
                      dividerColor: customColors ? dividerColor : null,
                      indicatorColor: customColors ? indicatorColor : null,
                      dividerHeight: removeDivider ? 0 : null,
                      tabs: const <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    const Text('Non-scrollable - TabAlignment.center'),
                    TabBar(
                      tabAlignment: TabAlignment.center,
                      dividerColor: customColors ? dividerColor : null,
                      indicatorColor: customColors ? indicatorColor : null,
                      dividerHeight: removeDivider ? 0 : null,
                      tabs: const <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    const Spacer(),
                    const Text('Secondary - TabAlignment.fill'),
                    TabBar.secondary(
                      tabAlignment: TabAlignment.fill,
                      dividerColor: customColors ? dividerColor : null,
                      indicatorColor: customColors ? indicatorColor : null,
                      dividerHeight: removeDivider ? 0 : null,
                      tabs: const <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    const Text('Secondary - TabAlignment.center'),
                    TabBar.secondary(
                      tabAlignment: TabAlignment.center,
                      dividerColor: customColors ? dividerColor : null,
                      indicatorColor: customColors ? indicatorColor : null,
                      dividerHeight: removeDivider ? 0 : null,
                      tabs: const <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    const Spacer(),
                  ],
                ),
              ),
            ),
          );
        }
      }
      ``` 
      	
      </details>
      
      ### Before
      
      ![Screenshot 2023-07-27 at 14 12 36](https://github.com/flutter/flutter/assets/48603081/1c08a9d2-ac15-4d33-8fa1-c765b4b10f92)
      
      ### After 
      
      ![Screenshot 2023-07-27 at 14 13 12](https://github.com/flutter/flutter/assets/48603081/7e662dfe-9f32-46c9-a128-3024a4782882)
      
      This also contains regression test for https://github.com/flutter/flutter/pull/125974#discussion_r1239089151
      
      ```dart
        // This is a regression test for https://github.com/flutter/flutter/pull/125974#discussion_r1239089151.
        testWidgets('Divider can be constrained', (WidgetTester tester) async {
      ```
      
      ![Screenshot 2023-07-27 at 14 16 37](https://github.com/flutter/flutter/assets/48603081/ac2ef49b-2410-46d0-8ae2-d9b77236abba)
      2c71881f
  27. 14 Jul, 2023 1 commit
  28. 22 Jun, 2023 2 commits
    • Kate Lovett's avatar
      Revert "Fix Material 3 Scrollable `TabBar`" (#129383) · 087377ea
      Kate Lovett authored
      Reverts flutter/flutter#125974
      087377ea
    • Taha Tesser's avatar
      Fix Material 3 Scrollable `TabBar` (#125974) · 32fde139
      Taha Tesser authored
      fix https://github.com/flutter/flutter/issues/117722
      
      ### Description
      1. Fix the divider doesn't stretch to take all the available width in the scrollable tab bar in M3
      2. Add `dividerHeight` property.
      3. Update the default tab alignment for the scrollable tab bar to match the specs (this is backward compatible for M2 with the new `tabAlignment` property).
      
      ### Bug (default tab alignment)
      
      ![Screenshot 2023-05-05 at 19 04 40](https://user-images.githubusercontent.com/48603081/236509483-1d03af21-a764-4776-acef-2126560f0d51.png)
      
      ### Fix (default tab alignment)
      
      ![Screenshot 2023-05-05 at 19 04 15](https://user-images.githubusercontent.com/48603081/236509513-2426d456-c54f-42bd-9545-a14dc6ee7e69.png)
      
      ### Code sample
      
      <details> 
      <summary>code sample</summary> 
      
      ```dart
      import 'package:flutter/material.dart';
      
      /// Flutter code sample for [TabBar].
      
      void main() => runApp(const TabBarApp());
      
      class TabBarApp extends StatelessWidget {
        const TabBarApp({super.key});
      
        @override
        Widget build(BuildContext context) {
          return MaterialApp(
            theme: ThemeData(
              //  tabBarTheme: const TabBarTheme(tabAlignment: TabAlignment.start),
                useMaterial3: true,
            ),
            home: const TabBarExample(),
          );
        }
      }
      
      class TabBarExample extends StatefulWidget {
        const TabBarExample({super.key});
      
        @override
        State<TabBarExample> createState() => _TabBarExampleState();
      }
      
      class _TabBarExampleState extends State<TabBarExample> {
        bool rtl = false;
      
        @override
        Widget build(BuildContext context) {
          return DefaultTabController(
            initialIndex: 1,
            length: 3,
            child: Directionality(
              textDirection:  rtl ? TextDirection.rtl : TextDirection.ltr,
              child: Scaffold(
                appBar: AppBar(
                  title: const Text('TabBar Sample'),
                ),
                body: const Column(
                  children: <Widget>[
                    Text('Scrollable-TabAlignment.start'),
                    TabBar(
                      isScrollable: true,
                      tabAlignment: TabAlignment.start,
                      tabs: <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    Text('Scrollable-TabAlignment.startOffset'),
                    TabBar(
                      isScrollable: true,
                      tabAlignment: TabAlignment.startOffset,
                      tabs: <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    Text('Scrollable-TabAlignment.center'),
                    TabBar(
                      isScrollable: true,
                      tabAlignment: TabAlignment.center,
                      tabs: <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    Spacer(),
                    Text('Non-scrollable-TabAlignment.fill'),
                    TabBar(
                      tabAlignment: TabAlignment.fill,
                      tabs: <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    Text('Non-scrollable-TabAlignment.center'),
                    TabBar(
                      tabAlignment: TabAlignment.center,
                      tabs: <Widget>[
                        Tab(
                          icon: Icon(Icons.cloud_outlined),
                        ),
                        Tab(
                          icon: Icon(Icons.beach_access_sharp),
                        ),
                        Tab(
                          icon: Icon(Icons.brightness_5_sharp),
                        ),
                      ],
                    ),
                    Spacer(),
                  ],
                ),
                floatingActionButton: FloatingActionButton.extended(
                  onPressed: () {
                    setState(() {
                      rtl = !rtl;
                    });
                  },
                  label: const Text('Switch Direction'),
                  icon: const Icon(Icons.swap_horiz),
                ),
              ),
            ),
          );
        }
      }
      ``` 
      	
      </details>
      
      ![Screenshot 2023-06-06 at 18 06 12](https://github.com/flutter/flutter/assets/48603081/5ee5386d-cc64-4025-a020-ed2222cb6031)
      32fde139
  29. 13 Jun, 2023 1 commit
    • Qun Cheng's avatar
      Update unit tests in material library for Material 3 (#128725) · a5f8b64e
      Qun Cheng authored
      Updates most of the unit tests in the packages/flutter/test/material folder so that they'll pass if ThemeData.useMaterial3 defaults to true.
      
      All of the tests have wired useMaterial3 to false and will need to be updated with a M3 version.
      
      related to #127064
      a5f8b64e
  30. 30 May, 2023 1 commit
  31. 26 May, 2023 1 commit