Skip to content

Commit bd96a81

Browse files
authored
feat(action-sheet, loading, modal, picker, popover): pass HTML attributes to host element (ionic-team#23929)
1 parent 73a1daf commit bd96a81

File tree

29 files changed

+268
-50
lines changed

29 files changed

+268
-50
lines changed

core/api.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ ion-action-sheet,prop,buttons,(string | ActionSheetButton)[],[],false,false
66
ion-action-sheet,prop,cssClass,string | string[] | undefined,undefined,false,false
77
ion-action-sheet,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
88
ion-action-sheet,prop,header,string | undefined,undefined,false,false
9+
ion-action-sheet,prop,htmlAttributes,ActionSheetAttributes | undefined,undefined,false,false
910
ion-action-sheet,prop,keyboardClose,boolean,true,false,false
1011
ion-action-sheet,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
1112
ion-action-sheet,prop,mode,"ios" | "md",undefined,false,false
@@ -334,7 +335,7 @@ ion-datetime,prop,monthShortNames,string | string[] | undefined,undefined,false,
334335
ion-datetime,prop,monthValues,number | number[] | string | undefined,undefined,false,false
335336
ion-datetime,prop,name,string,this.inputId,false,false
336337
ion-datetime,prop,pickerFormat,string | undefined,undefined,false,false
337-
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
338+
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
338339
ion-datetime,prop,placeholder,null | string | undefined,undefined,false,false
339340
ion-datetime,prop,readonly,boolean,false,false,false
340341
ion-datetime,prop,value,null | string | undefined,undefined,false,false
@@ -622,6 +623,7 @@ ion-loading,prop,backdropDismiss,boolean,false,false,false
622623
ion-loading,prop,cssClass,string | string[] | undefined,undefined,false,false
623624
ion-loading,prop,duration,number,0,false,false
624625
ion-loading,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
626+
ion-loading,prop,htmlAttributes,LoadingAttributes | undefined,undefined,false,false
625627
ion-loading,prop,keyboardClose,boolean,true,false,false
626628
ion-loading,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
627629
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
709711
ion-modal,prop,componentProps,undefined | { [key: string]: any; },undefined,false,false
710712
ion-modal,prop,cssClass,string | string[] | undefined,undefined,false,false
711713
ion-modal,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
714+
ion-modal,prop,htmlAttributes,ModalAttributes | undefined,undefined,false,false
712715
ion-modal,prop,keyboardClose,boolean,true,false,false
713716
ion-modal,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
714717
ion-modal,prop,mode,"ios" | "md",undefined,false,false
@@ -777,6 +780,7 @@ ion-picker,prop,columns,PickerColumn[],[],false,false
777780
ion-picker,prop,cssClass,string | string[] | undefined,undefined,false,false
778781
ion-picker,prop,duration,number,0,false,false
779782
ion-picker,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
783+
ion-picker,prop,htmlAttributes,PickerAttributes | undefined,undefined,false,false
780784
ion-picker,prop,keyboardClose,boolean,true,false,false
781785
ion-picker,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
782786
ion-picker,prop,mode,"ios" | "md",undefined,false,false
@@ -812,6 +816,7 @@ ion-popover,prop,componentProps,undefined | { [key: string]: any; },undefined,fa
812816
ion-popover,prop,cssClass,string | string[] | undefined,undefined,false,false
813817
ion-popover,prop,enterAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
814818
ion-popover,prop,event,any,undefined,false,false
819+
ion-popover,prop,htmlAttributes,PopoverAttributes | undefined,undefined,false,false
815820
ion-popover,prop,keyboardClose,boolean,true,false,false
816821
ion-popover,prop,leaveAnimation,((baseEl: any, opts?: any) => Animation) | undefined,undefined,false,false
817822
ion-popover,prop,mode,"ios" | "md",undefined,false,false

core/src/components.d.ts

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* It contains typing information for all components that exist in this project.
66
*/
77
import { HTMLStencilElement, JSXBase } from "@stencil/core/internal";
8-
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";
8+
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";
99
import { IonicSafeString } from "./utils/sanitization";
1010
import { AlertAttributes } from "./components/alert/alert-interface";
1111
import { NavigationHookCallback } from "./components/route/route-interface";
@@ -43,6 +43,10 @@ export namespace Components {
4343
* Title for the action sheet.
4444
*/
4545
"header"?: string;
46+
/**
47+
* Additional attributes to pass to the action sheet.
48+
*/
49+
"htmlAttributes"?: ActionSheetAttributes;
4650
/**
4751
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
4852
*/
@@ -1183,6 +1187,10 @@ export namespace Components {
11831187
* Animation to use when the loading indicator is presented.
11841188
*/
11851189
"enterAnimation"?: AnimationBuilder;
1190+
/**
1191+
* Additional attributes to pass to the loader.
1192+
*/
1193+
"htmlAttributes"?: LoadingAttributes;
11861194
/**
11871195
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
11881196
*/
@@ -1347,6 +1355,10 @@ export namespace Components {
13471355
* Animation to use when the modal is presented.
13481356
*/
13491357
"enterAnimation"?: AnimationBuilder;
1358+
/**
1359+
* Additional attributes to pass to the modal.
1360+
*/
1361+
"htmlAttributes"?: ModalAttributes;
13501362
/**
13511363
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
13521364
*/
@@ -1564,6 +1576,10 @@ export namespace Components {
15641576
* @param name The name of the column.
15651577
*/
15661578
"getColumn": (name: string) => Promise<PickerColumn | undefined>;
1579+
/**
1580+
* Additional attributes to pass to the picker.
1581+
*/
1582+
"htmlAttributes"?: PickerAttributes;
15671583
/**
15681584
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
15691585
*/
@@ -1636,6 +1652,10 @@ export namespace Components {
16361652
* The event to pass to the popover animation.
16371653
*/
16381654
"event": any;
1655+
/**
1656+
* Additional attributes to pass to the popover.
1657+
*/
1658+
"htmlAttributes"?: PopoverAttributes;
16391659
/**
16401660
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
16411661
*/
@@ -3356,6 +3376,10 @@ declare namespace LocalJSX {
33563376
* Title for the action sheet.
33573377
*/
33583378
"header"?: string;
3379+
/**
3380+
* Additional attributes to pass to the action sheet.
3381+
*/
3382+
"htmlAttributes"?: ActionSheetAttributes;
33593383
/**
33603384
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
33613385
*/
@@ -4534,6 +4558,10 @@ declare namespace LocalJSX {
45344558
* Animation to use when the loading indicator is presented.
45354559
*/
45364560
"enterAnimation"?: AnimationBuilder;
4561+
/**
4562+
* Additional attributes to pass to the loader.
4563+
*/
4564+
"htmlAttributes"?: LoadingAttributes;
45374565
/**
45384566
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
45394567
*/
@@ -4692,6 +4720,10 @@ declare namespace LocalJSX {
46924720
* Animation to use when the modal is presented.
46934721
*/
46944722
"enterAnimation"?: AnimationBuilder;
4723+
/**
4724+
* Additional attributes to pass to the modal.
4725+
*/
4726+
"htmlAttributes"?: ModalAttributes;
46954727
/**
46964728
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
46974729
*/
@@ -4826,6 +4858,10 @@ declare namespace LocalJSX {
48264858
* Animation to use when the picker is presented.
48274859
*/
48284860
"enterAnimation"?: AnimationBuilder;
4861+
/**
4862+
* Additional attributes to pass to the picker.
4863+
*/
4864+
"htmlAttributes"?: PickerAttributes;
48294865
/**
48304866
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
48314867
*/
@@ -4900,6 +4936,10 @@ declare namespace LocalJSX {
49004936
* The event to pass to the popover animation.
49014937
*/
49024938
"event"?: any;
4939+
/**
4940+
* Additional attributes to pass to the popover.
4941+
*/
4942+
"htmlAttributes"?: PopoverAttributes;
49034943
/**
49044944
* If `true`, the keyboard will be automatically dismissed when the overlay is presented.
49054945
*/

core/src/components/action-sheet/action-sheet-interface.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { JSXBase } from '@stencil/core/internal';
2+
13
import { AnimationBuilder, Mode } from '../../interface';
24

35
export interface ActionSheetOptions {
@@ -11,11 +13,14 @@ export interface ActionSheetOptions {
1113
mode?: Mode;
1214
keyboardClose?: boolean;
1315
id?: string;
16+
htmlAttributes?: ActionSheetAttributes;
1417

1518
enterAnimation?: AnimationBuilder;
1619
leaveAnimation?: AnimationBuilder;
1720
}
1821

22+
export interface ActionSheetAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
23+
1924
export interface ActionSheetButton {
2025
text?: string;
2126
role?: 'cancel' | 'destructive' | 'selected' | string;

core/src/components/action-sheet/action-sheet.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { Component, ComponentInterface, Element, Event, EventEmitter, Host, Method, Prop, h, readTask } from '@stencil/core';
22

33
import { getIonMode } from '../../global/ionic-global';
4-
import { ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
4+
import { ActionSheetAttributes, ActionSheetButton, AnimationBuilder, CssClassMap, OverlayEventDetail, OverlayInterface } from '../../interface';
55
import { Gesture } from '../../utils/gesture';
66
import { createButtonActiveGesture } from '../../utils/gesture/button-active';
77
import { BACKDROP, dismiss, eventMethod, isCancel, prepareOverlay, present, safeCall } from '../../utils/overlays';
@@ -90,6 +90,11 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
9090
*/
9191
@Prop() animated = true;
9292

93+
/**
94+
* Additional attributes to pass to the action sheet.
95+
*/
96+
@Prop() htmlAttributes?: ActionSheetAttributes;
97+
9398
/**
9499
* Emitted after the alert has presented.
95100
*/
@@ -228,6 +233,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
228233
}
229234

230235
render() {
236+
const { htmlAttributes } = this;
231237
const mode = getIonMode(this);
232238
const allButtons = this.getButtons();
233239
const cancelButton = allButtons.find(b => b.role === 'cancel');
@@ -238,6 +244,7 @@ export class ActionSheet implements ComponentInterface, OverlayInterface {
238244
role="dialog"
239245
aria-modal="true"
240246
tabindex="-1"
247+
{...htmlAttributes as any}
241248
style={{
242249
zIndex: `${20000 + this.overlayIndex}`,
243250
}}

core/src/components/action-sheet/readme.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,12 +62,19 @@ interface ActionSheetOptions {
6262
mode?: Mode;
6363
keyboardClose?: boolean;
6464
id?: string;
65+
htmlAttributes?: ActionSheetAttributes;
6566

6667
enterAnimation?: AnimationBuilder;
6768
leaveAnimation?: AnimationBuilder;
6869
}
6970
```
7071

72+
### ActionSheetAttributes
73+
74+
```typescript
75+
interface ActionSheetAttributes extends JSXBase.HTMLAttributes<HTMLElement> {}
76+
```
77+
7178
<!-- Auto Generated Below -->
7279

7380

@@ -524,6 +531,7 @@ export default defineComponent({
524531
| `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` |
525532
| `enterAnimation` | -- | Animation to use when the action sheet is presented. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
526533
| `header` | `header` | Title for the action sheet. | `string \| undefined` | `undefined` |
534+
| `htmlAttributes` | -- | Additional attributes to pass to the action sheet. | `ActionSheetAttributes \| undefined` | `undefined` |
527535
| `keyboardClose` | `keyboard-close` | If `true`, the keyboard will be automatically dismissed when the overlay is presented. | `boolean` | `true` |
528536
| `leaveAnimation` | -- | Animation to use when the action sheet is dismissed. | `((baseEl: any, opts?: any) => Animation) \| undefined` | `undefined` |
529537
| `mode` | `mode` | The mode determines which platform styles to use. | `"ios" \| "md"` | `undefined` |

core/src/components/action-sheet/test/basic/e2e.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,21 @@ test('action-sheet:rtl: basic, scroll without cancel', async () => {
111111
test('action-sheet:rtl: basic, custom backdrop', async () => {
112112
await testActionSheet(DIRECTORY, '#customBackdrop', true);
113113
});
114+
115+
// Attributes
116+
117+
test('action-sheet: htmlAttributes', async () => {
118+
const page = await newE2EPage({ url: '/src/components/action-sheet/test/basic?ionic:_testing=true' });
119+
120+
await page.click('#basic');
121+
await page.waitForSelector('#basic');
122+
123+
let toast = await page.find('ion-action-sheet');
124+
125+
expect(toast).not.toBe(null);
126+
await toast.waitForVisible();
127+
128+
const attribute = await page.evaluate((el) => document.querySelector('ion-action-sheet').getAttribute('data-testid'));
129+
130+
expect(attribute).toEqual('basic-action-sheet');
131+
});

core/src/components/action-sheet/test/basic/index.html

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@
7171
await openActionSheet({
7272
header: "Albums",
7373
subHeader: 'This is a sub header inside of an action sheet',
74+
htmlAttributes: {
75+
'data-testid': 'basic-action-sheet'
76+
},
7477
buttons: [{
7578
text: 'Delete',
7679
role: 'destructive',

core/src/components/alert/alert.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -561,13 +561,14 @@ export class Alert implements ComponentInterface, OverlayInterface {
561561
const hdrId = `alert-${overlayIndex}-hdr`;
562562
const subHdrId = `alert-${overlayIndex}-sub-hdr`;
563563
const msgId = `alert-${overlayIndex}-msg`;
564-
const role = htmlAttributes?.role || (this.inputs.length > 0 || this.buttons.length > 0 ? 'alertdialog' : 'alert');
564+
const role = this.inputs.length > 0 || this.buttons.length > 0 ? 'alertdialog' : 'alert';
565565

566566
return (
567567
<Host
568568
role={role}
569569
aria-modal="true"
570570
tabindex="-1"
571+
{...htmlAttributes as any}
571572
style={{
572573
zIndex: `${20000 + overlayIndex}`,
573574
}}
@@ -578,7 +579,6 @@ export class Alert implements ComponentInterface, OverlayInterface {
578579
}}
579580
onIonAlertWillDismiss={this.dispatchCancelHandler}
580581
onIonBackdropTap={this.onBackdropTap}
581-
{...htmlAttributes as any}
582582
>
583583

584584
<ion-backdrop tappable={this.backdropDismiss}/>

0 commit comments

Comments
 (0)