diff --git a/core/api.txt b/core/api.txt
index 439a457556..f7e7e3c595 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -2213,6 +2213,7 @@ ion-tab-button,prop,layout,"icon-bottom" | "icon-end" | "icon-hide" | "icon-star
ion-tab-button,prop,mode,"ios" | "md",undefined,false,false
ion-tab-button,prop,rel,string | undefined,undefined,false,false
ion-tab-button,prop,selected,boolean,false,false,false
+ion-tab-button,prop,shape,"rectangular" | "round" | "soft" | undefined,undefined,false,false
ion-tab-button,prop,tab,string | undefined,undefined,false,false
ion-tab-button,prop,target,string | undefined,undefined,false,false
ion-tab-button,prop,theme,"ios" | "md" | "ionic",undefined,false,false
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index 5b4a6b1e9c..1d0d42c8e5 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -3504,6 +3504,10 @@ export namespace Components {
* The selected tab component
*/
"selected": boolean;
+ /**
+ * 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.
+ */
+ "shape"?: 'soft' | 'round' | 'rectangular';
/**
* 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.
*/
@@ -8941,6 +8945,10 @@ declare namespace LocalJSX {
* The selected tab component
*/
"selected"?: boolean;
+ /**
+ * 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.
+ */
+ "shape"?: 'soft' | 'round' | 'rectangular';
/**
* 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.
*/
diff --git a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Chrome-linux.png
index 36cff63981..6a2f7179a4 100644
Binary files a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Chrome-linux.png and b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Firefox-linux.png
index 3b522db74e..5cbfee193a 100644
Binary files a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Firefox-linux.png and b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Safari-linux.png
index bce88a0be1..c809507817 100644
Binary files a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Safari-linux.png and b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-ltr-light-Mobile-Safari-linux.png differ
diff --git a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Chrome-linux.png b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Chrome-linux.png
index 54aff9fc64..9c0a8c4302 100644
Binary files a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Chrome-linux.png and b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Firefox-linux.png b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Firefox-linux.png
index 3e4a2a582f..46cb7e73e6 100644
Binary files a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Firefox-linux.png and b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Safari-linux.png b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Safari-linux.png
index 2555a9e3b7..8a175cb91b 100644
Binary files a/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Safari-linux.png and b/core/src/components/tab-bar/test/basic/tab-bar.e2e.ts-snapshots/tab-bar-default-ionic-md-rtl-light-Mobile-Safari-linux.png differ
diff --git a/core/src/components/tab-button/tab-button.ionic.scss b/core/src/components/tab-button/tab-button.ionic.scss
index 463385df2a..8f2f3ca748 100644
--- a/core/src/components/tab-button/tab-button.ionic.scss
+++ b/core/src/components/tab-button/tab-button.ionic.scss
@@ -8,8 +8,6 @@
--focus-ring-color: #{globals.$ion-border-focus-default};
--focus-ring-width: #{globals.$ion-border-radius-025};
- @include globals.border-radius(globals.$ion-border-radius-200);
-
align-content: center;
min-height: globals.$ion-scale-1200;
@@ -73,3 +71,18 @@
width: globals.$ion-scale-600;
height: globals.$ion-scale-600;
}
+
+// Tab Button Shapes
+// -------------------------------------------------------------------------------
+
+:host(.tab-button-shape-soft) {
+ @include globals.border-radius(globals.$ion-border-radius-200);
+}
+
+:host(.tab-button-shape-round) {
+ @include globals.border-radius(globals.$ion-border-radius-400);
+}
+
+:host(.tab-button-shape-rectangular) {
+ @include globals.border-radius(globals.$ion-border-radius-0);
+}
diff --git a/core/src/components/tab-button/tab-button.tsx b/core/src/components/tab-button/tab-button.tsx
index ab973b9f07..e03b8a69e3 100644
--- a/core/src/components/tab-button/tab-button.tsx
+++ b/core/src/components/tab-button/tab-button.tsx
@@ -68,6 +68,15 @@ export class TabButton implements ComponentInterface, AnchorInterface {
*/
@Prop({ mutable: true }) selected = false;
+ /**
+ * 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.
+ */
+ @Prop() shape?: 'soft' | 'round' | 'rectangular';
+
/**
* 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.
@@ -107,6 +116,22 @@ export class TabButton implements ComponentInterface, AnchorInterface {
}
}
+ private getShape(): string | undefined {
+ const theme = getIonTheme(this);
+ const { shape } = this;
+
+ // TODO(ROU-11436): Remove theme check when shapes are defined for all themes.
+ if (theme !== 'ionic') {
+ return undefined;
+ }
+
+ if (shape === undefined) {
+ return 'round';
+ }
+
+ return shape;
+ }
+
private selectTab(ev: Event | KeyboardEvent) {
if (this.tab !== undefined) {
if (!this.disabled) {
@@ -141,6 +166,7 @@ export class TabButton implements ComponentInterface, AnchorInterface {
render() {
const { disabled, hasIcon, hasLabel, href, rel, target, layout, selected, tab, inheritedAttributes } = this;
const theme = getIonTheme(this);
+ const shape = this.getShape();
const attrs = {
download: this.download,
href,
@@ -164,6 +190,7 @@ export class TabButton implements ComponentInterface, AnchorInterface {
[`tab-layout-${layout}`]: true,
'ion-activatable': true,
'ion-selectable': true,
+ [`tab-button-shape-${shape}`]: shape !== undefined,
'ion-focusable': true,
}}
>
diff --git a/core/src/components/tab-button/test/shape/index.html b/core/src/components/tab-button/test/shape/index.html
new file mode 100644
index 0000000000..614da48e9e
--- /dev/null
+++ b/core/src/components/tab-button/test/shape/index.html
@@ -0,0 +1,55 @@
+
+
+
+
+ Tab Button - Shape
+
+
+
+
+
+
+
+
+
+
+
+
+ Tab Button - Shape
+
+
+
+
+ (Only available for ionic theme)
+
+
+
+ Default Shape
+
+
+
+
+ Soft Shape
+
+
+
+
+ Round Shape
+
+
+
+
+ Rectangular Shape
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts b/core/src/components/tab-button/test/shape/tab-button.e2e.ts
new file mode 100644
index 0000000000..a9d31f1c38
--- /dev/null
+++ b/core/src/components/tab-button/test/shape/tab-button.e2e.ts
@@ -0,0 +1,51 @@
+import { expect } from '@playwright/test';
+import { configs, test } from '@utils/test/playwright';
+import type { E2EPage, E2EPageOptions, ScreenshotFn } from '@utils/test/playwright';
+
+class TabButtonFixture {
+ readonly page: E2EPage;
+
+ constructor(page: E2EPage) {
+ this.page = page;
+ }
+
+ async goto(config: E2EPageOptions) {
+ const { page } = this;
+ await page.goto(`/src/components/tab-button/test/shape`, config);
+ }
+
+ async screenshot(screenshotModifier: string, screenshot: ScreenshotFn, buttonId: string) {
+ const { page } = this;
+
+ const screenshotString = screenshot(`tab-button-${screenshotModifier}`);
+ const tabButton = page.locator(buttonId);
+
+ await expect(tabButton).toHaveScreenshot(screenshotString);
+ }
+}
+
+/**
+ * This behavior does not vary across directions.
+ */
+configs({ modes: ['ionic-md'], directions: ['ltr'] }).forEach(({ config, screenshot, title }) => {
+ test.describe(title('tab-button: shape'), () => {
+ let tabButtonFixture: TabButtonFixture;
+
+ test.beforeEach(async ({ page }) => {
+ tabButtonFixture = new TabButtonFixture(page);
+ await tabButtonFixture.goto(config);
+ });
+
+ test('should render a soft tab button', async () => {
+ await tabButtonFixture.screenshot('shape-soft', screenshot, '#soft-tab-button');
+ });
+
+ test('should render a round tab button', async () => {
+ await tabButtonFixture.screenshot('shape-round', screenshot, '#round-tab-button');
+ });
+
+ test('should render a rectangular tab button', async () => {
+ await tabButtonFixture.screenshot('shape-rectangular', screenshot, '#rect-tab-button');
+ });
+ });
+});
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-rectangular-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-rectangular-ionic-md-ltr-light-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..e03e4ac09f
Binary files /dev/null and b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-rectangular-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-rectangular-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-rectangular-ionic-md-ltr-light-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..ce90c00a6e
Binary files /dev/null and b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-rectangular-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-rectangular-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-rectangular-ionic-md-ltr-light-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..057d33d5d3
Binary files /dev/null and b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-rectangular-ionic-md-ltr-light-Mobile-Safari-linux.png differ
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-round-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-round-ionic-md-ltr-light-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..98b1834085
Binary files /dev/null and b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-round-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-round-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-round-ionic-md-ltr-light-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..a6a33dfdb4
Binary files /dev/null and b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-round-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-round-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-round-ionic-md-ltr-light-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..534169aab5
Binary files /dev/null and b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-round-ionic-md-ltr-light-Mobile-Safari-linux.png differ
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-soft-ionic-md-ltr-light-Mobile-Chrome-linux.png b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-soft-ionic-md-ltr-light-Mobile-Chrome-linux.png
new file mode 100644
index 0000000000..6e5086a417
Binary files /dev/null and b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-soft-ionic-md-ltr-light-Mobile-Chrome-linux.png differ
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-soft-ionic-md-ltr-light-Mobile-Firefox-linux.png b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-soft-ionic-md-ltr-light-Mobile-Firefox-linux.png
new file mode 100644
index 0000000000..922219804f
Binary files /dev/null and b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-soft-ionic-md-ltr-light-Mobile-Firefox-linux.png differ
diff --git a/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-soft-ionic-md-ltr-light-Mobile-Safari-linux.png b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-soft-ionic-md-ltr-light-Mobile-Safari-linux.png
new file mode 100644
index 0000000000..1c2e74d329
Binary files /dev/null and b/core/src/components/tab-button/test/shape/tab-button.e2e.ts-snapshots/tab-button-shape-soft-ionic-md-ltr-light-Mobile-Safari-linux.png differ
diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts
index 8d3dac8cb1..ea1b4e31c2 100644
--- a/packages/angular/src/directives/proxies.ts
+++ b/packages/angular/src/directives/proxies.ts
@@ -2276,14 +2276,14 @@ export declare interface IonTabBar extends Components.IonTabBar {}
@ProxyCmp({
- inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'tab', 'target', 'theme']
+ inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'shape', 'tab', 'target', 'theme']
})
@Component({
selector: 'ion-tab-button',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
- inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'tab', 'target', 'theme'],
+ inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'shape', 'tab', 'target', 'theme'],
})
export class IonTabButton {
protected el: HTMLElement;
diff --git a/packages/angular/standalone/src/directives/proxies.ts b/packages/angular/standalone/src/directives/proxies.ts
index df589497e9..8d828c3c64 100644
--- a/packages/angular/standalone/src/directives/proxies.ts
+++ b/packages/angular/standalone/src/directives/proxies.ts
@@ -2081,14 +2081,14 @@ export declare interface IonTabBar extends Components.IonTabBar {}
@ProxyCmp({
defineCustomElementFn: defineIonTabButton,
- inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'tab', 'target', 'theme']
+ inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'shape', 'tab', 'target', 'theme']
})
@Component({
selector: 'ion-tab-button',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
- inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'tab', 'target', 'theme'],
+ inputs: ['disabled', 'download', 'href', 'layout', 'mode', 'rel', 'selected', 'shape', 'tab', 'target', 'theme'],
standalone: true
})
export class IonTabButton {