diff --git a/core/api.txt b/core/api.txt index a964a58fad1..fec664eae62 100644 --- a/core/api.txt +++ b/core/api.txt @@ -6,6 +6,7 @@ ion-action-sheet,prop,buttons,(string | ActionSheetButton)[],[],false,false ion-action-sheet,prop,cssClass,string | string[] | undefined,undefined,false,false ion-action-sheet,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-action-sheet,prop,header,string | undefined,undefined,false,false +ion-action-sheet,prop,htmlAttributes,ActionSheetAttributes | undefined,undefined,false,false ion-action-sheet,prop,keyboardClose,boolean,true,false,false ion-action-sheet,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-action-sheet,prop,mode,"ios" | "md",undefined,false,false @@ -334,7 +335,7 @@ ion-datetime,prop,monthShortNames,string | string[] | undefined,undefined,false, ion-datetime,prop,monthValues,number | number[] | string | undefined,undefined,false,false ion-datetime,prop,name,string,this.inputId,false,false ion-datetime,prop,pickerFormat,string | undefined,undefined,false,false -ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; showBackdrop?: boolean | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: Mode | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false +ion-datetime,prop,pickerOptions,undefined | { columns?: PickerColumn[] | undefined; buttons?: PickerButton[] | undefined; cssClass?: string | string[] | undefined; showBackdrop?: boolean | undefined; backdropDismiss?: boolean | undefined; animated?: boolean | undefined; mode?: Mode | undefined; keyboardClose?: boolean | undefined; id?: string | undefined; htmlAttributes?: PickerAttributes | undefined; enterAnimation?: AnimationBuilder | undefined; leaveAnimation?: AnimationBuilder | undefined; },undefined,false,false ion-datetime,prop,placeholder,null | string | undefined,undefined,false,false ion-datetime,prop,readonly,boolean,false,false,false ion-datetime,prop,value,null | string | undefined,undefined,false,false @@ -622,6 +623,7 @@ ion-loading,prop,backdropDismiss,boolean,false,false,false ion-loading,prop,cssClass,string | string[] | undefined,undefined,false,false ion-loading,prop,duration,number,0,false,false ion-loading,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false +ion-loading,prop,htmlAttributes,LoadingAttributes | undefined,undefined,false,false ion-loading,prop,keyboardClose,boolean,true,false,false ion-loading,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-loading,prop,message,IonicSafeString | string | undefined,undefined,false,false @@ -709,6 +711,7 @@ ion-modal,prop,component,Function | HTMLElement | null | string,undefined,true,f ion-modal,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false ion-modal,prop,cssClass,string | string[] | undefined,undefined,false,false ion-modal,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false +ion-modal,prop,htmlAttributes,ModalAttributes | undefined,undefined,false,false ion-modal,prop,keyboardClose,boolean,true,false,false ion-modal,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-modal,prop,mode,"ios" | "md",undefined,false,false @@ -777,6 +780,7 @@ ion-picker,prop,columns,PickerColumn[],[],false,false ion-picker,prop,cssClass,string | string[] | undefined,undefined,false,false ion-picker,prop,duration,number,0,false,false ion-picker,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false +ion-picker,prop,htmlAttributes,PickerAttributes | undefined,undefined,false,false ion-picker,prop,keyboardClose,boolean,true,false,false ion-picker,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-picker,prop,mode,"ios" | "md",undefined,false,false @@ -812,6 +816,7 @@ ion-popover,prop,componentProps,undefined | { [key: string]: any; },undefined,fa ion-popover,prop,cssClass,string | string[] | undefined,undefined,false,false ion-popover,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-popover,prop,event,any,undefined,false,false +ion-popover,prop,htmlAttributes,PopoverAttributes | undefined,undefined,false,false ion-popover,prop,keyboardClose,boolean,true,false,false ion-popover,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false ion-popover,prop,mode,"ios" | "md",undefined,false,false diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 9c7aad7dedb..e44e07918d6 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -5,7 +5,7 @@ * It contains typing information for all components that exist in this project. */ import { HTMLStencilElement, JSXBase } from "@stencil/core/internal"; -import { ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimeOptions, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, MenuChangeEventDetail, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerButton, PickerColumn, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, ViewController } from "./interface"; +import { ActionSheetAttributes, ActionSheetButton, AlertButton, AlertInput, AnimationBuilder, AutocompleteTypes, CheckboxChangeEventDetail, Color, ComponentProps, ComponentRef, DatetimeChangeEventDetail, DatetimeOptions, DomRenderFn, FooterHeightFn, FrameworkDelegate, HeaderFn, HeaderHeightFn, InputChangeEventDetail, ItemHeightFn, ItemRenderFn, ItemReorderEventDetail, LoadingAttributes, MenuChangeEventDetail, ModalAttributes, NavComponent, NavComponentWithProps, NavOptions, OverlayEventDetail, PickerAttributes, PickerButton, PickerColumn, PopoverAttributes, RadioGroupChangeEventDetail, RangeChangeEventDetail, RangeValue, RefresherEventDetail, RouteID, RouterDirection, RouterEventDetail, RouterOutletOptions, RouteWrite, ScrollBaseDetail, ScrollDetail, SearchbarChangeEventDetail, SegmentButtonLayout, SegmentChangeEventDetail, SelectChangeEventDetail, SelectInterface, SelectPopoverOption, Side, SpinnerTypes, StyleEventDetail, SwipeGestureHandler, TabBarChangedEventDetail, TabButtonClickEventDetail, TabButtonLayout, TextareaChangeEventDetail, TextFieldTypes, ToastButton, ToggleChangeEventDetail, TransitionDoneFn, TransitionInstruction, ViewController } from "./interface"; import { IonicSafeString } from "./utils/sanitization"; import { AlertAttributes } from "./components/alert/alert-interface"; import { NavigationHookCallback } from "./components/route/route-interface"; @@ -43,6 +43,10 @@ export namespace Components { * Title for the action sheet. */ "header"?: string; + /** + * Additional attributes to pass to the action sheet. + */ + "htmlAttributes"?: ActionSheetAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -1183,6 +1187,10 @@ export namespace Components { * Animation to use when the loading indicator is presented. */ "enterAnimation"?: AnimationBuilder; + /** + * Additional attributes to pass to the loader. + */ + "htmlAttributes"?: LoadingAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -1347,6 +1355,10 @@ export namespace Components { * Animation to use when the modal is presented. */ "enterAnimation"?: AnimationBuilder; + /** + * Additional attributes to pass to the modal. + */ + "htmlAttributes"?: ModalAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -1564,6 +1576,10 @@ export namespace Components { * @param name The name of the column. */ "getColumn": (name: string) => Promise; + /** + * Additional attributes to pass to the picker. + */ + "htmlAttributes"?: PickerAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -1636,6 +1652,10 @@ export namespace Components { * The event to pass to the popover animation. */ "event": any; + /** + * Additional attributes to pass to the popover. + */ + "htmlAttributes"?: PopoverAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -3356,6 +3376,10 @@ declare namespace LocalJSX { * Title for the action sheet. */ "header"?: string; + /** + * Additional attributes to pass to the action sheet. + */ + "htmlAttributes"?: ActionSheetAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -4534,6 +4558,10 @@ declare namespace LocalJSX { * Animation to use when the loading indicator is presented. */ "enterAnimation"?: AnimationBuilder; + /** + * Additional attributes to pass to the loader. + */ + "htmlAttributes"?: LoadingAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -4692,6 +4720,10 @@ declare namespace LocalJSX { * Animation to use when the modal is presented. */ "enterAnimation"?: AnimationBuilder; + /** + * Additional attributes to pass to the modal. + */ + "htmlAttributes"?: ModalAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -4826,6 +4858,10 @@ declare namespace LocalJSX { * Animation to use when the picker is presented. */ "enterAnimation"?: AnimationBuilder; + /** + * Additional attributes to pass to the picker. + */ + "htmlAttributes"?: PickerAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ @@ -4900,6 +4936,10 @@ declare namespace LocalJSX { * The event to pass to the popover animation. */ "event"?: any; + /** + * Additional attributes to pass to the popover. + */ + "htmlAttributes"?: PopoverAttributes; /** * If `true`, the keyboard will be automatically dismissed when the overlay is presented. */ diff --git a/core/src/components/action-sheet/action-sheet-interface.ts b/core/src/components/action-sheet/action-sheet-interface.ts index d7d8154b8be..7b33a74125c 100644 --- a/core/src/components/action-sheet/action-sheet-interface.ts +++ b/core/src/components/action-sheet/action-sheet-interface.ts @@ -1,3 +1,5 @@ +import { JSXBase } from '@stencil/core/internal'; + import { AnimationBuilder, Mode } from '../../interface'; export interface ActionSheetOptions { @@ -11,11 +13,14 @@ export interface ActionSheetOptions { mode?: Mode; keyboardClose?: boolean; id?: string; + htmlAttributes?: ActionSheetAttributes; enterAnimation?: AnimationBuilder; leaveAnimation?: AnimationBuilder; } +export interface ActionSheetAttributes extends JSXBase.HTMLAttributes {} + export interface ActionSheetButton { text?: string; role?: 'cancel' | 'destructive' | 'selected' | string; diff --git a/core/src/components/action-sheet/action-sheet.tsx b/core/src/components/action-sheet/action-sheet.tsx index 47581a62e59..c2e1007ea29 100644 --- a/core/src/components/action-sheet/action-sheet.tsx +++ b/core/src/components/action-sheet/action-sheet.tsx @@ -1,7 +1,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h, readTask } from '@stencil/core'; import { getIonMode } from '../../global/ionic-global'; -import { ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface'; +import { ActionSheetAttributes, ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface'; import { Gesture } from '../../utils/gesture'; import { createButtonActiveGesture } from '../../utils/gesture/button-active'; import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays'; @@ -90,6 +90,11 @@ export class ActionSheet implements ComponentInterface, OverlayInterface { */ @Prop() animated = true; + /** + * Additional attributes to pass to the action sheet. + */ + @Prop() htmlAttributes?: ActionSheetAttributes; + /** * Emitted after the alert has presented. */ @@ -228,6 +233,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface { } render() { + const { htmlAttributes } = this; const mode = getIonMode(this); const allButtons = this.getButtons(); const cancelButton = allButtons.find(b => b.role === 'cancel'); @@ -238,6 +244,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface { role="dialog" aria-modal="true" tabindex="-1" + {...htmlAttributes as any} style={{ zIndex: `${20000 + this.overlayIndex}`, }} diff --git a/core/src/components/action-sheet/readme.md b/core/src/components/action-sheet/readme.md index d40f2d0ea27..530dcd2f661 100644 --- a/core/src/components/action-sheet/readme.md +++ b/core/src/components/action-sheet/readme.md @@ -62,12 +62,19 @@ interface ActionSheetOptions { mode?: Mode; keyboardClose?: boolean; id?: string; + htmlAttributes?: ActionSheetAttributes; enterAnimation?: AnimationBuilder; leaveAnimation?: AnimationBuilder; } ``` +### ActionSheetAttributes + +```typescript +interface ActionSheetAttributes extends JSXBase.HTMLAttributes {} +``` + @@ -524,6 +531,7 @@ export default defineComponent({ | `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` | | `enterAnimation` | -- | Animation to use when the action sheet is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | | `header` | `header` | Title for the action sheet. | `string \| undefined` | `undefined` | +| `htmlAttributes` | -- | Additional attributes to pass to the action sheet. | `ActionSheetAttributes \| undefined` | `undefined` | | `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` | | `leaveAnimation` | -- | Animation to use when the action sheet is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | | `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` | diff --git a/core/src/components/action-sheet/test/basic/e2e.ts b/core/src/components/action-sheet/test/basic/e2e.ts index a98661d7650..423ba2ef4e7 100644 --- a/core/src/components/action-sheet/test/basic/e2e.ts +++ b/core/src/components/action-sheet/test/basic/e2e.ts @@ -111,3 +111,21 @@ test('action-sheet:rtl: basic, scroll without cancel', async () => { test('action-sheet:rtl: basic, custom backdrop', async () => { await testActionSheet(DIRECTORY, '#customBackdrop', true); }); + +// Attributes + +test('action-sheet: htmlAttributes', async () => { + const page = await newE2EPage({ url: '/src/components/action-sheet/test/basic?ionic:_testing=true' }); + + await page.click('#basic'); + await page.waitForSelector('#basic'); + + let toast = await page.find('ion-action-sheet'); + + expect(toast).not.toBe(null); + await toast.waitForVisible(); + + const attribute = await page.evaluate((el) => document.querySelector('ion-action-sheet').getAttribute('data-testid')); + + expect(attribute).toEqual('basic-action-sheet'); +}); diff --git a/core/src/components/action-sheet/test/basic/index.html b/core/src/components/action-sheet/test/basic/index.html index af0ab90ffb1..02c4f0c83ca 100644 --- a/core/src/components/action-sheet/test/basic/index.html +++ b/core/src/components/action-sheet/test/basic/index.html @@ -71,6 +71,9 @@ await openActionSheet({ header: "Albums", subHeader: 'This is a sub header inside of an action sheet', + htmlAttributes: { + 'data-testid': 'basic-action-sheet' + }, buttons: [{ text: 'Delete', role: 'destructive', diff --git a/core/src/components/alert/alert.tsx b/core/src/components/alert/alert.tsx index 88ff5077eea..5fe3024d81b 100644 --- a/core/src/components/alert/alert.tsx +++ b/core/src/components/alert/alert.tsx @@ -561,13 +561,14 @@ export class Alert implements ComponentInterface, OverlayInterface { const hdrId = `alert-${overlayIndex}-hdr`; const subHdrId = `alert-${overlayIndex}-sub-hdr`; const msgId = `alert-${overlayIndex}-msg`; - const role = htmlAttributes?.role || (this.inputs.length > 0 || this.buttons.length > 0 ? 'alertdialog' : 'alert'); + const role = this.inputs.length > 0 || this.buttons.length > 0 ? 'alertdialog' : 'alert'; return ( diff --git a/core/src/components/datetime/readme.md b/core/src/components/datetime/readme.md index 3dfbf85522a..c8c822ee97c 100644 --- a/core/src/components/datetime/readme.md +++ b/core/src/components/datetime/readme.md @@ -792,31 +792,31 @@ export default defineComponent({ ## Properties -| Property | Attribute | Description | Type | Default | -| ----------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | -| `cancelText` | `cancel-text` | The text to display on the picker's cancel button. | `string` | `'Cancel'` | -| `dayNames` | `day-names` | Full day of the week names. This can be used to provide locale names for each day in the week. Defaults to English. | `string \| string[] \| undefined` | `undefined` | -| `dayShortNames` | `day-short-names` | Short abbreviated day of the week names. This can be used to provide locale names for each day in the week. Defaults to English. Defaults to: `['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']` | `string \| string[] \| undefined` | `undefined` | -| `dayValues` | `day-values` | Values used to create the list of selectable days. By default every day is shown for the given month. However, to control exactly which days of the month to display, the `dayValues` input can take a number, an array of numbers, or a string of comma separated numbers. Note that even if the array days have an invalid number for the selected month, like `31` in February, it will correctly not show days which are not valid for the selected month. | `number \| number[] \| string \| undefined` | `undefined` | -| `disabled` | `disabled` | If `true`, the user cannot interact with the datetime. | `boolean` | `false` | -| `displayFormat` | `display-format` | The display format of the date and time as text that shows within the item. When the `pickerFormat` input is not used, then the `displayFormat` is used for both display the formatted text, and determining the datetime picker's columns. See the `pickerFormat` input description for more info. Defaults to `MMM D, YYYY`. | `string` | `'MMM D, YYYY'` | -| `displayTimezone` | `display-timezone` | The timezone to use for display purposes only. See [Date.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) for a list of supported timezones. If no value is provided, the component will default to displaying times in the user's local timezone. | `string \| undefined` | `undefined` | -| `doneText` | `done-text` | The text to display on the picker's "Done" button. | `string` | `'Done'` | -| `hourValues` | `hour-values` | Values used to create the list of selectable hours. By default the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However, to control exactly which hours to display, the `hourValues` input can take a number, an array of numbers, or a string of comma separated numbers. | `number \| number[] \| string \| undefined` | `undefined` | -| `max` | `max` | The maximum datetime allowed. Value must be a date string following the [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime), `1996-12-19`. The format does not have to be specific to an exact datetime. For example, the maximum could just be the year, such as `1994`. Defaults to the end of this year. | `string \| undefined` | `undefined` | -| `min` | `min` | The minimum datetime allowed. Value must be a date string following the [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime), such as `1996-12-19`. The format does not have to be specific to an exact datetime. For example, the minimum could just be the year, such as `1994`. Defaults to the beginning of the year, 100 years ago from today. | `string \| undefined` | `undefined` | -| `minuteValues` | `minute-values` | Values used to create the list of selectable minutes. By default the minutes range from `0` to `59`. However, to control exactly which minutes to display, the `minuteValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if the minute selections should only be every 15 minutes, then this input value would be `minuteValues="0,15,30,45"`. | `number \| number[] \| string \| undefined` | `undefined` | -| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` | -| `monthNames` | `month-names` | Full names for each month name. This can be used to provide locale month names. Defaults to English. | `string \| string[] \| undefined` | `undefined` | -| `monthShortNames` | `month-short-names` | Short abbreviated names for each month name. This can be used to provide locale month names. Defaults to English. | `string \| string[] \| undefined` | `undefined` | -| `monthValues` | `month-values` | Values used to create the list of selectable months. By default the month values range from `1` to `12`. However, to control exactly which months to display, the `monthValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if only summer months should be shown, then this input value would be `monthValues="6,7,8"`. Note that month numbers do *not* have a zero-based index, meaning January's value is `1`, and December's is `12`. | `number \| number[] \| string \| undefined` | `undefined` | -| `name` | `name` | The name of the control, which is submitted with the form data. | `string` | `this.inputId` | -| `pickerFormat` | `picker-format` | The format of the date and time picker columns the user selects. A datetime input can have one or many datetime parts, each getting their own column which allow individual selection of that particular datetime part. For example, year and month columns are two individually selectable columns which help choose an exact date from the datetime picker. Each column follows the string parse format. Defaults to use `displayFormat`. | `string \| undefined` | `undefined` | -| `pickerOptions` | -- | Any additional options that the picker interface can accept. See the [Picker API docs](../picker) for the picker options. | `undefined \| { columns?: PickerColumn[] \| undefined; buttons?: PickerButton[] \| undefined; cssClass?: string \| string[] \| undefined; showBackdrop?: boolean \| undefined; backdropDismiss?: boolean \| undefined; animated?: boolean \| undefined; mode?: Mode \| undefined; keyboardClose?: boolean \| undefined; id?: string \| undefined; enterAnimation?: AnimationBuilder \| undefined; leaveAnimation?: AnimationBuilder \| undefined; }` | `undefined` | -| `placeholder` | `placeholder` | The text to display when there's no date selected yet. Using lowercase to match the input attribute | `null \| string \| undefined` | `undefined` | -| `readonly` | `readonly` | If `true`, the datetime appears normal but is not interactive. | `boolean` | `false` | -| `value` | `value` | The value of the datetime as a valid ISO 8601 datetime string. | `null \| string \| undefined` | `undefined` | -| `yearValues` | `year-values` | Values used to create the list of selectable years. By default the year values range between the `min` and `max` datetime inputs. However, to control exactly which years to display, the `yearValues` input can take a number, an array of numbers, or string of comma separated numbers. For example, to show upcoming and recent leap years, then this input's value would be `yearValues="2024,2020,2016,2012,2008"`. | `number \| number[] \| string \| undefined` | `undefined` | +| Property | Attribute | Description | Type | Default | +| ----------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | +| `cancelText` | `cancel-text` | The text to display on the picker's cancel button. | `string` | `'Cancel'` | +| `dayNames` | `day-names` | Full day of the week names. This can be used to provide locale names for each day in the week. Defaults to English. | `string \| string[] \| undefined` | `undefined` | +| `dayShortNames` | `day-short-names` | Short abbreviated day of the week names. This can be used to provide locale names for each day in the week. Defaults to English. Defaults to: `['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']` | `string \| string[] \| undefined` | `undefined` | +| `dayValues` | `day-values` | Values used to create the list of selectable days. By default every day is shown for the given month. However, to control exactly which days of the month to display, the `dayValues` input can take a number, an array of numbers, or a string of comma separated numbers. Note that even if the array days have an invalid number for the selected month, like `31` in February, it will correctly not show days which are not valid for the selected month. | `number \| number[] \| string \| undefined` | `undefined` | +| `disabled` | `disabled` | If `true`, the user cannot interact with the datetime. | `boolean` | `false` | +| `displayFormat` | `display-format` | The display format of the date and time as text that shows within the item. When the `pickerFormat` input is not used, then the `displayFormat` is used for both display the formatted text, and determining the datetime picker's columns. See the `pickerFormat` input description for more info. Defaults to `MMM D, YYYY`. | `string` | `'MMM D, YYYY'` | +| `displayTimezone` | `display-timezone` | The timezone to use for display purposes only. See [Date.prototype.toLocaleString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString) for a list of supported timezones. If no value is provided, the component will default to displaying times in the user's local timezone. | `string \| undefined` | `undefined` | +| `doneText` | `done-text` | The text to display on the picker's "Done" button. | `string` | `'Done'` | +| `hourValues` | `hour-values` | Values used to create the list of selectable hours. By default the hour values range from `0` to `23` for 24-hour, or `1` to `12` for 12-hour. However, to control exactly which hours to display, the `hourValues` input can take a number, an array of numbers, or a string of comma separated numbers. | `number \| number[] \| string \| undefined` | `undefined` | +| `max` | `max` | The maximum datetime allowed. Value must be a date string following the [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime), `1996-12-19`. The format does not have to be specific to an exact datetime. For example, the maximum could just be the year, such as `1994`. Defaults to the end of this year. | `string \| undefined` | `undefined` | +| `min` | `min` | The minimum datetime allowed. Value must be a date string following the [ISO 8601 datetime format standard](https://www.w3.org/TR/NOTE-datetime), such as `1996-12-19`. The format does not have to be specific to an exact datetime. For example, the minimum could just be the year, such as `1994`. Defaults to the beginning of the year, 100 years ago from today. | `string \| undefined` | `undefined` | +| `minuteValues` | `minute-values` | Values used to create the list of selectable minutes. By default the minutes range from `0` to `59`. However, to control exactly which minutes to display, the `minuteValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if the minute selections should only be every 15 minutes, then this input value would be `minuteValues="0,15,30,45"`. | `number \| number[] \| string \| undefined` | `undefined` | +| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` | +| `monthNames` | `month-names` | Full names for each month name. This can be used to provide locale month names. Defaults to English. | `string \| string[] \| undefined` | `undefined` | +| `monthShortNames` | `month-short-names` | Short abbreviated names for each month name. This can be used to provide locale month names. Defaults to English. | `string \| string[] \| undefined` | `undefined` | +| `monthValues` | `month-values` | Values used to create the list of selectable months. By default the month values range from `1` to `12`. However, to control exactly which months to display, the `monthValues` input can take a number, an array of numbers, or a string of comma separated numbers. For example, if only summer months should be shown, then this input value would be `monthValues="6,7,8"`. Note that month numbers do *not* have a zero-based index, meaning January's value is `1`, and December's is `12`. | `number \| number[] \| string \| undefined` | `undefined` | +| `name` | `name` | The name of the control, which is submitted with the form data. | `string` | `this.inputId` | +| `pickerFormat` | `picker-format` | The format of the date and time picker columns the user selects. A datetime input can have one or many datetime parts, each getting their own column which allow individual selection of that particular datetime part. For example, year and month columns are two individually selectable columns which help choose an exact date from the datetime picker. Each column follows the string parse format. Defaults to use `displayFormat`. | `string \| undefined` | `undefined` | +| `pickerOptions` | -- | Any additional options that the picker interface can accept. See the [Picker API docs](../picker) for the picker options. | `undefined \| { columns?: PickerColumn[] \| undefined; buttons?: PickerButton[] \| undefined; cssClass?: string \| string[] \| undefined; showBackdrop?: boolean \| undefined; backdropDismiss?: boolean \| undefined; animated?: boolean \| undefined; mode?: Mode \| undefined; keyboardClose?: boolean \| undefined; id?: string \| undefined; htmlAttributes?: PickerAttributes \| undefined; enterAnimation?: AnimationBuilder \| undefined; leaveAnimation?: AnimationBuilder \| undefined; }` | `undefined` | +| `placeholder` | `placeholder` | The text to display when there's no date selected yet. Using lowercase to match the input attribute | `null \| string \| undefined` | `undefined` | +| `readonly` | `readonly` | If `true`, the datetime appears normal but is not interactive. | `boolean` | `false` | +| `value` | `value` | The value of the datetime as a valid ISO 8601 datetime string. | `null \| string \| undefined` | `undefined` | +| `yearValues` | `year-values` | Values used to create the list of selectable years. By default the year values range between the `min` and `max` datetime inputs. However, to control exactly which years to display, the `yearValues` input can take a number, an array of numbers, or string of comma separated numbers. For example, to show upcoming and recent leap years, then this input's value would be `yearValues="2024,2020,2016,2012,2008"`. | `number \| number[] \| string \| undefined` | `undefined` | ## Events diff --git a/core/src/components/loading/loading-interface.ts b/core/src/components/loading/loading-interface.ts index ac70933a2c6..4065863a7e9 100644 --- a/core/src/components/loading/loading-interface.ts +++ b/core/src/components/loading/loading-interface.ts @@ -1,3 +1,5 @@ +import { JSXBase } from '@stencil/core/internal'; + import { AnimationBuilder, Mode, SpinnerTypes } from '../../interface'; import { IonicSafeString } from '../../utils/sanitization'; @@ -13,7 +15,10 @@ export interface LoadingOptions { mode?: Mode; keyboardClose?: boolean; id?: string; + htmlAttributes?: LoadingAttributes; enterAnimation?: AnimationBuilder; leaveAnimation?: AnimationBuilder; } + +export interface LoadingAttributes extends JSXBase.HTMLAttributes {} diff --git a/core/src/components/loading/loading.tsx b/core/src/components/loading/loading.tsx index 7ac6f3c0817..1a497bc9c75 100644 --- a/core/src/components/loading/loading.tsx +++ b/core/src/components/loading/loading.tsx @@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Meth import { config } from '../../global/config'; import { getIonMode } from '../../global/ionic-global'; -import { AnimationBuilder, OverlayEventDetail, OverlayInterface, SpinnerTypes } from '../../interface'; +import { AnimationBuilder, LoadingAttributes, OverlayEventDetail, OverlayInterface, SpinnerTypes } from '../../interface'; import { BACKDROP, dismiss, eventMethod, prepareOverlay, present } from '../../utils/overlays'; import { IonicSafeString, sanitizeDOMString } from '../../utils/sanitization'; import { getClassMap } from '../../utils/theme'; @@ -92,6 +92,11 @@ export class Loading implements ComponentInterface, OverlayInterface { */ @Prop() animated = true; + /** + * Additional attributes to pass to the loader. + */ + @Prop() htmlAttributes?: LoadingAttributes; + /** * Emitted after the loading has presented. */ @@ -179,15 +184,16 @@ export class Loading implements ComponentInterface, OverlayInterface { } render() { - const { message, spinner } = this; + const { message, spinner, htmlAttributes } = this; const mode = getIonMode(this); return ( {} +``` + @@ -375,6 +382,7 @@ export default defineComponent({ | `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` | | `duration` | `duration` | Number of milliseconds to wait before dismissing the loading indicator. | `number` | `0` | | `enterAnimation` | -- | Animation to use when the loading indicator is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | +| `htmlAttributes` | -- | Additional attributes to pass to the loader. | `LoadingAttributes \| undefined` | `undefined` | | `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` | | `leaveAnimation` | -- | Animation to use when the loading indicator is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | | `message` | `message` | Optional text content to display in the loading indicator. | `IonicSafeString \| string \| undefined` | `undefined` | diff --git a/core/src/components/loading/test/basic/e2e.ts b/core/src/components/loading/test/basic/e2e.ts index e94e75e2c1a..f14c6992561 100644 --- a/core/src/components/loading/test/basic/e2e.ts +++ b/core/src/components/loading/test/basic/e2e.ts @@ -95,3 +95,19 @@ test('loading:rtl: backdrop standalone', async () => { test('loading:rtl: html content basic', async () => { await testLoading(DIRECTORY, '#html-content-loading', true); }); + +test('loading: htmlAttributes', async () => { + const page = await newE2EPage({ url: '/src/components/loading/test/basic?ionic:_testing=true' }); + + await page.click('#basic-loading'); + await page.waitForSelector('#basic-loading'); + + let alert = await page.find('ion-loading'); + + expect(alert).not.toBe(null); + await alert.waitForVisible(); + + const attribute = await page.evaluate((el) => document.querySelector('ion-loading').getAttribute('data-testid')); + + expect(attribute).toEqual('basic-loading'); +}); diff --git a/core/src/components/loading/test/basic/index.html b/core/src/components/loading/test/basic/index.html index 60a790c10c8..98e93ec079b 100644 --- a/core/src/components/loading/test/basic/index.html +++ b/core/src/components/loading/test/basic/index.html @@ -24,7 +24,7 @@ - Show Loading + Show Loading Show Default Loading Show Loading with long message Show Loading with no spinner diff --git a/core/src/components/modal/modal-interface.ts b/core/src/components/modal/modal-interface.ts index dc007b19965..de69acc800c 100644 --- a/core/src/components/modal/modal-interface.ts +++ b/core/src/components/modal/modal-interface.ts @@ -1,3 +1,5 @@ +import { JSXBase } from '@stencil/core/internal'; + import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Mode } from '../../interface'; export interface ModalOptions { @@ -14,7 +16,10 @@ export interface ModalOptions { mode?: Mode; keyboardClose?: boolean; id?: string; + htmlAttributes?: ModalAttributes; enterAnimation?: AnimationBuilder; leaveAnimation?: AnimationBuilder; } + +export interface ModalAttributes extends JSXBase.HTMLAttributes {} diff --git a/core/src/components/modal/modal.tsx b/core/src/components/modal/modal.tsx index f09d06a83c2..ffd345285a5 100644 --- a/core/src/components/modal/modal.tsx +++ b/core/src/components/modal/modal.tsx @@ -2,7 +2,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Meth import { config } from '../../global/config'; import { getIonMode } from '../../global/ionic-global'; -import { Animation, AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Gesture, OverlayEventDetail, OverlayInterface } from '../../interface'; +import { Animation, AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Gesture, ModalAttributes, OverlayEventDetail, OverlayInterface } from '../../interface'; import { attachComponent, detachComponent } from '../../utils/framework-delegate'; import { BACKDROP, activeAnimations, dismiss, eventMethod, prepareOverlay, present } from '../../utils/overlays'; import { getClassMap } from '../../utils/theme'; @@ -102,6 +102,11 @@ export class Modal implements ComponentInterface, OverlayInterface { */ @Prop() presentingElement?: HTMLElement; + /** + * Additional attributes to pass to the modal. + */ + @Prop() htmlAttributes?: ModalAttributes; + /** * Emitted after the modal has presented. */ @@ -265,6 +270,7 @@ export class Modal implements ComponentInterface, OverlayInterface { } render() { + const { htmlAttributes } = this; const mode = getIonMode(this); return ( @@ -272,14 +278,15 @@ export class Modal implements ComponentInterface, OverlayInterface { no-router aria-modal="true" tabindex="-1" + {...htmlAttributes as any} + style={{ + zIndex: `${20000 + this.overlayIndex}`, + }} class={{ [mode]: true, [`modal-card`]: this.presentingElement !== undefined && mode === 'ios', ...getClassMap(this.cssClass) }} - style={{ - zIndex: `${20000 + this.overlayIndex}`, - }} onIonBackdropTap={this.onBackdropTap} onIonDismiss={this.onDismiss} onIonModalDidPresent={this.onLifecycle} diff --git a/core/src/components/modal/readme.md b/core/src/components/modal/readme.md index 325493333cf..300bda2efd0 100644 --- a/core/src/components/modal/readme.md +++ b/core/src/components/modal/readme.md @@ -60,12 +60,19 @@ interface ModalOptions { mode?: Mode; keyboardClose?: boolean; id?: string; + htmlAttributes?: ModalAttributes; enterAnimation?: AnimationBuilder; leaveAnimation?: AnimationBuilder; } ``` +### ModalAttributes + +```typescript +interface ModalAttributes extends JSXBase.HTMLAttributes {} +``` + @@ -829,6 +836,7 @@ export default defineComponent({ | `componentProps` | -- | The data to pass to the modal component. | `undefined \| { [key: string]: any; }` | `undefined` | | `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` | | `enterAnimation` | -- | Animation to use when the modal is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | +| `htmlAttributes` | -- | Additional attributes to pass to the modal. | `ModalAttributes \| undefined` | `undefined` | | `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` | | `leaveAnimation` | -- | Animation to use when the modal is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | | `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` | diff --git a/core/src/components/modal/test/basic/e2e.ts b/core/src/components/modal/test/basic/e2e.ts index 06ce04f06bd..621252dffca 100644 --- a/core/src/components/modal/test/basic/e2e.ts +++ b/core/src/components/modal/test/basic/e2e.ts @@ -71,3 +71,19 @@ test('modal: basic', async () => { test('modal:rtl: basic', async () => { await testModal(DIRECTORY, '#basic-modal', true); }); + +test('modal: htmlAttributes', async () => { + const page = await newE2EPage({ url: '/src/components/modal/test/basic?ionic:_testing=true' }); + + await page.click('#basic-modal'); + await page.waitForSelector('#basic-modal'); + + let alert = await page.find('ion-modal'); + + expect(alert).not.toBe(null); + await alert.waitForVisible(); + + const attribute = await page.evaluate((el) => document.querySelector('ion-modal').getAttribute('data-testid')); + + expect(attribute).toEqual('basic-modal'); +}); diff --git a/core/src/components/modal/test/basic/index.html b/core/src/components/modal/test/basic/index.html index 510024c6845..d083df6a115 100644 --- a/core/src/components/modal/test/basic/index.html +++ b/core/src/components/modal/test/basic/index.html @@ -67,7 +67,10 @@

Content of doom

// present the modal const modalElement = Object.assign(document.createElement('ion-modal'), { - component: element + component: element, + htmlAttributes: { + 'data-testid': 'basic-modal' + } }); // listen for close event const button = element.querySelector('ion-button'); diff --git a/core/src/components/picker/picker-interface.ts b/core/src/components/picker/picker-interface.ts index 8079c0279e0..0dd94a335bb 100644 --- a/core/src/components/picker/picker-interface.ts +++ b/core/src/components/picker/picker-interface.ts @@ -1,3 +1,5 @@ +import { JSXBase } from '@stencil/core/internal'; + import { AnimationBuilder, Mode } from '../../interface'; export interface PickerOptions { @@ -11,11 +13,14 @@ export interface PickerOptions { mode?: Mode; keyboardClose?: boolean; id?: string; + htmlAttributes?: PickerAttributes; enterAnimation?: AnimationBuilder; leaveAnimation?: AnimationBuilder; } +export interface PickerAttributes extends JSXBase.HTMLAttributes {} + export interface PickerButton { text?: string; role?: string; diff --git a/core/src/components/picker/picker.tsx b/core/src/components/picker/picker.tsx index 595a8ae136d..5d64e75ab41 100644 --- a/core/src/components/picker/picker.tsx +++ b/core/src/components/picker/picker.tsx @@ -1,7 +1,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, State, h } from '@stencil/core'; import { getIonMode } from '../../global/ionic-global'; -import { AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface, PickerButton, PickerColumn } from '../../interface'; +import { AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface, PickerAttributes, PickerButton, PickerColumn } from '../../interface'; import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays'; import { getClassMap } from '../../utils/theme'; @@ -81,6 +81,11 @@ export class Picker implements ComponentInterface, OverlayInterface { */ @Prop() animated = true; + /** + * Additional attributes to pass to the picker. + */ + @Prop() htmlAttributes?: PickerAttributes; + /** * Emitted after the picker has presented. */ @@ -213,11 +218,16 @@ export class Picker implements ComponentInterface, OverlayInterface { } render() { + const { htmlAttributes } = this; const mode = getIonMode(this); return ( diff --git a/core/src/components/picker/readme.md b/core/src/components/picker/readme.md index 57c1d8ab654..c661f464226 100644 --- a/core/src/components/picker/readme.md +++ b/core/src/components/picker/readme.md @@ -62,12 +62,19 @@ interface PickerOptions { mode?: Mode; keyboardClose?: boolean; id?: string; + htmlAttributes?: PickerAttributes; enterAnimation?: AnimationBuilder; leaveAnimation?: AnimationBuilder; } ``` +### PickerAttributes + +```typescript +interface PickerAttributes extends JSXBase.HTMLAttributes {} +``` + @@ -228,6 +235,7 @@ export default { | `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` | | `duration` | `duration` | Number of milliseconds to wait before dismissing the picker. | `number` | `0` | | `enterAnimation` | -- | Animation to use when the picker is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | +| `htmlAttributes` | -- | Additional attributes to pass to the picker. | `PickerAttributes \| undefined` | `undefined` | | `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` | | `leaveAnimation` | -- | Animation to use when the picker is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | | `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` | diff --git a/core/src/components/picker/test/basic/index.html b/core/src/components/picker/test/basic/index.html index 95ace740b2f..d8e7af990fc 100644 --- a/core/src/components/picker/test/basic/index.html +++ b/core/src/components/picker/test/basic/index.html @@ -115,6 +115,9 @@ value: '12' }] }], + htmlAttributes: { + 'data-testid': 'basic-picker' + } cssClass: customClass }); diff --git a/core/src/components/popover/popover-interface.ts b/core/src/components/popover/popover-interface.ts index 9ded4006dd6..8c913519f1f 100644 --- a/core/src/components/popover/popover-interface.ts +++ b/core/src/components/popover/popover-interface.ts @@ -1,3 +1,5 @@ +import { JSXBase } from '@stencil/core/internal'; + import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, Mode } from '../../interface'; export interface PopoverOptions { @@ -14,7 +16,10 @@ export interface PopoverOptions { mode?: Mode; keyboardClose?: boolean; id?: string; + htmlAttributes?: PopoverAttributes; enterAnimation?: AnimationBuilder; leaveAnimation?: AnimationBuilder; } + +export interface PopoverAttributes extends JSXBase.HTMLAttributes {} diff --git a/core/src/components/popover/popover.tsx b/core/src/components/popover/popover.tsx index 3584883e1af..f4db06fd73c 100644 --- a/core/src/components/popover/popover.tsx +++ b/core/src/components/popover/popover.tsx @@ -1,7 +1,7 @@ import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h } from '@stencil/core'; import { getIonMode } from '../../global/ionic-global'; -import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, OverlayEventDetail, OverlayInterface } from '../../interface'; +import { AnimationBuilder, ComponentProps, ComponentRef, FrameworkDelegate, OverlayEventDetail, OverlayInterface, PopoverAttributes } from '../../interface'; import { attachComponent, detachComponent } from '../../utils/framework-delegate'; import { BACKDROP, dismiss, eventMethod, prepareOverlay, present } from '../../utils/overlays'; import { getClassMap } from '../../utils/theme'; @@ -96,6 +96,11 @@ export class Popover implements ComponentInterface, OverlayInterface { */ @Prop() animated = true; + /** + * Additional attributes to pass to the popover. + */ + @Prop() htmlAttributes?: PopoverAttributes; + /** * Emitted after the popover has presented. */ @@ -198,12 +203,13 @@ export class Popover implements ComponentInterface, OverlayInterface { render() { const mode = getIonMode(this); - const { onLifecycle } = this; + const { onLifecycle, htmlAttributes } = this; return ( {} +``` + @@ -392,6 +399,7 @@ export default defineComponent({ | `cssClass` | `css-class` | Additional classes to apply for custom CSS. If multiple classes are provided they should be separated by spaces. | `string \| string[] \| undefined` | `undefined` | | `enterAnimation` | -- | Animation to use when the popover is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | | `event` | `event` | The event to pass to the popover animation. | `any` | `undefined` | +| `htmlAttributes` | -- | Additional attributes to pass to the popover. | `PopoverAttributes \| undefined` | `undefined` | | `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` | | `leaveAnimation` | -- | Animation to use when the popover is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` | | `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` | diff --git a/core/src/components/popover/test/basic/e2e.ts b/core/src/components/popover/test/basic/e2e.ts index f586ea20108..c0ec276db0a 100644 --- a/core/src/components/popover/test/basic/e2e.ts +++ b/core/src/components/popover/test/basic/e2e.ts @@ -80,3 +80,19 @@ test('popover:rtl: no event', async () => { test('popover:rtl: custom class', async () => { await testPopover(DIRECTORY, '#custom-class-popover', true); }); + +test('popover: htmlAttributes', async () => { + const page = await newE2EPage({ url: '/src/components/popover/test/basic?ionic:_testing=true' }); + + await page.click('#basic-popover'); + await page.waitForSelector('#basic-popover'); + + let alert = await page.find('ion-popover'); + + expect(alert).not.toBe(null); + await alert.waitForVisible(); + + const attribute = await page.evaluate((el) => document.querySelector('ion-popover').getAttribute('data-testid')); + + expect(attribute).toEqual('basic-popover'); +}); diff --git a/core/src/components/popover/test/basic/index.html b/core/src/components/popover/test/basic/index.html index ce0f7089e03..bfc989a273c 100644 --- a/core/src/components/popover/test/basic/index.html +++ b/core/src/components/popover/test/basic/index.html @@ -29,7 +29,7 @@ - Show Popover + Show Popover Show Translucent Popover Show Long List Popover No Event Popover diff --git a/core/src/components/toast/toast.tsx b/core/src/components/toast/toast.tsx index eef86781635..bc01705556e 100644 --- a/core/src/components/toast/toast.tsx +++ b/core/src/components/toast/toast.tsx @@ -269,10 +269,13 @@ export class Toast implements ComponentInterface, OverlayInterface { 'toast-wrapper': true, [`toast-${this.position}`]: true }; - const role = this.htmlAttributes?.role || (allButtons.length > 0 ? 'dialog' : 'status'); + const role = allButtons.length > 0 ? 'dialog' : 'status'; return (