feat(tabs): add ionic theme for tab bar and tab button (#29359)

Issue number: internal

---------

## What is the current behavior?
Tab bar & tab button use the `md` styles for the `ionic` theme

## What is the new behavior?
Adds the following styles for the `ionic` theme:
- Rectangular, fixed tab bar
- Box shadow with elevation z2
- Selected, activated, and focused states

## Does this introduce a breaking change?

- [ ] Yes
- [x] No

## Other information
- A ticket (FW-6186) has been created to track updating the hardcoded
hex values to design tokens
- A ticket (FW-6189) has been created to add badge styles
This commit is contained in:
Brandy Carney
2024-04-19 14:26:15 -04:00
committed by GitHub
parent 1e757513ce
commit fa2fabdb0a
25 changed files with 181 additions and 2 deletions

View File

@@ -0,0 +1,18 @@
@use "../../foundations/ionic.vars.scss" as tokens;
@import "./tab-bar";
@import "./tab-bar.ionic.vars";
:host {
--background: #{$tabbar-ionic-background};
--background-activated: #{$tabbar-ionic-background-activated};
--background-focused: #{$tabbar-ionic-background-focused};
--color: #{$tabbar-ionic-color};
--color-selected: #{$tabbar-ionic-color-selected};
@include padding(4px, 16px);
height: 52px;
gap: 12px;
box-shadow: tokens.$ionic-elevation-2;
}

View File

@@ -0,0 +1,20 @@
@use "../../foundations/ionic.vars.scss" as tokens;
// Ionic Tab Bar
// --------------------------------------------------
/// @prop - Background color of the tab bar
$tabbar-ionic-background: var(--ion-tab-bar-background, tokens.$ionic-color-neutral-0) !default;
/// @prop - Background color of the tab bar button when activated
// TODO(FW-6186): use design token here when it is added
$tabbar-ionic-background-activated: var(--ion-tab-bar-background-activated, #ececec) !default;
/// @prop - Background color of the tab bar button when focused
$tabbar-ionic-background-focused: var(--ion-tab-bar-background-focused, transparent) !default;
/// @prop - Color of the tab bar button
$tabbar-ionic-color: var(--ion-tab-bar-color, tokens.$ionic-color-neutral-500) !default;
/// @prop - Color of the selected tab bar button
$tabbar-ionic-color-selected: var(--ion-tab-bar-color-selected, tokens.$ionic-color-primary-400) !default;

View File

@@ -18,7 +18,7 @@ import type { TabBarChangedEventDetail } from './tab-bar-interface';
styleUrls: {
ios: 'tab-bar.ios.scss',
md: 'tab-bar.md.scss',
ionic: 'tab-bar.md.scss',
ionic: 'tab-bar.ionic.scss',
},
shadow: true,
})

View File

@@ -17,6 +17,67 @@
<body>
<ion-app>
<ion-content>
<ion-tab-bar selected-tab="1">
<ion-tab-button tab="1">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="2">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="3" class="ion-focused">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
</ion-tab-bar>
<ion-tab-bar selected-tab="2">
<ion-tab-button tab="1">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="2">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="3" class="ion-focused">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="4" class="ion-activated">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
</ion-tab-bar>
<ion-tab-bar>
<ion-tab-button tab="1" class="ion-activated">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="2" class="ion-activated">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="3" class="ion-activated">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="4" class="ion-activated">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
</ion-tab-bar>
<!-- Default -->
<ion-tab-bar selected-tab="1">
<ion-tab-button tab="1">

View File

@@ -1,6 +1,46 @@
import { expect } from '@playwright/test';
import { configs, test } from '@utils/test/playwright';
/**
* This behavior needs to be tested in all modes and directions
*/
configs({ modes: ['ionic-md', 'md', 'ios'] }).forEach(({ title, screenshot, config }) => {
test.describe(title('tab-bar: basic'), () => {
test('should not have visual regressions', async ({ page }) => {
await page.setContent(
`
<ion-tab-bar selected-tab="2">
<ion-tab-button tab="1">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="2">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="3" class="ion-focused">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
<ion-tab-button tab="4" class="ion-activated">
<ion-icon name="home-outline"></ion-icon>
<ion-label>Label</ion-label>
</ion-tab-button>
</ion-tab-bar>
`,
config
);
const tabBar = page.locator('ion-tab-bar');
await expect(tabBar).toHaveScreenshot(screenshot(`tab-bar-default`));
});
});
});
/**
* This behavior needs to be tested in both modes and directions to
* make sure the safe area padding is applied only to that side

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

@@ -0,0 +1,40 @@
@use "../../foundations/ionic.vars.scss" as tokens;
@import "./tab-button";
// Ionic Tab Button
// --------------------------------------------------------------
:host {
// TODO(FW-6186): use design token here when it is added
--focus-ring-color: #9ec4fd;
--focus-ring-width: 2px;
@include border-radius(tokens.$ionic-border-radius-rounded-medium);
}
// Tab Button Focused
// -------------------------------------------------------------------------------
.button-native {
overflow: visible;
&::after {
@include border-radius(inherit);
}
}
// Only show the focus ring when the tab button is focused
:host(.ion-focused) .button-native {
&::after {
outline: var(--focus-ring-width) solid var(--focus-ring-color);
}
}
// Tab Button Activated
// -------------------------------------------------------------------------------
:host(.ion-activated) .button-native::after {
background: var(--background-activated);
opacity: var(--background-activated-opacity);
}

View File

@@ -23,7 +23,7 @@ import type {
styleUrls: {
ios: 'tab-button.ios.scss',
md: 'tab-button.md.scss',
ionic: 'tab-button.md.scss',
ionic: 'tab-button.ionic.scss',
},
shadow: true,
})