Skip to content

Commit be076b0

Browse files
First commit
1 parent 1e33a57 commit be076b0

File tree

9 files changed

+169
-7
lines changed

9 files changed

+169
-7
lines changed

core/src/components.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3504,6 +3504,10 @@ export namespace Components {
35043504
* The selected tab component
35053505
*/
35063506
"selected": boolean;
3507+
/**
3508+
* Set to `"soft"` for a tab-button with slightly rounded corners, `"round"` for a tab-button with fully rounded corners, or `"rectangular"` for a tab-button without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
3509+
*/
3510+
"shape"?: 'soft' | 'round' | 'rectangular';
35073511
/**
35083512
* A tab id must be provided for each `ion-tab`. It's used internally to reference the selected tab or by the router to switch between them.
35093513
*/
@@ -8941,6 +8945,10 @@ declare namespace LocalJSX {
89418945
* The selected tab component
89428946
*/
89438947
"selected"?: boolean;
8948+
/**
8949+
* Set to `"soft"` for a tab-button with slightly rounded corners, `"round"` for a tab-button with fully rounded corners, or `"rectangular"` for a tab-button without rounded corners. Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
8950+
*/
8951+
"shape"?: 'soft' | 'round' | 'rectangular';
89448952
/**
89458953
* A tab id must be provided for each `ion-tab`. It's used internally to reference the selected tab or by the router to switch between them.
89468954
*/

core/src/components/tab-bar/tab-bar.ionic.scss

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,21 @@
3737
padding-right: calc(globals.$ion-space-400 + var(--ion-safe-area-right, 0));
3838
padding-left: calc(globals.$ion-space-400 + var(--ion-safe-area-left, 0));
3939
/* stylelint-enable */
40+
41+
//contain: size layout style;
4042
}
4143

4244
:host([slot="top"].tab-bar-full) {
4345
padding-top: calc(globals.$ion-space-100 + var(--ion-safe-area-top, 0));
4446
padding-bottom: globals.$ion-space-100;
4547
}
4648

49+
:host-context(.ion-content) {
50+
:host(.tab-bar-full) {
51+
contain: size layout style;
52+
}
53+
}
54+
4755
/* Compact */
4856
:host(.tab-bar-compact) {
4957
@include globals.padding(globals.$ion-space-100, globals.$ion-space-400);

core/src/components/tab-button/tab-button.ionic.scss

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
--focus-ring-color: #{globals.$ion-border-focus-default};
99
--focus-ring-width: #{globals.$ion-border-radius-025};
1010

11-
@include globals.border-radius(globals.$ion-border-radius-200);
12-
1311
align-content: center;
1412

1513
min-height: globals.$ion-scale-1200;
@@ -73,3 +71,18 @@
7371
width: globals.$ion-scale-600;
7472
height: globals.$ion-scale-600;
7573
}
74+
75+
// Toast Shapes
76+
// -------------------------------------------------------------------------------
77+
78+
:host(.toast-shape-soft) {
79+
border-radius: #{globals.$ion-border-radius-200};
80+
}
81+
82+
:host(.toast-shape-round) {
83+
border-radius: #{globals.$ion-border-radius-400};
84+
}
85+
86+
:host(.toast-shape-rectangular) {
87+
border-radius: #{globals.$ion-border-radius-0};
88+
}

core/src/components/tab-button/tab-button.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,15 @@ export class TabButton implements ComponentInterface, AnchorInterface {
6868
*/
6969
@Prop({ mutable: true }) selected = false;
7070

71+
/**
72+
* Set to `"soft"` for a tab-button with slightly rounded corners,
73+
* `"round"` for a tab-button with fully rounded corners, or `"rectangular"`
74+
* for a tab-button without rounded corners.
75+
*
76+
* Defaults to `"round"` for the `ionic` theme, undefined for all other themes.
77+
*/
78+
@Prop() shape?: 'soft' | 'round' | 'rectangular';
79+
7180
/**
7281
* A tab id must be provided for each `ion-tab`. It's used internally to reference
7382
* the selected tab or by the router to switch between them.
@@ -107,6 +116,21 @@ export class TabButton implements ComponentInterface, AnchorInterface {
107116
}
108117
}
109118

119+
private getShape(): string | undefined {
120+
const { shape } = this;
121+
122+
// TODO(ROU-11300): Remove theme check when shapes are defined for all themes.
123+
if (getIonTheme(this) !== 'ionic') {
124+
return undefined;
125+
}
126+
127+
if (shape === undefined) {
128+
return 'round';
129+
}
130+
131+
return shape;
132+
}
133+
110134
private selectTab(ev: Event | KeyboardEvent) {
111135
if (this.tab !== undefined) {
112136
if (!this.disabled) {
@@ -141,6 +165,7 @@ export class TabButton implements ComponentInterface, AnchorInterface {
141165
render() {
142166
const { disabled, hasIcon, hasLabel, href, rel, target, layout, selected, tab, inheritedAttributes } = this;
143167
const theme = getIonTheme(this);
168+
const shape = this.getShape();
144169
const attrs = {
145170
download: this.download,
146171
href,
@@ -164,6 +189,7 @@ export class TabButton implements ComponentInterface, AnchorInterface {
164189
[`tab-layout-${layout}`]: true,
165190
'ion-activatable': true,
166191
'ion-selectable': true,
192+
[`toast-shape-${shape}`]: shape !== undefined,
167193
'ion-focusable': true,
168194
}}
169195
>

core/src/components/tab-button/test/a11y/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
<main>
1616
<h1>Tab Button</h1>
1717
<ion-tab-bar>
18-
<ion-tab-button href="#">
18+
<ion-tab-button href="#" shape="rectangular">
1919
<ion-label>Tab One</ion-label>
2020
<ion-icon aria-hidden="true" name="star"></ion-icon>
2121
</ion-tab-button>
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<!DOCTYPE html>
2+
<html lang="en" dir="ltr">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<title>Tab Button - Shape</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0" />
7+
<link href="../../../../../css/core.css" rel="stylesheet" />
8+
<link href="../../../../../scripts/testing/styles.css" rel="stylesheet" />
9+
<script src="../../../../../scripts/testing/scripts.js"></script>
10+
<script nomodule src="../../../../../dist/ionic/ionic.js"></script>
11+
<script type="module" src="../../../../../dist/ionic/ionic.esm.js"></script>
12+
</head>
13+
14+
<body>
15+
<ion-app>
16+
<ion-header>
17+
<ion-toolbar>
18+
<ion-title>Tab Button - Shape</ion-title>
19+
</ion-toolbar>
20+
</ion-header>
21+
22+
<ion-content class="ion-padding" id="content" style="text-align: center">
23+
(Only available for ionic theme)
24+
25+
<ion-tab-bar style="margin-top: 16px">
26+
<ion-segment style="flex: 1">
27+
Default Shape:
28+
<ion-tab-button id="default-tab-button" style="background: #ff9e99">
29+
<ion-label>Round Shape</ion-label>
30+
<ion-icon aria-hidden="true" name="stop-circle"></ion-icon>
31+
</ion-tab-button>
32+
</ion-segment>
33+
34+
<ion-tab-button id="soft-tab-button" shape="soft" style="background: #faf19d">
35+
<ion-label>Soft Shape</ion-label>
36+
<ion-icon aria-hidden="true" name="cloud"></ion-icon>
37+
</ion-tab-button>
38+
39+
<ion-tab-button id="round-tab-button" shape="round" style="background: #ff9e99">
40+
<ion-label>Round Shape</ion-label>
41+
<ion-icon aria-hidden="true" name="stop-circle"></ion-icon>
42+
</ion-tab-button>
43+
44+
<ion-tab-button id="rect-tab-button" shape="rectangular" style="background: #a3ff85">
45+
<ion-label>Rectangular Shape</ion-label>
46+
<ion-icon aria-hidden="true" name="square"></ion-icon>
47+
</ion-tab-button>
48+
</ion-tab-bar>
49+
</ion-content>
50+
</ion-app>
51+
</body>
52+
</html>
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { expect } from '@playwright/test';
2+
import { configs, test } from '@utils/test/playwright';
3+
import type { E2EPage, E2EPageOptions, ScreenshotFn } from '@utils/test/playwright';
4+
5+
class TabButtonFixture {
6+
readonly page: E2EPage;
7+
8+
constructor(page: E2EPage) {
9+
this.page = page;
10+
}
11+
12+
async goto(config: E2EPageOptions) {
13+
const { page } = this;
14+
await page.goto(`/src/components/tab-button/test/shape`, config);
15+
}
16+
17+
async screenshot(screenshotModifier: string, screenshot: ScreenshotFn, buttonId: string) {
18+
const { page } = this;
19+
20+
const screenshotString = screenshot(`tab-button-${screenshotModifier}`);
21+
const tabButton = page.locator(buttonId);
22+
23+
await expect(tabButton).toHaveScreenshot(screenshotString);
24+
}
25+
}
26+
27+
/**
28+
* This behavior does not vary across directions.
29+
*/
30+
configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
31+
test.describe(title('tab-button: shape'), () => {
32+
let tabButtonFixture: TabButtonFixture;
33+
34+
test.beforeEach(async ({ page }) => {
35+
tabButtonFixture = new TabButtonFixture(page);
36+
await tabButtonFixture.goto(config);
37+
});
38+
39+
test('should render the default toast', async () => {
40+
await tabButtonFixture.screenshot('shape-round', screenshot, '#default-tab-button');
41+
});
42+
43+
test('should render a soft toast', async () => {
44+
await tabButtonFixture.screenshot('shape-soft', screenshot, '#soft-tab-button');
45+
});
46+
47+
test('should render a round toast', async () => {
48+
await tabButtonFixture.screenshot('shape-round', screenshot, '#round-tab-button');
49+
});
50+
51+
test('should render a rectangular toast', async () => {
52+
await tabButtonFixture.screenshot('shape-rectangular', screenshot, '#rect-tab-button');
53+
});
54+
});
55+
});

