Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion core/api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2547,7 +2547,6 @@ ion-tab,shadow
ion-tab,prop,component,Function | HTMLElement | null | string | undefined,undefined,false,false
ion-tab,prop,mode,"ios" | "md",undefined,false,false
ion-tab,prop,tab,string,undefined,true,false
ion-tab,prop,theme,"ios" | "md" | "ionic",undefined,false,false
ion-tab,method,setActive,setActive() => Promise<void>

ion-tab-bar,shadow
Expand Down
8 changes: 0 additions & 8 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3928,10 +3928,6 @@ export namespace Components {
* 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.
*/
"tab": string;
/**
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
}
interface IonTabBar {
/**
Expand Down Expand Up @@ -9941,10 +9937,6 @@ declare namespace LocalJSX {
* 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.
*/
"tab": string;
/**
* The theme determines the visual appearance of the component.
*/
"theme"?: "ios" | "md" | "ionic";
}
interface IonTabBar {
/**
Expand Down
1 change: 0 additions & 1 deletion core/src/components/tab/tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import type { ComponentRef, FrameworkDelegate } from '../../interface';

/**
* @virtualProp {"ios" | "md"} mode - The mode determines the platform behaviors of the component.
* @virtualProp {"ios" | "md" | "ionic"} theme - The theme determines the visual appearance of the component.
*/
@Component({
tag: 'ion-tab',
Expand Down
45 changes: 45 additions & 0 deletions core/src/components/tab/test/tab.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { newSpecPage } from '@stencil/core/testing';

import type { FrameworkDelegate } from '../../../interface';
import { Tab } from '../tab';

const mockDelegate = (attachViewToDom: FrameworkDelegate['attachViewToDom']): FrameworkDelegate => ({
attachViewToDom,
removeViewFromDom: jest.fn().mockResolvedValue(undefined),
});

describe('ion-tab: lazy loading', () => {
it('should attach the component only once across multiple setActive calls', async () => {
const page = await newSpecPage({
components: [Tab],
html: '<ion-tab tab="home" component="ion-content"></ion-tab>',
});

const tabEl = page.body.querySelector('ion-tab') as any;
const attachViewToDom = jest.fn().mockResolvedValue(document.createElement('div'));
tabEl.delegate = mockDelegate(attachViewToDom);

await tabEl.setActive();
await tabEl.setActive();

expect(attachViewToDom).toHaveBeenCalledTimes(1);
});

it('should not retry attach after a failed first attempt', async () => {
const page = await newSpecPage({
components: [Tab],
html: '<ion-tab tab="home" component="ion-content"></ion-tab>',
});

const tabEl = page.body.querySelector('ion-tab') as any;
const attachViewToDom = jest.fn().mockRejectedValue(new Error('attach failed'));
tabEl.delegate = mockDelegate(attachViewToDom);

// First call rejects because the delegate throws. The loaded flag is already
// set to true before the attempt, so the failure is permanent.
await expect(tabEl.setActive()).rejects.toThrow('attach failed');
await tabEl.setActive();

expect(attachViewToDom).toHaveBeenCalledTimes(1);
});
});
4 changes: 2 additions & 2 deletions packages/angular/src/directives/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2336,15 +2336,15 @@ export declare interface IonSplitPane extends Components.IonSplitPane {


@ProxyCmp({
inputs: ['component', 'mode', 'tab', 'theme'],
inputs: ['component', 'mode', 'tab'],
methods: ['setActive']
})
@Component({
selector: 'ion-tab',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['component', 'mode', 'tab', 'theme'],
inputs: ['component', 'mode', 'tab'],
})
export class IonTab {
protected el: HTMLIonTabElement;
Expand Down
4 changes: 2 additions & 2 deletions packages/angular/standalone/src/directives/proxies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2077,15 +2077,15 @@ export declare interface IonSplitPane extends Components.IonSplitPane {

@ProxyCmp({
defineCustomElementFn: defineIonTab,
inputs: ['component', 'mode', 'tab', 'theme'],
inputs: ['component', 'mode', 'tab'],
methods: ['setActive']
})
@Component({
selector: 'ion-tab',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['component', 'mode', 'tab', 'theme'],
inputs: ['component', 'mode', 'tab'],
standalone: true
})
export class IonTab {
Expand Down
Loading