Repository: flutter
Issue: Umbrella issue for matching HIGs tab bars
Labels: framework,f: cupertino,team-design

Ideally Flutter developers can use the widgets in our framework to create similar, if not identical, UI components to those in SwiftUI / Apple's HIGs. This issue documents what's off or missing to match SwiftUI tab views using `CupertinoTabBar` and Material `BottomNavigationBar` and `NavigationBar`

**`CupertinoTabBar`**
*Note that this video shows a comparison of the SwiftUI tab views and the CupertinoTabBar in a forked version of the overlay tool. You can see the exact code [here](https://github.com/leighajarett/xplatform_audit/blob/main/lib/Widgets/TabBars.dart#L60). When "a" is fully to the right, we are looking at SwiftUI, when it has been slid to the left, we are looking at Cupertino*

https://user-images.githubusercontent.com/21065911/231491838-49059cb5-91c9-46c4-8eb2-d43564645274.mov

- [ ] In SwiftUI, the TabView appearance changes based on whether or not content has scrolled under, in CupertinoBottomNavigationBar, the border and background color resembles the "scrolled under" state of SwiftUI even when content is not scrolled under
- [ ] In SwiftUI, the TabView icons are smaller, and in general the Cupertino icons seem out of date
- [ ] The font doesn't match up, likely due to this existing issue: #63507 

**`BottomNavigationBar`**
*Note that this video shows a comparison of the SwiftUI tab views and the Material BottomNavigationBar in a forked version of the overlay tool. You can see the exact code [here](https://github.com/leighajarett/xplatform_audit/blob/main/lib/Widgets/TabBars.dart#L140). When "a" is fully to the right, we are looking at SwiftUI, when it has been slid to the left, we are looking at Material*

https://user-images.githubusercontent.com/21065911/231494577-2deb4a32-5932-469b-9dbc-32d17828769c.mov

- [ ] Can't control the padding between the label and the icon, or between the label / icon and the bottom of the screen
- [ ] Can't directly control the border or the height (but you can wrap with a container / box decoration)
- [ ] Can't control the splash effect when selecting the tabs
- [ ] Can't control the styling based on whether or not content is scrolled under

**`NavigationBar`**
*Note that this video shows a comparison of the SwiftUI tab views and the Material NavigationBar in a forked version of the overlay tool. You can see the exact code [here](https://github.com/leighajarett/xplatform_audit/blob/main/lib/Widgets/TabBars.dart#L140). When "a" is fully to the right, we are looking at SwiftUI, when it has been slid to the left, we are looking at Material*


https://user-images.githubusercontent.com/21065911/231517562-4cc64860-6c11-4762-ae9b-025d9d75dbf0.mov


- [ ] Can't control the label styling while also removing the indicator shape, I tried to make the indicator color transparent but then we can't even see the label or icon when selected
- [ ] Can't control the padding between the label and the icon, or between the label / icon and the bottom of the screen
- [ ] Can't directly control the border or the height (but you can wrap with a container / box decoration)
- [ ] Can't remove the effect when clicking on a new tab
- [ ] Can't control the styling based on whether or not content is scrolled under

** Adapting between cupertino and material**
Adapting between `CupertinoTabBar` and `BottomNavigationBar` was pretty seamless because they can both take a list of `BottomNavigationBarItems`. Adapting between `CupertinoTabBar` and `NavigationBar` is more difficult, but it's what's needed to actually match material 3 styling:

```
final Map<String, Icon> _navigationItems = {
    'Menu': Platform.isIOS ? Icon(CupertinoIcons.house_fill) : Icon(Icons.home),
    'Order': Icon(Icons.adaptive.share),
  };

...

Platform.isIOS
                ? CupertinoTabBar(
                    currentIndex: _currentIndex,
                    onTap: (index) {
                      setState(() => _currentIndex = index);
                      _loadScreen();
                    },
                    items: _navigationItems.entries
                        .map<BottomNavigationBarItem>(
                            (entry) => BottomNavigationBarItem(
                                  icon: entry.value,
                                  label: entry.key,
                                ))
                        .toList(),
                  )
                : NavigationBar(
                    selectedIndex: _currentIndex,
                    onDestinationSelected: (index) {
                      setState(() => _currentIndex = index);
                      _loadScreen();
                    },
                    destinations: _navigationItems.entries
                        .map<Widget>((entry) => NavigationDestination(
                              icon: entry.value,
                              label: entry.key,
                            ))
                        .toList(),
                  )));
```




Please let me know if I've missed anything or am incorrect!