packages/angular/src/directives/proxies.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2276,14 +2276,14 @@ export declare interface IonTabBar extends Components.IonTabBar {}
22762276

22772277

22782278
@ProxyCmp({
2279-
inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'tab', 'target', 'theme']
2279+
inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'shape', 'tab', 'target', 'theme']
22802280
})
22812281
@Component({
22822282
selector: 'ion-tab-button',
22832283
changeDetection: ChangeDetectionStrategy.OnPush,
22842284
template: '<ng-content></ng-content>',
22852285
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
2286-
inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'tab', 'target', 'theme'],
2286+
inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'shape', 'tab', 'target', 'theme'],
22872287
})
22882288
export class IonTabButton {
22892289
protected el: HTMLElement;

packages/angular/standalone/src/directives/proxies.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2081,14 +2081,14 @@ export declare interface IonTabBar extends Components.IonTabBar {}
20812081

20822082
@ProxyCmp({
20832083
defineCustomElementFn: defineIonTabButton,
2084-
inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'tab', 'target', 'theme']
2084+
inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'shape', 'tab', 'target', 'theme']
20852085
})
20862086
@Component({
20872087
selector: 'ion-tab-button',
20882088
changeDetection: ChangeDetectionStrategy.OnPush,
20892089
template: '<ng-content></ng-content>',
20902090
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
2091-
inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'tab', 'target', 'theme'],
2091+
inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'shape', 'tab', 'target', 'theme'],
20922092
standalone: true
20932093
})
20942094
export class IonTabButton {

0 commit comments

Comments
 (0)