From 7794a1121526414c9d46fb1681b2b289494b822e Mon Sep 17 00:00:00 2001 From: Brandy Smith Date: Tue, 4 Mar 2025 13:29:00 -0500 Subject: [PATCH 1/6] chore(git): update automatic assignees (#30225) Co-authored-by: Brandy Smith <6577830+brandyscarney@users.noreply.github.com> --- .github/workflows/assign-issues.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/assign-issues.yml b/.github/workflows/assign-issues.yml index 8440cbad8ee..d06c1f52e10 100644 --- a/.github/workflows/assign-issues.yml +++ b/.github/workflows/assign-issues.yml @@ -13,6 +13,6 @@ jobs: - name: 'Auto-assign issue' uses: pozil/auto-assign-issue@39c06395cbac76e79afc4ad4e5c5c6db6ecfdd2e # v2.2.0 with: - assignees: brandyscarney, thetaPC, joselrio, rugoncalves, BenOsodrac, JoaoFerreira-FrontEnd, OS-giulianasilva, tanner-reits + assignees: brandyscarney, thetaPC, ShaneK numOfAssignee: 1 allowSelfAssign: false From b6b43ae2925f8a12b35cabd43abd9d838bc9714f Mon Sep 17 00:00:00 2001 From: r-yanyo Date: Thu, 6 Mar 2025 10:14:36 +0900 Subject: [PATCH 2/6] fix(capacitor): replace deprecated platform check method (#30195) Issue number: resolves internal ref: https://github.com/ionic-team/capacitor/issues/7884 --------- ## What is the current behavior? `this.platform.is('capacitor')` returns `false` in Capacitor App. ## What is the new behavior? `this.platform.is('capacitor')` returns as expected. ## Does this introduce a breaking change? - [ ] Yes - [x] No ## Other information It might also need to be fixed. https://github.com/ionic-team/ionic-framework/blob/14b6538d98303cb753d881ec6978fb98f53ed54c/core/src/utils/test/platform.utils.ts#L32 --------- Co-authored-by: ShaneK --- core/src/utils/platform.ts | 3 ++- core/src/utils/test/platform.utils.ts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/src/utils/platform.ts b/core/src/utils/platform.ts index 622b81cac15..438bab0a42e 100644 --- a/core/src/utils/platform.ts +++ b/core/src/utils/platform.ts @@ -99,7 +99,8 @@ const isCordova = (win: any): boolean => !!(win['cordova'] || win['phonegap'] || const isCapacitorNative = (win: any): boolean => { const capacitor = win['Capacitor']; - return !!capacitor?.isNative; + // TODO(ROU-11693): Remove when we no longer support Capacitor 2, which does not have isNativePlatform + return !!(capacitor?.isNative || (capacitor?.isNativePlatform && !!capacitor.isNativePlatform())); }; const isElectron = (win: Window): boolean => testUserAgent(win, /electron/i); diff --git a/core/src/utils/test/platform.utils.ts b/core/src/utils/test/platform.utils.ts index 0cc7bce9b2e..a9235d80247 100644 --- a/core/src/utils/test/platform.utils.ts +++ b/core/src/utils/test/platform.utils.ts @@ -29,7 +29,7 @@ export const PlatformConfiguration = { }, Capacitor: { Capacitor: { - isNative: true, + isNativePlatform: () => true, }, }, PWA: { From 2149ba2c8d56a3a8ef4a6de89de1292f6efe3031 Mon Sep 17 00:00:00 2001 From: Shane Date: Wed, 5 Mar 2025 17:14:45 -0800 Subject: [PATCH 3/6] fix(capacitor): use proper types for capacitor v7 support (#30228) Issue number: resolves internal --------- ## What is the current behavior? Currently, Capacitor types are outdated in Ionic Framework and we're accessing a type property that no longer exists in Capacitor 7.0.0+ ## What is the new behavior? This PR updates the capacitor version and addresses removal of `.Plugins` from `@capacitor/core`'s `CapacitorGlobal`, which we rely on to dynamically access plugins that the user may or may not have installed. The fix for this was creating a custom type definition to support accessing `Plugins`. While `Plugins` was removed from Capacitor if we were accessing it directly from core, we're pulling it from the window in the browser, where it's still exposed, so we just needed to make our type reflect that. ## Does this introduce a breaking change? - [ ] Yes - [X] No ## Other information Technically, this issue does not prevent Framework from working with Capacitor 7 because it's only a typing issue, but it's still a minor issue that should be addressed in our effort to support Capacitor 7. This PR, along with #30195, should make it ready for that. --- core/package-lock.json | 66 ++++++++++++++++-------------- core/package.json | 8 ++-- core/src/utils/native/capacitor.ts | 10 ++++- 3 files changed, 48 insertions(+), 36 deletions(-) diff --git a/core/package-lock.json b/core/package-lock.json index 1ef90673eb3..d8e0ef62101 100644 --- a/core/package-lock.json +++ b/core/package-lock.json @@ -15,10 +15,10 @@ }, "devDependencies": { "@axe-core/playwright": "^4.10.0", - "@capacitor/core": "^6.0.0", - "@capacitor/haptics": "^6.0.0", - "@capacitor/keyboard": "^6.0.0", - "@capacitor/status-bar": "^6.0.0", + "@capacitor/core": "^7.0.0", + "@capacitor/haptics": "^7.0.0", + "@capacitor/keyboard": "^7.0.0", + "@capacitor/status-bar": "^7.0.0", "@clack/prompts": "^0.10.0", "@ionic/eslint-config": "^0.3.0", "@ionic/prettier-config": "^2.0.0", @@ -663,39 +663,43 @@ "dev": true }, "node_modules/@capacitor/core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-6.2.0.tgz", - "integrity": "sha512-B9IlJtDpUqhhYb+T8+cp2Db/3RETX36STgjeU2kQZBs/SLAcFiMama227o+msRjLeo3DO+7HJjWVA1+XlyyPEg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.0.1.tgz", + "integrity": "sha512-1Ob9bvA/p8g8aNwK6VesxEekGXowLVf6APjkW4LRnr05H+7z/bke+Q5pn9zqh/GgTbIxAQ/rwZrAZvvxkdm1UA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/@capacitor/haptics": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-6.0.2.tgz", - "integrity": "sha512-xcFdIH4iIIeW2+1lzmlYMVicqB9ytaiuZ9NE3a9laKFPvMGC7hdj6i6tHFezwPJ/96xkHOwXT2b0F8Mh9xtTWg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-7.0.0.tgz", + "integrity": "sha512-8uI8rWyAbq8EzkjS+sHZSncyzujHzVbuLKgj8J5H0yUL6+r26F16gVA2iuQuIBvzbSMy7Y0/pUuWlwZr/H8AKg==", "dev": true, + "license": "MIT", "peerDependencies": { - "@capacitor/core": "^6.0.0" + "@capacitor/core": ">=7.0.0" } }, "node_modules/@capacitor/keyboard": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-6.0.3.tgz", - "integrity": "sha512-V/mURxBI68HvClYjrGBlOriWkwYN7r+cWid/igJz/3scNc/V81DgQ9fpoLr4W0I5NY7YxOesjIJLuLO+LT18mQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-7.0.0.tgz", + "integrity": "sha512-Tqwy8wG+sx4UqiFCX4Q+bFw6uKgG7BiHKAPpeefoIgoEB8H8Jf3xZNZoVPnJIMuPsCdSvuyHXZbJXH9IEEirGA==", "dev": true, + "license": "MIT", "peerDependencies": { - "@capacitor/core": "^6.0.0" + "@capacitor/core": ">=7.0.0" } }, "node_modules/@capacitor/status-bar": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-6.0.2.tgz", - "integrity": "sha512-AmRIX6QvFemItlY7/69ARkIAqitRQqJ2qwgZmD1KqgFb78pH+XFXm1guvS/a8CuOOm/IqZ4ddDbl20yxtBqzGA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-7.0.0.tgz", + "integrity": "sha512-wsvPkWkoSOXMIgVHu4c6P1sOuDSZ1ClUo5OpLRwj7u8DYzlV4jlmNzztQn2Lvsiqx1z4kfukSaqe40k1Lo4c9g==", "dev": true, + "license": "MIT", "peerDependencies": { - "@capacitor/core": "^6.0.0" + "@capacitor/core": ">=7.0.0" } }, "node_modules/@clack/core": { @@ -10977,32 +10981,32 @@ "dev": true }, "@capacitor/core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-6.2.0.tgz", - "integrity": "sha512-B9IlJtDpUqhhYb+T8+cp2Db/3RETX36STgjeU2kQZBs/SLAcFiMama227o+msRjLeo3DO+7HJjWVA1+XlyyPEg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@capacitor/core/-/core-7.0.1.tgz", + "integrity": "sha512-1Ob9bvA/p8g8aNwK6VesxEekGXowLVf6APjkW4LRnr05H+7z/bke+Q5pn9zqh/GgTbIxAQ/rwZrAZvvxkdm1UA==", "dev": true, "requires": { "tslib": "^2.1.0" } }, "@capacitor/haptics": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-6.0.2.tgz", - "integrity": "sha512-xcFdIH4iIIeW2+1lzmlYMVicqB9ytaiuZ9NE3a9laKFPvMGC7hdj6i6tHFezwPJ/96xkHOwXT2b0F8Mh9xtTWg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@capacitor/haptics/-/haptics-7.0.0.tgz", + "integrity": "sha512-8uI8rWyAbq8EzkjS+sHZSncyzujHzVbuLKgj8J5H0yUL6+r26F16gVA2iuQuIBvzbSMy7Y0/pUuWlwZr/H8AKg==", "dev": true, "requires": {} }, "@capacitor/keyboard": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-6.0.3.tgz", - "integrity": "sha512-V/mURxBI68HvClYjrGBlOriWkwYN7r+cWid/igJz/3scNc/V81DgQ9fpoLr4W0I5NY7YxOesjIJLuLO+LT18mQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@capacitor/keyboard/-/keyboard-7.0.0.tgz", + "integrity": "sha512-Tqwy8wG+sx4UqiFCX4Q+bFw6uKgG7BiHKAPpeefoIgoEB8H8Jf3xZNZoVPnJIMuPsCdSvuyHXZbJXH9IEEirGA==", "dev": true, "requires": {} }, "@capacitor/status-bar": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-6.0.2.tgz", - "integrity": "sha512-AmRIX6QvFemItlY7/69ARkIAqitRQqJ2qwgZmD1KqgFb78pH+XFXm1guvS/a8CuOOm/IqZ4ddDbl20yxtBqzGA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@capacitor/status-bar/-/status-bar-7.0.0.tgz", + "integrity": "sha512-wsvPkWkoSOXMIgVHu4c6P1sOuDSZ1ClUo5OpLRwj7u8DYzlV4jlmNzztQn2Lvsiqx1z4kfukSaqe40k1Lo4c9g==", "dev": true, "requires": {} }, diff --git a/core/package.json b/core/package.json index 092fc9759fd..80db8b924ed 100644 --- a/core/package.json +++ b/core/package.json @@ -37,10 +37,10 @@ }, "devDependencies": { "@axe-core/playwright": "^4.10.0", - "@capacitor/core": "^6.0.0", - "@capacitor/haptics": "^6.0.0", - "@capacitor/keyboard": "^6.0.0", - "@capacitor/status-bar": "^6.0.0", + "@capacitor/core": "^7.0.0", + "@capacitor/haptics": "^7.0.0", + "@capacitor/keyboard": "^7.0.0", + "@capacitor/status-bar": "^7.0.0", "@clack/prompts": "^0.10.0", "@ionic/eslint-config": "^0.3.0", "@ionic/prettier-config": "^2.0.0", diff --git a/core/src/utils/native/capacitor.ts b/core/src/utils/native/capacitor.ts index 5554f28f6e1..0d31b20dfe2 100644 --- a/core/src/utils/native/capacitor.ts +++ b/core/src/utils/native/capacitor.ts @@ -1,9 +1,17 @@ import type { CapacitorGlobal } from '@capacitor/core'; import { win } from '@utils/browser'; +type CustomCapacitorGlobal = CapacitorGlobal & { + // Capacitor from @capacitor/core no longer exports Plugins, but we're pulling + // Capacitor from window.Capacitor, which does + Plugins: { + [key: string]: any; + }; +}; + export const getCapacitor = () => { if (win !== undefined) { - return (win as any).Capacitor as CapacitorGlobal; + return (win as any).Capacitor as CustomCapacitorGlobal; } return undefined; }; From 4df0e0f4c00faec33f5ddc802945bf4ad9dc53d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Rio?= Date: Thu, 6 Mar 2025 11:16:04 +0000 Subject: [PATCH 4/6] fix(alert): change focused element and improve keyboard navigation (#30220) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Issue number: internal ## What is the current behavior? > Once Alert gets open the focusable element was the ion-alert itself. > Screenshot 2025-02-27 at 18 07 19 ## What is the new behavior? In order to mimick native alert a11y behaviour... Changed the focused element based on the amount of existing buttons. > If there is only 1 button, it should be that one focused > Screenshot 2025-02-27 at 18 04 52 > Otherwise it should focus the `.alert-wrapper` container > Screenshot 2025-02-27 at 18 05 02 > > **NOTE**: The yellow outline it's just for demo purposes, it was not implemented 🤪 ## Does this introduce a breaking change? - [ ] Yes - [X] No ## Other information - Also updated support to the shiftTab keyboard navigation. - Updated tests and screenshots with the latest changes. --------- Co-authored-by: Maria Hutt --- core/src/components/alert/alert.tsx | 44 ++++++++++++++---- .../components/alert/test/a11y/alert.e2e.ts | 5 +- ...kbox-scale-ios-ltr-Mobile-Chrome-linux.png | Bin 37357 -> 35428 bytes ...box-scale-ios-ltr-Mobile-Firefox-linux.png | Bin 41463 -> 44688 bytes ...kbox-scale-ios-ltr-Mobile-Safari-linux.png | Bin 32974 -> 34580 bytes ...ckbox-scale-md-ltr-Mobile-Chrome-linux.png | Bin 35719 -> 33135 bytes ...kbox-scale-md-ltr-Mobile-Firefox-linux.png | Bin 42961 -> 42749 bytes ...ckbox-scale-md-ltr-Mobile-Safari-linux.png | Bin 32379 -> 32514 bytes ...-text-wrap-ios-ltr-Mobile-Chrome-linux.png | Bin 15540 -> 15097 bytes ...text-wrap-ios-ltr-Mobile-Firefox-linux.png | Bin 21009 -> 22669 bytes ...-text-wrap-ios-ltr-Mobile-Safari-linux.png | Bin 13964 -> 15117 bytes ...adio-scale-ios-ltr-Mobile-Chrome-linux.png | Bin 29260 -> 27803 bytes ...dio-scale-ios-ltr-Mobile-Firefox-linux.png | Bin 35220 -> 36399 bytes ...adio-scale-ios-ltr-Mobile-Safari-linux.png | Bin 25959 -> 27212 bytes ...radio-scale-md-ltr-Mobile-Chrome-linux.png | Bin 37357 -> 34622 bytes ...adio-scale-md-ltr-Mobile-Firefox-linux.png | Bin 44014 -> 44735 bytes ...radio-scale-md-ltr-Mobile-Safari-linux.png | Bin 33440 -> 33507 bytes ...-text-wrap-ios-ltr-Mobile-Chrome-linux.png | Bin 13844 -> 13535 bytes ...text-wrap-ios-ltr-Mobile-Firefox-linux.png | Bin 20353 -> 21439 bytes ...-text-wrap-ios-ltr-Mobile-Safari-linux.png | Bin 12459 -> 13645 bytes ...ert-scale-ios-ltr-Mobile-Firefox-linux.png | Bin 23864 -> 24956 bytes ...lert-scale-ios-ltr-Mobile-Safari-linux.png | Bin 15890 -> 17040 bytes ...lert-scale-md-ltr-Mobile-Firefox-linux.png | Bin 31372 -> 30632 bytes ...alert-scale-md-ltr-Mobile-Safari-linux.png | Bin 19290 -> 19392 bytes ...lds-scale-ios-ltr-Mobile-Firefox-linux.png | Bin 31064 -> 32438 bytes ...elds-scale-ios-ltr-Mobile-Safari-linux.png | Bin 22688 -> 23820 bytes ...elds-scale-md-ltr-Mobile-Firefox-linux.png | Bin 36375 -> 36012 bytes ...ields-scale-md-ltr-Mobile-Safari-linux.png | Bin 24320 -> 24535 bytes .../components/alert/test/alert-id.spec.tsx | 6 +-- .../components/alert/test/basic/alert.e2e.ts | 3 +- ...pleButtons-ios-ltr-Mobile-Chrome-linux.png | Bin 12006 -> 11856 bytes ...leButtons-ios-ltr-Mobile-Firefox-linux.png | Bin 19060 -> 20124 bytes ...pleButtons-ios-ltr-Mobile-Safari-linux.png | Bin 10683 -> 11764 bytes ...ttons-ios-ltr-dark-Mobile-Chrome-linux.png | Bin 11858 -> 10744 bytes ...tons-ios-ltr-dark-Mobile-Firefox-linux.png | Bin 18911 -> 20145 bytes ...ttons-ios-ltr-dark-Mobile-Safari-linux.png | Bin 9613 -> 10822 bytes ...pleButtons-ios-rtl-Mobile-Chrome-linux.png | Bin 12011 -> 11864 bytes ...leButtons-ios-rtl-Mobile-Firefox-linux.png | Bin 18900 -> 19957 bytes ...pleButtons-ios-rtl-Mobile-Safari-linux.png | Bin 10689 -> 11769 bytes ...ttons-ios-rtl-dark-Mobile-Chrome-linux.png | Bin 11928 -> 10747 bytes ...tons-ios-rtl-dark-Mobile-Firefox-linux.png | Bin 18735 -> 19971 bytes ...ttons-ios-rtl-dark-Mobile-Safari-linux.png | Bin 9648 -> 10826 bytes ...ipleButtons-md-ltr-Mobile-Chrome-linux.png | Bin 15920 -> 14514 bytes ...pleButtons-md-ltr-Mobile-Firefox-linux.png | Bin 26545 -> 25812 bytes ...ipleButtons-md-ltr-Mobile-Safari-linux.png | Bin 13989 -> 14071 bytes ...uttons-md-ltr-dark-Mobile-Chrome-linux.png | Bin 11627 -> 10781 bytes ...ttons-md-ltr-dark-Mobile-Firefox-linux.png | Bin 19774 -> 19395 bytes ...uttons-md-ltr-dark-Mobile-Safari-linux.png | Bin 10022 -> 10483 bytes ...ipleButtons-md-rtl-Mobile-Chrome-linux.png | Bin 15908 -> 14515 bytes ...pleButtons-md-rtl-Mobile-Firefox-linux.png | Bin 26381 -> 25598 bytes ...ipleButtons-md-rtl-Mobile-Safari-linux.png | Bin 13989 -> 14063 bytes ...uttons-md-rtl-dark-Mobile-Chrome-linux.png | Bin 11632 -> 10792 bytes ...ttons-md-rtl-dark-Mobile-Firefox-linux.png | Bin 19608 -> 19185 bytes ...uttons-md-rtl-dark-Mobile-Safari-linux.png | Bin 10010 -> 10475 bytes 54 files changed, 44 insertions(+), 14 deletions(-) diff --git a/core/src/components/alert/alert.tsx b/core/src/components/alert/alert.tsx index ee2e07244ca..dc598fbdf0a 100644 --- a/core/src/components/alert/alert.tsx +++ b/core/src/components/alert/alert.tsx @@ -237,6 +237,18 @@ export class Alert implements ComponentInterface, OverlayInterface { return; } + /** + * Ensure when alert container is being focused, and the user presses the tab + shift keys, the focus will be set to the last alert button. + */ + if (ev.target.classList.contains('alert-wrapper')) { + if (ev.key === 'Tab' && ev.shiftKey) { + ev.preventDefault(); + const lastChildBtn = this.wrapperEl?.querySelector('.alert-button:last-child') as HTMLButtonElement; + lastChildBtn.focus(); + return; + } + } + // The only inputs we want to navigate between using arrow keys are the radios // ignore the keydown event if it is not on a radio button if ( @@ -400,7 +412,19 @@ export class Alert implements ComponentInterface, OverlayInterface { await this.delegateController.attachViewToDom(); - await present(this, 'alertEnter', iosEnterAnimation, mdEnterAnimation); + await present(this, 'alertEnter', iosEnterAnimation, mdEnterAnimation).then(() => { + /** + * Check if alert has only one button and no inputs. + * If so, then focus on the button. Otherwise, focus the alert wrapper. + * This will map to the default native alert behavior. + */ + if (this.buttons.length === 1 && this.inputs.length === 0) { + const queryBtn = this.wrapperEl?.querySelector('.alert-button') as HTMLButtonElement; + queryBtn.focus(); + } else { + this.wrapperEl?.focus(); + } + }); unlock(); } @@ -725,8 +749,8 @@ export class Alert implements ComponentInterface, OverlayInterface { const { overlayIndex, header, subHeader, message, htmlAttributes } = this; const mode = getIonMode(this); const hdrId = `alert-${overlayIndex}-hdr`; - const subHdrId = `alert-${overlayIndex}-sub-hdr`; const msgId = `alert-${overlayIndex}-msg`; + const subHdrId = `alert-${overlayIndex}-sub-hdr`; const role = this.inputs.length > 0 || this.buttons.length > 0 ? 'alertdialog' : 'alert'; /** @@ -739,12 +763,7 @@ export class Alert implements ComponentInterface, OverlayInterface { return (