diff --git a/core/api.txt b/core/api.txt
index 201c86c28d0..70c32153f68 100644
--- a/core/api.txt
+++ b/core/api.txt
@@ -1695,6 +1695,7 @@ ion-select,part,supporting-text
ion-select,part,text
ion-select-modal,scoped
+ion-select-modal,prop,closeText,string | undefined,undefined,false,false
ion-select-modal,prop,header,string | undefined,undefined,false,false
ion-select-modal,prop,multiple,boolean | undefined,undefined,false,false
ion-select-modal,prop,options,SelectModalOption[],[],false,false
diff --git a/core/src/components.d.ts b/core/src/components.d.ts
index c458b851506..6a13ab518ca 100644
--- a/core/src/components.d.ts
+++ b/core/src/components.d.ts
@@ -2862,6 +2862,7 @@ export namespace Components {
"value"?: any | null;
}
interface IonSelectModal {
+ "cancelText"?: string;
"header"?: string;
"multiple"?: boolean;
"options": SelectModalOption[];
@@ -7742,6 +7743,7 @@ declare namespace LocalJSX {
"value"?: any | null;
}
interface IonSelectModal {
+ "cancelText"?: string;
"header"?: string;
"multiple"?: boolean;
"options"?: SelectModalOption[];
diff --git a/core/src/components/select-modal/select-modal.tsx b/core/src/components/select-modal/select-modal.tsx
index 5925d209640..a5447be1d8d 100644
--- a/core/src/components/select-modal/select-modal.tsx
+++ b/core/src/components/select-modal/select-modal.tsx
@@ -23,6 +23,8 @@ export class SelectModal implements ComponentInterface {
@Prop() header?: string;
+ @Prop() cancelText?: string;
+
@Prop() multiple?: boolean;
@Prop() options: SelectModalOption[] = [];
@@ -149,7 +151,7 @@ export class SelectModal implements ComponentInterface {
{this.header !== undefined && {this.header}}
- this.closeModal()}>Close
+ this.closeModal()}>{this.cancelText || 'Close'}
diff --git a/core/src/components/select-modal/test/custom-close-text/index.html b/core/src/components/select-modal/test/custom-close-text/index.html
new file mode 100644
index 00000000000..ba329f09300
--- /dev/null
+++ b/core/src/components/select-modal/test/custom-close-text/index.html
@@ -0,0 +1,40 @@
+
+
+
+
+ Select - Modal
+
+
+
+
+
+
+
+
+
+
+
+
+ Select Modal - Custom Close Text
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts
new file mode 100644
index 00000000000..f78f5eb6a82
--- /dev/null
+++ b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts
@@ -0,0 +1,101 @@
+import { expect } from '@playwright/test';
+import { configs, test } from '@utils/test/playwright';
+
+import type { SelectModalOption } from '../../select-modal-interface';
+import { SelectModalPage } from '../fixtures';
+
+const options: SelectModalOption[] = [
+ { value: 'apple', text: 'Apple', disabled: false, checked: false },
+ { value: 'banana', text: 'Banana', disabled: false, checked: false },
+];
+
+const checkedOptions: SelectModalOption[] = [
+ { value: 'apple', text: 'Apple', disabled: false, checked: true },
+ { value: 'banana', text: 'Banana', disabled: false, checked: false },
+];
+
+/**
+ * This behavior does not vary across modes/directions.
+ */
+configs({ modes: ['md'], directions: ['ltr'] }).forEach(({ title, config }) => {
+ test.describe(title('select-modal: custom-close-text'), () => {
+ test.beforeEach(({ browserName }) => {
+ test.skip(browserName === 'webkit', 'ROU-5437');
+ });
+
+ test.describe('single selection', () => {
+ let selectModalPage: SelectModalPage;
+
+ test.beforeEach(async ({ page }) => {
+ selectModalPage = new SelectModalPage(page);
+ });
+
+ test('clicking an unselected option should dismiss the modal', async () => {
+ await selectModalPage.setup(config, options, false);
+
+ await selectModalPage.clickOption('apple');
+ await selectModalPage.ionModalDidDismiss.next();
+ await expect(selectModalPage.modal).not.toBeVisible();
+ });
+
+ test('clicking a selected option should dismiss the modal', async () => {
+ await selectModalPage.setup(config, checkedOptions, false);
+
+ await selectModalPage.clickOption('apple');
+ await selectModalPage.ionModalDidDismiss.next();
+ await expect(selectModalPage.modal).not.toBeVisible();
+ });
+
+ test('pressing Space on an unselected option should dismiss the modal', async () => {
+ await selectModalPage.setup(config, options, false);
+
+ await selectModalPage.pressSpaceOnOption('apple');
+ await selectModalPage.ionModalDidDismiss.next();
+ await expect(selectModalPage.modal).not.toBeVisible();
+ });
+
+ test('pressing Space on a selected option should dismiss the modal', async ({ browserName }) => {
+ test.skip(browserName === 'firefox', 'Same behavior as ROU-5437');
+
+ await selectModalPage.setup(config, checkedOptions, false);
+
+ await selectModalPage.pressSpaceOnOption('apple');
+ await selectModalPage.ionModalDidDismiss.next();
+ await expect(selectModalPage.modal).not.toBeVisible();
+ });
+
+ test('clicking the close button should dismiss the modal', async () => {
+ await selectModalPage.setup(config, options, false);
+
+ const closeButton = selectModalPage.modal.locator('ion-header ion-toolbar ion-button');
+ await closeButton.click();
+ await selectModalPage.ionModalDidDismiss.next();
+ await expect(selectModalPage.modal).not.toBeVisible();
+ });
+ });
+ });
+});
+
+/**
+ * This behavior does not vary across directions.
+ * The components used inside of `ion-select-modal`
+ * do have RTL logic, but those are tested in their
+ * respective component test files.
+ */
+configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
+ test.describe(title('select-modal: rendering'), () => {
+ let selectModalPage: SelectModalPage;
+
+ test.beforeEach(async ({ page }) => {
+ selectModalPage = new SelectModalPage(page);
+ });
+ test('should not have visual regressions with single selection', async () => {
+ await selectModalPage.setup(config, checkedOptions, false);
+ await selectModalPage.screenshot(screenshot, 'select-modal-diff');
+ });
+ test('should not have visual regressions with multiple selection', async () => {
+ await selectModalPage.setup(config, checkedOptions, true);
+ await selectModalPage.screenshot(screenshot, 'select-modal-multiple-diff');
+ });
+ });
+});
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-ios-ltr-Mobile-Chrome-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-ios-ltr-Mobile-Chrome-darwin.png
new file mode 100644
index 00000000000..863cbde10a9
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-ios-ltr-Mobile-Chrome-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-ios-ltr-Mobile-Firefox-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-ios-ltr-Mobile-Firefox-darwin.png
new file mode 100644
index 00000000000..42a65eb1fa8
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-ios-ltr-Mobile-Firefox-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-ios-ltr-Mobile-Safari-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-ios-ltr-Mobile-Safari-darwin.png
new file mode 100644
index 00000000000..9297c6904dc
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-ios-ltr-Mobile-Safari-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-md-ltr-Mobile-Chrome-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-md-ltr-Mobile-Chrome-darwin.png
new file mode 100644
index 00000000000..f214fbb6579
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-md-ltr-Mobile-Chrome-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-md-ltr-Mobile-Firefox-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-md-ltr-Mobile-Firefox-darwin.png
new file mode 100644
index 00000000000..1701959edf2
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-md-ltr-Mobile-Firefox-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-md-ltr-Mobile-Safari-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-md-ltr-Mobile-Safari-darwin.png
new file mode 100644
index 00000000000..2ae98a5096c
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-diff-md-ltr-Mobile-Safari-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-ios-ltr-Mobile-Chrome-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-ios-ltr-Mobile-Chrome-darwin.png
new file mode 100644
index 00000000000..4ab59e44a7b
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-ios-ltr-Mobile-Chrome-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-ios-ltr-Mobile-Firefox-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-ios-ltr-Mobile-Firefox-darwin.png
new file mode 100644
index 00000000000..fb230741df1
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-ios-ltr-Mobile-Firefox-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-ios-ltr-Mobile-Safari-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-ios-ltr-Mobile-Safari-darwin.png
new file mode 100644
index 00000000000..c7e0b5836e2
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-ios-ltr-Mobile-Safari-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-md-ltr-Mobile-Chrome-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-md-ltr-Mobile-Chrome-darwin.png
new file mode 100644
index 00000000000..3e58df9f4d8
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-md-ltr-Mobile-Chrome-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-md-ltr-Mobile-Firefox-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-md-ltr-Mobile-Firefox-darwin.png
new file mode 100644
index 00000000000..2989c08534f
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-md-ltr-Mobile-Firefox-darwin.png differ
diff --git a/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-md-ltr-Mobile-Safari-darwin.png b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-md-ltr-Mobile-Safari-darwin.png
new file mode 100644
index 00000000000..9914a5cdf0f
Binary files /dev/null and b/core/src/components/select-modal/test/custom-close-text/select-modal.e2e.ts-snapshots/select-modal-multiple-diff-md-ltr-Mobile-Safari-darwin.png differ
diff --git a/core/src/components/select-modal/test/fixtures.ts b/core/src/components/select-modal/test/fixtures.ts
index 2058848aa84..ef5c39ecaf6 100644
--- a/core/src/components/select-modal/test/fixtures.ts
+++ b/core/src/components/select-modal/test/fixtures.ts
@@ -1,5 +1,5 @@
import { expect } from '@playwright/test';
-import type { E2EPage, E2ELocator, EventSpy, E2EPageOptions, ScreenshotFn } from '@utils/test/playwright';
+import type { E2ELocator, E2EPage, E2EPageOptions, EventSpy, ScreenshotFn } from '@utils/test/playwright';
import type { SelectModalOption } from '../select-modal-interface';
@@ -31,6 +31,7 @@ export class SelectModalPage {
const selectModal = document.querySelector('ion-select-modal');
selectModal.options = ${JSON.stringify(options)};
selectModal.multiple = ${multiple};
+ selectModal.cancelText = 'Close me';
`,
config
diff --git a/core/src/components/select/select.tsx b/core/src/components/select/select.tsx
index 7fc456092db..f32ddc08de7 100644
--- a/core/src/components/select/select.tsx
+++ b/core/src/components/select/select.tsx
@@ -1,9 +1,9 @@
import type { ComponentInterface, EventEmitter } from '@stencil/core';
-import { Component, Element, Event, Host, Method, Prop, State, Watch, h, forceUpdate } from '@stencil/core';
+import { Component, Element, Event, Host, Method, Prop, State, Watch, forceUpdate, h } from '@stencil/core';
import type { NotchController } from '@utils/forms';
import { compareOptions, createNotchController, isOptionSelected } from '@utils/forms';
-import { focusVisibleElement, renderHiddenInput, inheritAttributes } from '@utils/helpers';
import type { Attributes } from '@utils/helpers';
+import { focusVisibleElement, inheritAttributes, renderHiddenInput } from '@utils/helpers';
import { printIonWarning } from '@utils/logging';
import { actionSheetController, alertController, popoverController, modalController } from '@utils/overlays';
import type { OverlaySelect } from '@utils/overlays-interface';
@@ -18,15 +18,15 @@ import type {
AlertOptions,
Color,
CssClassMap,
+ ModalOptions,
PopoverOptions,
StyleEventDetail,
- ModalOptions,
} from '../../interface';
import type { ActionSheetButton } from '../action-sheet/action-sheet-interface';
import type { AlertInput } from '../alert/alert-interface';
import type { SelectPopoverOption } from '../select-popover/select-popover-interface';
-import type { SelectChangeEventDetail, SelectInterface, SelectCompareFn } from './select-interface';
+import type { SelectChangeEventDetail, SelectCompareFn, SelectInterface } from './select-interface';
// TODO(FW-2832): types
@@ -735,6 +735,7 @@ export class Select implements ComponentInterface {
component: 'ion-select-modal',
componentProps: {
header: interfaceOptions.header,
+ cancelText: this.cancelText,
multiple,
value,
options: this.createOverlaySelectOptions(this.childOpts, value),
diff --git a/packages/angular/src/directives/proxies.ts b/packages/angular/src/directives/proxies.ts
index cfa828e322c..90c2e0ab7c4 100644
--- a/packages/angular/src/directives/proxies.ts
+++ b/packages/angular/src/directives/proxies.ts
@@ -2109,14 +2109,14 @@ This event will not emit when programmatically setting the `value` property.
@ProxyCmp({
- inputs: ['header', 'multiple', 'options']
+ inputs: ['cancelText', 'header', 'multiple', 'options']
})
@Component({
selector: 'ion-select-modal',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
- inputs: ['header', 'multiple', 'options'],
+ inputs: ['cancelText', 'header', 'multiple', 'options'],
})
export class IonSelectModal {
protected el: HTMLIonSelectModalElement;
diff --git a/packages/angular/standalone/src/directives/proxies.ts b/packages/angular/standalone/src/directives/proxies.ts
index c7d111f7bef..b71349908d8 100644
--- a/packages/angular/standalone/src/directives/proxies.ts
+++ b/packages/angular/standalone/src/directives/proxies.ts
@@ -1901,14 +1901,14 @@ export declare interface IonSegmentView extends Components.IonSegmentView {
@ProxyCmp({
defineCustomElementFn: defineIonSelectModal,
- inputs: ['header', 'multiple', 'options']
+ inputs: ['cancelText', 'header', 'multiple', 'options']
})
@Component({
selector: 'ion-select-modal',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
- inputs: ['header', 'multiple', 'options'],
+ inputs: ['cancelText', 'header', 'multiple', 'options'],
standalone: true
})
export class IonSelectModal {
diff --git a/packages/vue/src/proxies.ts b/packages/vue/src/proxies.ts
index 97270298bb4..da71535c252 100644
--- a/packages/vue/src/proxies.ts
+++ b/packages/vue/src/proxies.ts
@@ -910,6 +910,7 @@ export const IonSelect: StencilVueComponent = /*@__PURE__*/ defineContainer('ion-select-modal', defineIonSelectModal, [
'header',
+ 'cancelText',
'multiple',
'options'
]);