Compare commits
38 Commits
liamdebeas
...
FW-119
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32b679dbe3 | ||
|
|
4d6edee89c | ||
|
|
4b79bbef7d | ||
|
|
ac7631a324 | ||
|
|
b5cb828861 | ||
|
|
101ad5402f | ||
|
|
de35fa8b94 | ||
|
|
c766528a17 | ||
|
|
9b3cf9fbc2 | ||
|
|
ee5da7a747 | ||
|
|
c4bfc783e0 | ||
|
|
0137e732ce | ||
|
|
88ecb29e39 | ||
|
|
f726c35868 | ||
|
|
4a9d84ecbd | ||
|
|
f08759c2b8 | ||
|
|
2053bc77a6 | ||
|
|
02e05bd7cb | ||
|
|
fa387cb2a2 | ||
|
|
8ab116150c | ||
|
|
8c9182c52f | ||
|
|
c0a8e7a95d | ||
|
|
0c5a2967d8 | ||
|
|
6ebb3c4e38 | ||
|
|
cdcb6decbd | ||
|
|
652ea169b7 | ||
|
|
42c09a7ea1 | ||
|
|
c23be1befd | ||
|
|
a2923aaeb3 | ||
|
|
eeab96de55 | ||
|
|
ca0923812a | ||
|
|
1be956bd18 | ||
|
|
8ad66c03d7 | ||
|
|
dcea071daa | ||
|
|
9cab6052fb | ||
|
|
379e804fbf | ||
|
|
07f4121658 | ||
|
|
bf3426dad7 |
47
.github/CODEOWNERS
vendored
@@ -21,65 +21,22 @@
|
||||
/packages/angular-server @sean-perkins @thetaPC
|
||||
/packages/angular/test @thetaPC
|
||||
|
||||
## React
|
||||
|
||||
/packages/react/ @amandaejohnston
|
||||
/packages/react-router @amandaejohnston
|
||||
/packages/react/test-app/
|
||||
/packages/react-router/test-app/
|
||||
|
||||
## Vue
|
||||
|
||||
/packages/vue/ @liamdebeasi @thetaPC
|
||||
/packages/vue/ @thetaPC
|
||||
/packages/vue-router/ @liamdebeasi @thetaPC
|
||||
/packages/vue/test/ @thetaPC
|
||||
/packages/vue-router/__tests__ @thetaPC
|
||||
|
||||
# Components
|
||||
|
||||
/core/src/components/accordion/ @liamdebeasi
|
||||
/core/src/components/accordion-group/ @liamdebeasi
|
||||
|
||||
/core/src/components/checkbox/ @amandaejohnston
|
||||
|
||||
/core/src/components/datetime/ @liamdebeasi @amandaejohnston @sean-perkins
|
||||
/core/src/components/datetime-button/ @liamdebeasi
|
||||
|
||||
/core/src/components/item/ @brandyscarney
|
||||
|
||||
/core/src/components/menu/ @amandaejohnston
|
||||
/core/src/components/menu-toggle/ @amandaejohnston
|
||||
/core/src/components/datetime/ @sean-perkins
|
||||
|
||||
/core/src/components/nav/ @sean-perkins
|
||||
/core/src/components/nav-link/ @sean-perkins
|
||||
|
||||
/core/src/components/picker/ @liamdebeasi
|
||||
/core/src/components/picker-column/ @liamdebeasi
|
||||
|
||||
/core/src/components/radio/ @amandaejohnston
|
||||
/core/src/components/radio-group/ @amandaejohnston
|
||||
|
||||
/core/src/components/refresher/ @liamdebeasi
|
||||
/core/src/components/refresher-content/ @liamdebeasi
|
||||
|
||||
/core/src/components/searchbar/ @brandyscarney
|
||||
|
||||
/core/src/components/segment/ @brandyscarney
|
||||
/core/src/components/segment-button/ @brandyscarney
|
||||
|
||||
/core/src/components/skeleton-text/ @brandyscarney
|
||||
|
||||
# Utilities
|
||||
|
||||
/core/src/utils/animation/ @liamdebeasi
|
||||
/core/src/utils/content/ @sean-perkins
|
||||
/core/src/utils/gesture/ @liamdebeasi
|
||||
/core/src/utils/input-shims/ @liamdebeasi
|
||||
/core/src/utils/keyboard/ @liamdebeasi
|
||||
/core/src/utils/logging/ @amandaejohnston
|
||||
/core/src/utils/sanitization/ @liamdebeasi
|
||||
/core/src/utils/tap-click/ @liamdebeasi
|
||||
/core/src/utils/transition/ @liamdebeasi
|
||||
|
||||
/core/src/css/ @brandyscarney
|
||||
/core/src/themes/ @brandyscarney
|
||||
|
||||
2
.github/workflows/assign-issues.yml
vendored
@@ -13,6 +13,6 @@ jobs:
|
||||
- name: 'Auto-assign issue'
|
||||
uses: pozil/auto-assign-issue@edee9537367a8fbc625d27f9e10aa8bad47b8723 # v1.13.0
|
||||
with:
|
||||
assignees: liamdebeasi, sean-perkins, brandyscarney, amandaejohnston, mapsandapps, thetaPC
|
||||
assignees: liamdebeasi, sean-perkins, brandyscarney, amandaejohnston, thetaPC
|
||||
numOfAssignee: 1
|
||||
allowSelfAssign: false
|
||||
|
||||
8
.github/workflows/release-ionic.yml
vendored
@@ -41,8 +41,8 @@ jobs:
|
||||
uses: ./.github/workflows/actions/upload-archive
|
||||
with:
|
||||
name: ionic-docs
|
||||
output: docs/DocsBuild.zip
|
||||
paths: docs/core.json docs/core.d.ts
|
||||
output: packages/docs/DocsBuild.zip
|
||||
paths: packages/docs/core.json packages/docs/core.d.ts
|
||||
|
||||
release-docs:
|
||||
needs: [release-core]
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
uses: ./.github/workflows/actions/download-archive
|
||||
with:
|
||||
name: ionic-docs
|
||||
path: ./docs
|
||||
path: ./packages/docs
|
||||
filename: DocsBuild.zip
|
||||
- uses: ./.github/workflows/actions/publish-npm
|
||||
with:
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
tag: ${{ inputs.tag }}
|
||||
version: ${{ inputs.version }}
|
||||
preid: ${{ inputs.preid }}
|
||||
working-directory: 'docs'
|
||||
working-directory: 'packages/docs'
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
|
||||
release-angular:
|
||||
|
||||
61
CHANGELOG.md
@@ -3,6 +3,67 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
|
||||
## [7.8.3](https://github.com/ionic-team/ionic-framework/compare/v7.8.2...v7.8.3) (2024-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** activated outline button in toolbar no longer blends into background on MD dark mode ([#29216](https://github.com/ionic-team/ionic-framework/issues/29216)) ([ee5da7a](https://github.com/ionic-team/ionic-framework/commit/ee5da7a747c0a0b420c5e371a9fe9ec4938d179e))
|
||||
* **popover:** viewport can be scrolled if no content present ([#29215](https://github.com/ionic-team/ionic-framework/issues/29215)) ([f08759c](https://github.com/ionic-team/ionic-framework/commit/f08759c2b8256ff66f8d1901bd8e0be4617db262)), closes [#29211](https://github.com/ionic-team/ionic-framework/issues/29211)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-rc.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.4...v8.0.0-rc.0) (2024-03-27)
|
||||
|
||||
**Note:** Version bump only for package ionic-framework
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.4](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.3...v8.0.0-beta.4) (2024-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **angular:** schematics account for new theme files ([#29185](https://github.com/ionic-team/ionic-framework/issues/29185)) ([b0a10df](https://github.com/ionic-team/ionic-framework/commit/b0a10dfa56a65ee3905cc2c3d48d2221a42f222f))
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **haptics:** remove cordova haptics support ([#29186](https://github.com/ionic-team/ionic-framework/issues/29186)) ([9efeb0a](https://github.com/ionic-team/ionic-framework/commit/9efeb0ad31aadee5f5ae542641d928ecf93fe82a))
|
||||
* **searchbar:** autocapitalize defaults to off ([#29107](https://github.com/ionic-team/ionic-framework/issues/29107)) ([6e477b7](https://github.com/ionic-team/ionic-framework/commit/6e477b743e41b2b37627c8208901704f599b762a))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **button:** add circular shape as round ([#29161](https://github.com/ionic-team/ionic-framework/issues/29161)) ([44529f0](https://github.com/ionic-team/ionic-framework/commit/44529f0a62f1b1ce42750a20f19e829b2789febd))
|
||||
* **input:** add input-password-toggle component ([#29175](https://github.com/ionic-team/ionic-framework/issues/29175)) ([6c500fd](https://github.com/ionic-team/ionic-framework/commit/6c500fd6b2e2553c11fcddc9d86ac9a29f76e172))
|
||||
* remove css animations support for ionic animations ([#29123](https://github.com/ionic-team/ionic-framework/issues/29123)) ([892594d](https://github.com/ionic-team/ionic-framework/commit/892594de0665e8fc5c8a737d292812842ea03d64))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **searchbar:** The `autocapitalize` property on Searchbar now defaults to `'off'`.
|
||||
* **haptics:** Support for the Cordova Haptics plugin has been removed. Components that integrate with haptics, such as `ion-picker` and `ion-toggle`, will continue to function but will no longer play haptics in Cordova environments. Developers should migrate to Capacitor to continue to have haptics in these components.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.2](https://github.com/ionic-team/ionic-framework/compare/v7.8.1...v7.8.2) (2024-03-27)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **searchbar:** autocapitalize is initialized correctly ([#29197](https://github.com/ionic-team/ionic-framework/issues/29197)) ([8ad66c0](https://github.com/ionic-team/ionic-framework/commit/8ad66c03d777edcab19c97cba696b171acc2d2e8)), closes [#29193](https://github.com/ionic-team/ionic-framework/issues/29193)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.3](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.2...v8.0.0-beta.3) (2024-03-20)
|
||||
|
||||
|
||||
|
||||
@@ -3,6 +3,63 @@
|
||||
All notable changes to this project will be documented in this file.
|
||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||
|
||||
|
||||
## [7.8.3](https://github.com/ionic-team/ionic-framework/compare/v7.8.2...v7.8.3) (2024-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **button:** activated outline button in toolbar no longer blends into background on MD dark mode ([#29216](https://github.com/ionic-team/ionic-framework/issues/29216)) ([ee5da7a](https://github.com/ionic-team/ionic-framework/commit/ee5da7a747c0a0b420c5e371a9fe9ec4938d179e))
|
||||
* **popover:** viewport can be scrolled if no content present ([#29215](https://github.com/ionic-team/ionic-framework/issues/29215)) ([f08759c](https://github.com/ionic-team/ionic-framework/commit/f08759c2b8256ff66f8d1901bd8e0be4617db262)), closes [#29211](https://github.com/ionic-team/ionic-framework/issues/29211)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-rc.0](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.4...v8.0.0-rc.0) (2024-03-27)
|
||||
|
||||
**Note:** Version bump only for package @ionic/core
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.4](https://github.com/ionic-team/ionic-framework/compare/v8.0.0-beta.3...v8.0.0-beta.4) (2024-03-27)
|
||||
|
||||
|
||||
### Code Refactoring
|
||||
|
||||
* **haptics:** remove cordova haptics support ([#29186](https://github.com/ionic-team/ionic-framework/issues/29186)) ([9efeb0a](https://github.com/ionic-team/ionic-framework/commit/9efeb0ad31aadee5f5ae542641d928ecf93fe82a))
|
||||
* **searchbar:** autocapitalize defaults to off ([#29107](https://github.com/ionic-team/ionic-framework/issues/29107)) ([6e477b7](https://github.com/ionic-team/ionic-framework/commit/6e477b743e41b2b37627c8208901704f599b762a))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* **button:** add circular shape as round ([#29161](https://github.com/ionic-team/ionic-framework/issues/29161)) ([44529f0](https://github.com/ionic-team/ionic-framework/commit/44529f0a62f1b1ce42750a20f19e829b2789febd))
|
||||
* **input:** add input-password-toggle component ([#29175](https://github.com/ionic-team/ionic-framework/issues/29175)) ([6c500fd](https://github.com/ionic-team/ionic-framework/commit/6c500fd6b2e2553c11fcddc9d86ac9a29f76e172))
|
||||
* remove css animations support for ionic animations ([#29123](https://github.com/ionic-team/ionic-framework/issues/29123)) ([892594d](https://github.com/ionic-team/ionic-framework/commit/892594de0665e8fc5c8a737d292812842ea03d64))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* **searchbar:** The `autocapitalize` property on Searchbar now defaults to `'off'`.
|
||||
* **haptics:** Support for the Cordova Haptics plugin has been removed. Components that integrate with haptics, such as `ion-picker` and `ion-toggle`, will continue to function but will no longer play haptics in Cordova environments. Developers should migrate to Capacitor to continue to have haptics in these components.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
## [7.8.2](https://github.com/ionic-team/ionic-framework/compare/v7.8.1...v7.8.2) (2024-03-27)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **searchbar:** autocapitalize is initialized correctly ([#29197](https://github.com/ionic-team/ionic-framework/issues/29197)) ([8ad66c0](https://github.com/ionic-team/ionic-framework/commit/8ad66c03d777edcab19c97cba696b171acc2d2e8)), closes [#29193](https://github.com/ionic-team/ionic-framework/issues/29193)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# [8.0.0-beta.3](https://github.com/ionic-team/ionic-framework/compare/v7.8.1...v8.0.0-beta.3) (2024-03-20)
|
||||
|
||||
|
||||
|
||||
@@ -549,7 +549,7 @@ ion-infinite-scroll-content,prop,loadingText,IonicSafeString | string | undefine
|
||||
|
||||
ion-input,scoped
|
||||
ion-input,prop,autocapitalize,string,'off',false,false
|
||||
ion-input,prop,autocomplete,"name" | "email" | "tel" | "url" | "on" | "off" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "photo",'off',false,false
|
||||
ion-input,prop,autocomplete,"name" | "on" | "off" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "email" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "url" | "photo",'off',false,false
|
||||
ion-input,prop,autocorrect,"off" | "on",'off',false,false
|
||||
ion-input,prop,autofocus,boolean,false,false,false
|
||||
ion-input,prop,clearInput,boolean,false,false,false
|
||||
@@ -1173,7 +1173,7 @@ ion-row,shadow
|
||||
ion-searchbar,scoped
|
||||
ion-searchbar,prop,animated,boolean,false,false,false
|
||||
ion-searchbar,prop,autocapitalize,string,'off',false,false
|
||||
ion-searchbar,prop,autocomplete,"name" | "email" | "tel" | "url" | "on" | "off" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "photo",'off',false,false
|
||||
ion-searchbar,prop,autocomplete,"name" | "on" | "off" | "honorific-prefix" | "given-name" | "additional-name" | "family-name" | "honorific-suffix" | "nickname" | "email" | "username" | "new-password" | "current-password" | "one-time-code" | "organization-title" | "organization" | "street-address" | "address-line1" | "address-line2" | "address-line3" | "address-level4" | "address-level3" | "address-level2" | "address-level1" | "country" | "country-name" | "postal-code" | "cc-name" | "cc-given-name" | "cc-additional-name" | "cc-family-name" | "cc-number" | "cc-exp" | "cc-exp-month" | "cc-exp-year" | "cc-csc" | "cc-type" | "transaction-currency" | "transaction-amount" | "language" | "bday" | "bday-day" | "bday-month" | "bday-year" | "sex" | "tel" | "tel-country-code" | "tel-national" | "tel-area-code" | "tel-local" | "tel-extension" | "impp" | "url" | "photo",'off',false,false
|
||||
ion-searchbar,prop,autocorrect,"off" | "on",'off',false,false
|
||||
ion-searchbar,prop,cancelButtonIcon,string,config.get('backButtonIcon', arrowBackSharp) as string,false,false
|
||||
ion-searchbar,prop,cancelButtonText,string,'Cancel',false,false
|
||||
|
||||
40
core/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "8.0.0-beta.3",
|
||||
"version": "8.0.0-rc.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@ionic/core",
|
||||
"version": "8.0.0-beta.3",
|
||||
"version": "8.0.0-rc.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@stencil/core": "^4.12.2",
|
||||
@@ -633,9 +633,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@capacitor/core": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.7.3.tgz",
|
||||
"integrity": "sha512-xEuQmP+h0tugl2N+qRcdrUavZydvTnnmtvqu/OtCBb/bKZo2PDRFft7MxuQRE2GxXs6kLy3cvwzhDAHB3a+9mw==",
|
||||
"version": "5.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.7.4.tgz",
|
||||
"integrity": "sha512-iZBgvx3o4amzKv5ttA+QHB6i7cxK+/mYpCQd1tnSdipg6ZkvfBhg1HkzhEqHk+I7MNur+QwgYDZho9+ycHRwOw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"tslib": "^2.1.0"
|
||||
@@ -1759,9 +1759,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/core": {
|
||||
"version": "4.12.6",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.12.6.tgz",
|
||||
"integrity": "sha512-15JO2TdaxGVKNdLZb/2TtDa+juj3XGD/V0y/disgdzYYSnajgSh06nwODfdHz9eTUh1Hisz+KIo857I1rCZrfg==",
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.13.0.tgz",
|
||||
"integrity": "sha512-gg+gtBWekQ08mDja8GVAUHNu+rrFhQaKZDvfhnS3l/5JbYiJddTimuDPPhuc0sR0JZL1iRdJTJSa+JbvmnQ1cQ==",
|
||||
"bin": {
|
||||
"stencil": "bin/stencil"
|
||||
},
|
||||
@@ -1793,9 +1793,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@stencil/vue-output-target": {
|
||||
"version": "0.8.7",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.8.7.tgz",
|
||||
"integrity": "sha512-hgOzbKKgLdCFrhLpmaw/qQrPSXl6hZ09K+j3p/iWh3esq6sxnwuW1PJKLniwkT4Z/JlDIk6stGPGQYi+WE5I2Q==",
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.8.8.tgz",
|
||||
"integrity": "sha512-xrpz92lmTuLgwY9CLgl2Q14+zBXfBuXiRS6uXFPfeaFo0pe+do8cZitOOQ8i8tcoCa/tAqgD9B9CD+yQehSIGg==",
|
||||
"dev": true,
|
||||
"peerDependencies": {
|
||||
"@stencil/core": ">=2.0.0 || >=3 || >= 4.0.0-beta.0 || >= 4.0.0"
|
||||
@@ -10416,9 +10416,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@capacitor/core": {
|
||||
"version": "5.7.3",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.7.3.tgz",
|
||||
"integrity": "sha512-xEuQmP+h0tugl2N+qRcdrUavZydvTnnmtvqu/OtCBb/bKZo2PDRFft7MxuQRE2GxXs6kLy3cvwzhDAHB3a+9mw==",
|
||||
"version": "5.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-5.7.4.tgz",
|
||||
"integrity": "sha512-iZBgvx3o4amzKv5ttA+QHB6i7cxK+/mYpCQd1tnSdipg6ZkvfBhg1HkzhEqHk+I7MNur+QwgYDZho9+ycHRwOw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"tslib": "^2.1.0"
|
||||
@@ -11229,9 +11229,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@stencil/core": {
|
||||
"version": "4.12.6",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.12.6.tgz",
|
||||
"integrity": "sha512-15JO2TdaxGVKNdLZb/2TtDa+juj3XGD/V0y/disgdzYYSnajgSh06nwODfdHz9eTUh1Hisz+KIo857I1rCZrfg=="
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.13.0.tgz",
|
||||
"integrity": "sha512-gg+gtBWekQ08mDja8GVAUHNu+rrFhQaKZDvfhnS3l/5JbYiJddTimuDPPhuc0sR0JZL1iRdJTJSa+JbvmnQ1cQ=="
|
||||
},
|
||||
"@stencil/react-output-target": {
|
||||
"version": "0.5.3",
|
||||
@@ -11248,9 +11248,9 @@
|
||||
"requires": {}
|
||||
},
|
||||
"@stencil/vue-output-target": {
|
||||
"version": "0.8.7",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.8.7.tgz",
|
||||
"integrity": "sha512-hgOzbKKgLdCFrhLpmaw/qQrPSXl6hZ09K+j3p/iWh3esq6sxnwuW1PJKLniwkT4Z/JlDIk6stGPGQYi+WE5I2Q==",
|
||||
"version": "0.8.8",
|
||||
"resolved": "https://registry.npmjs.org/@stencil/vue-output-target/-/vue-output-target-0.8.8.tgz",
|
||||
"integrity": "sha512-xrpz92lmTuLgwY9CLgl2Q14+zBXfBuXiRS6uXFPfeaFo0pe+do8cZitOOQ8i8tcoCa/tAqgD9B9CD+yQehSIGg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@ionic/core",
|
||||
"version": "8.0.0-beta.3",
|
||||
"version": "8.0.0-rc.0",
|
||||
"description": "Base components for Ionic",
|
||||
"keywords": [
|
||||
"ionic",
|
||||
|
||||
@@ -149,7 +149,20 @@
|
||||
}
|
||||
|
||||
::slotted(ion-icon[slot="icon-only"]) {
|
||||
font-size: 1.125em;
|
||||
/**
|
||||
* The values were provided through a native iOS app.
|
||||
* min font size: 15px, default font size: 18px, max font size: 43px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 16px
|
||||
* (derived from rem), then the base size can use the default font
|
||||
* size of the icon.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.84, 18px, 2.39, 1em);
|
||||
}
|
||||
|
||||
:host(.button-small.button-has-icon-only) {
|
||||
@@ -157,11 +170,23 @@
|
||||
min-width: clamp(23px, 2.16em, 54px);
|
||||
// TODO(FW-6053): replace em value with the min-height variable.
|
||||
min-height: clamp(23px, 2.16em, 54px);
|
||||
|
||||
}
|
||||
|
||||
:host(.button-small) ::slotted(ion-icon[slot="icon-only"]) {
|
||||
font-size: 1.4em;
|
||||
/**
|
||||
* The values were provided through a native iOS app.
|
||||
* min font size: 12px, default font size: 17px, max font size: 40px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 13px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 17px, then the base size would need to be increased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.58, 20.93px, 1.92, 1em);
|
||||
}
|
||||
|
||||
:host(.button-large.button-has-icon-only) {
|
||||
@@ -172,7 +197,20 @@
|
||||
}
|
||||
|
||||
:host(.button-large) ::slotted(ion-icon[slot="icon-only"]) {
|
||||
font-size: 1em;
|
||||
/**
|
||||
* The values were provided through a native iOS app.
|
||||
* min font size: 15px, default font size: 18px, max font size: 43px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 20px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 18px, then the base size would need to be decreased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(1.05, 14.4px, 2.99, 1em);
|
||||
}
|
||||
|
||||
// iOS Button Focused
|
||||
@@ -247,3 +285,12 @@
|
||||
:host(.button-solid.ion-color.ion-activated) .button-native::after {
|
||||
background: #{current-color(shade)};
|
||||
}
|
||||
|
||||
|
||||
// Activated Button in Toolbar
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.button-outline.ion-activated.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
|
||||
background: var(--ion-toolbar-color, var(--color));
|
||||
color: #{var(--ion-toolbar-background, var(--background), ion-color(primary, contrast))};
|
||||
}
|
||||
|
||||
@@ -142,7 +142,21 @@
|
||||
}
|
||||
|
||||
::slotted(ion-icon[slot="icon-only"]) {
|
||||
font-size: 1.6em;
|
||||
/**
|
||||
* The values were provided through MD design,
|
||||
* large and small are based on the iOS sizes.
|
||||
* min font size: 15px, default font size: 22.4px, max font size: 43px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 14px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 22.4px, then the base size would need to be increased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.59, 25.6px, 1.68, 1em);
|
||||
}
|
||||
|
||||
:host(.button-small.button-has-icon-only) {
|
||||
@@ -153,7 +167,21 @@
|
||||
}
|
||||
|
||||
:host(.button-small) ::slotted(ion-icon[slot="icon-only"]) {
|
||||
font-size: 1.23em;
|
||||
/**
|
||||
* The values were provided through MD design,
|
||||
* large and small are based on the iOS sizes.
|
||||
* min font size: 12px, default font size: 16px, max font size: 40px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 13px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 16px, then the base size would need to be increased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.66, 19.7px, 2.05, 1em);
|
||||
}
|
||||
|
||||
:host(.button-large.button-has-icon-only) {
|
||||
@@ -164,7 +192,21 @@
|
||||
}
|
||||
|
||||
:host(.button-large) ::slotted(ion-icon[slot="icon-only"]) {
|
||||
font-size: 1.4em;
|
||||
/**
|
||||
* The values were provided through MD design,
|
||||
* large and small are based on the iOS sizes.
|
||||
* min font size: 15px, default font size: 28px, max font size: 43px
|
||||
*
|
||||
* Since the `ion-button` uses `rem` for the font size, we can't
|
||||
* just pass the desired icon font size in `em` to the `
|
||||
* dynamic-font-clamp`. Instead, we need to adjust the base size
|
||||
* to account for the ion-button` font size.
|
||||
*
|
||||
* For example, if the default font size of `ion-button` is 20px
|
||||
* (derived from rem) and the default font size of the icon is
|
||||
* 28px, then the base size would need to be increased.
|
||||
*/
|
||||
font-size: dynamic-font-clamp(0.67, 22.4px, 1.92, 1em);
|
||||
}
|
||||
|
||||
// Material Design Button: Hover
|
||||
@@ -196,3 +238,12 @@
|
||||
background: #{current-color(base)};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Activated Button in Toolbar
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.button-outline.ion-activated.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
|
||||
background: var(--ion-toolbar-background, var(--color));
|
||||
color: #{var(--ion-toolbar-color, var(--background), ion-color(primary, contrast))};
|
||||
}
|
||||
|
||||
@@ -325,11 +325,3 @@ ion-ripple-effect {
|
||||
background: #{var(--ion-toolbar-color, var(--background))};
|
||||
color: #{var(--ion-toolbar-background, var(--color))};
|
||||
}
|
||||
|
||||
// Activated Button in Toolbar
|
||||
// --------------------------------------------------
|
||||
|
||||
:host(.button-outline.ion-activated.in-toolbar:not(.ion-color):not(.in-toolbar-color)) .button-native {
|
||||
background: var(--ion-toolbar-color, var(--color));
|
||||
color: #{var(--ion-toolbar-background, var(--background), ion-color(primary, contrast))};
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 45 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.6 KiB |
|
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 9.3 KiB After Width: | Height: | Size: 9.0 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 8.5 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 73 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 69 KiB |
|
Before Width: | Height: | Size: 81 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 48 KiB After Width: | Height: | Size: 48 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
@@ -101,8 +101,6 @@
|
||||
display: flex;
|
||||
|
||||
flex-direction: column;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// Nested Popovers
|
||||
|
||||
@@ -48,6 +48,98 @@ configs({ directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
* Translucent popovers are only available on iOS
|
||||
*/
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('popover: scrolling'), async () => {
|
||||
test.beforeEach(({ skip }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/ionic-team/ionic-framework/issues/29211',
|
||||
});
|
||||
// We are testing if Ionic sets overflow is set correctly on elements,
|
||||
// so we do not need to test across browsers
|
||||
skip.browser('webkit', 'Behavior does not vary across browsers');
|
||||
skip.browser('firefox', 'Behavior does not vary across browsers');
|
||||
});
|
||||
test('should scroll to bottom without IonContent', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
ion-popover {
|
||||
--height: 150px;
|
||||
}
|
||||
</style>
|
||||
<ion-popover>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
</ion-popover>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const popover = page.locator('ion-popover');
|
||||
const viewport = popover.locator('.popover-viewport');
|
||||
const p = popover.locator('p');
|
||||
const lastP = await p.last();
|
||||
|
||||
await popover.evaluate((el: HTMLIonPopoverElement) => el.present());
|
||||
|
||||
await expect(lastP).not.toBeInViewport();
|
||||
|
||||
// hover over viewport and scroll to bottom
|
||||
await viewport.hover();
|
||||
await page.mouse.wheel(0, 500);
|
||||
|
||||
await expect(lastP).toBeInViewport();
|
||||
});
|
||||
test('should scroll to bottom with IonContent', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<style>
|
||||
ion-popover {
|
||||
--height: 150px;
|
||||
}
|
||||
</style>
|
||||
<ion-popover>
|
||||
<ion-content>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
<p>Text</p>
|
||||
</ion-content>
|
||||
</ion-popover>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const popover = page.locator('ion-popover');
|
||||
const content = popover.locator('ion-content');
|
||||
const p = popover.locator('p');
|
||||
const lastP = await p.last();
|
||||
|
||||
await popover.evaluate((el: HTMLIonPopoverElement) => el.present());
|
||||
|
||||
await expect(lastP).not.toBeInViewport();
|
||||
|
||||
// hover over viewport and scroll to bottom
|
||||
await content.hover();
|
||||
await page.mouse.wheel(0, 500);
|
||||
|
||||
await expect(lastP).toBeInViewport();
|
||||
});
|
||||
});
|
||||
test.describe(title('popover: translucent variants'), async () => {
|
||||
let popoverFixture!: PopoverFixture;
|
||||
test.beforeEach(async ({ page }) => {
|
||||
|
||||
@@ -606,7 +606,7 @@ export class Searchbar implements ComponentInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { cancelButtonText } = this;
|
||||
const { cancelButtonText, autocapitalize } = this;
|
||||
const animated = this.animated && config.getBoolean('animated', true);
|
||||
const mode = getIonMode(this);
|
||||
const clearIcon = this.clearIcon || (mode === 'ios' ? closeCircle : closeSharp);
|
||||
@@ -668,7 +668,7 @@ export class Searchbar implements ComponentInterface {
|
||||
placeholder={this.placeholder}
|
||||
type={this.type}
|
||||
value={this.getValue()}
|
||||
autoCapitalize={this.autocapitalize}
|
||||
autoCapitalize={autocapitalize === 'default' ? undefined : autocapitalize}
|
||||
autoComplete={this.autocomplete}
|
||||
autoCorrect={this.autocorrect}
|
||||
spellcheck={this.spellcheck}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import AxeBuilder from '@axe-core/playwright';
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
@@ -74,3 +75,52 @@ configs({ directions: ['ltr'], modes: ['ios'] }).forEach(({ title, screenshot, c
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) => {
|
||||
test.describe(title('title: level 1 heading'), () => {
|
||||
test('should not have accessibility violations', async ({ page }) => {
|
||||
/**
|
||||
* Level 1 headings must be inside of a landmark (ion-header)
|
||||
*/
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>My Title</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const results = await new AxeBuilder({ page }).analyze();
|
||||
|
||||
expect(results.violations).toEqual([]);
|
||||
});
|
||||
test('should not have accessibility violations with multiple h1 elements on a hidden page', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<div class="ion-page ion-page-hidden">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>My Title</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
</div>
|
||||
<div class="ion-page">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>My Title</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
</div>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const results = await new AxeBuilder({ page }).analyze();
|
||||
|
||||
expect(results.violations).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
147
core/src/components/title/test/title.spec.ts
Normal file
@@ -0,0 +1,147 @@
|
||||
import { newSpecPage } from '@stencil/core/testing';
|
||||
|
||||
import { Header } from '../../header/header';
|
||||
import { Toolbar } from '../../toolbar/toolbar';
|
||||
import { ToolbarTitle } from '../title';
|
||||
|
||||
describe('title: a11y', () => {
|
||||
it('should add heading level 1 attributes when inside of a landmark', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Header, Toolbar, ToolbarTitle],
|
||||
html: `
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Title</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
});
|
||||
|
||||
const title = page.body.querySelector('ion-title')!;
|
||||
|
||||
expect(title.getAttribute('role')).toBe('heading');
|
||||
expect(title.getAttribute('aria-level')).toBe('1');
|
||||
});
|
||||
it('should not override a custom role', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Header, Toolbar, ToolbarTitle],
|
||||
html: `
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title role="article">Title 1</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
});
|
||||
const title = page.body.querySelector('ion-title')!;
|
||||
|
||||
expect(title.getAttribute('role')).toBe('article');
|
||||
expect(title.hasAttribute('aria-level')).toBe(false);
|
||||
});
|
||||
it('should not add heading level 1 attributes when outside of a landmark', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Header, Toolbar, ToolbarTitle],
|
||||
html: `
|
||||
<ion-title>Title</ion-title>
|
||||
`,
|
||||
});
|
||||
|
||||
const title = page.body.querySelector('ion-title')!;
|
||||
|
||||
expect(title.hasAttribute('role')).toBe(false);
|
||||
expect(title.hasAttribute('aria-level')).toBe(false);
|
||||
});
|
||||
it('at most one ion-title should have level 1 attributes', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Header, Toolbar, ToolbarTitle],
|
||||
html: `
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Title 1</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Title 2</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
});
|
||||
|
||||
const titles = page.body.querySelectorAll('ion-title');
|
||||
|
||||
expect(titles[0].getAttribute('role')).toBe('heading');
|
||||
expect(titles[0].getAttribute('aria-level')).toBe('1');
|
||||
|
||||
expect(titles[1].hasAttribute('role')).toBe(false);
|
||||
expect(titles[1].hasAttribute('aria-level')).toBe(false);
|
||||
});
|
||||
it('should not add level 1 attributes if other level 1 headings exist', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Header, Toolbar, ToolbarTitle],
|
||||
html: `
|
||||
<h1>Title</h1>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Title 1</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
});
|
||||
|
||||
const title = page.body.querySelector('ion-title')!;
|
||||
|
||||
expect(title.hasAttribute('role')).toBe(false);
|
||||
expect(title.hasAttribute('aria-level')).toBe(false);
|
||||
});
|
||||
it('should not add level 1 attributes if other level 1 attributes exist', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Header, Toolbar, ToolbarTitle],
|
||||
html: `
|
||||
<div role="heading" aria-level="1">Title</div>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Title 1</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
});
|
||||
|
||||
const title = page.body.querySelector('ion-title')!;
|
||||
|
||||
expect(title.hasAttribute('role')).toBe(false);
|
||||
expect(title.hasAttribute('aria-level')).toBe(false);
|
||||
});
|
||||
|
||||
it('should have level 1 attributes even if there is a level 1 heading on another page', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Header, Toolbar, ToolbarTitle],
|
||||
html: `
|
||||
<div class="ion-page">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Title 1</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
</div>
|
||||
|
||||
<div class="ion-page">
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Title 2</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
</div>
|
||||
`,
|
||||
});
|
||||
|
||||
const pages = page.body.querySelectorAll('.ion-page');
|
||||
|
||||
pages.forEach((page) => {
|
||||
const title = page.querySelector('ion-title')!;
|
||||
|
||||
expect(title.getAttribute('role')).toBe('heading');
|
||||
expect(title.getAttribute('aria-level')).toBe('1');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
import type { ComponentInterface, EventEmitter } from '@stencil/core';
|
||||
import { Component, Element, Event, Host, Prop, Watch, h } from '@stencil/core';
|
||||
import { doc } from '@utils/browser';
|
||||
import { createColorClasses } from '@utils/theme';
|
||||
|
||||
import { getIonMode } from '../../global/ionic-global';
|
||||
@@ -56,11 +57,37 @@ export class ToolbarTitle implements ComponentInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { el } = this;
|
||||
const mode = getIonMode(this);
|
||||
const size = this.getSize();
|
||||
|
||||
/**
|
||||
* If there is already a level one heading
|
||||
* within the context of the page then
|
||||
* do not add another one.
|
||||
*/
|
||||
const root = el.closest('.ion-page') ?? doc?.body;
|
||||
const hasHeading = root?.querySelector('h1, [role="heading"][aria-level="1"]');
|
||||
const hasRole = el.hasAttribute('role');
|
||||
|
||||
/**
|
||||
* The first `ion-title` on the page is considered
|
||||
* the heading. This can be customized by setting
|
||||
* role="heading" aria-level="1" on another element
|
||||
* or by using h1.
|
||||
*
|
||||
* Level 1 headings must be contained inside of a landmark,
|
||||
* so we check for ion-header which is typically the landmark.
|
||||
*/
|
||||
const isHeading =
|
||||
hasRole === false &&
|
||||
hasHeading === null &&
|
||||
root?.querySelector('ion-title') === el &&
|
||||
el?.closest('ion-header[role]') !== null;
|
||||
return (
|
||||
<Host
|
||||
role={isHeading ? 'heading' : null}
|
||||
aria-level={isHeading ? '1' : null}
|
||||
class={createColorClasses(this.color, {
|
||||
[mode]: true,
|
||||
[`title-${size}`]: true,
|
||||
|
||||
@@ -1,14 +1,160 @@
|
||||
import { expect } from '@playwright/test';
|
||||
import { configs, test } from '@utils/test/playwright';
|
||||
|
||||
configs().forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('toolbar: basic'), () => {
|
||||
test('should not have visual regressions', async ({ page }) => {
|
||||
await page.goto(`/src/components/toolbar/test/basic`, config);
|
||||
configs({ palettes: ['light', 'dark'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('toolbar: basic (LTR only)'), () => {
|
||||
test('should not have visual regressions with text only', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Toolbar</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
// capture both header toolbars at once, but don't include all the white space in the ion-content
|
||||
const header = page.locator('ion-header');
|
||||
await expect(header).toHaveScreenshot(screenshot(`toolbar-basic`));
|
||||
await expect(header).toHaveScreenshot(screenshot(`toolbar-basic-text-only`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
configs({ palettes: ['light', 'dark'] }).forEach(({ title, screenshot, config }) => {
|
||||
test.describe(title('toolbar: basic'), () => {
|
||||
test('should truncate long title with ellipsis', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>This is the title that never ends. It just goes on and on my friend.</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const header = page.locator('ion-header');
|
||||
await expect(header).toHaveScreenshot(screenshot(`toolbar-basic-long-text`));
|
||||
});
|
||||
|
||||
test('should not have visual regressions with icon-only buttons', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="secondary">
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="person-circle"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-button>
|
||||
<ion-icon slot="icon-only" name="search"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button color="secondary">
|
||||
<ion-icon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Toolbar</ion-title>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="secondary">
|
||||
<ion-button class="ion-activated">
|
||||
<ion-icon slot="icon-only" name="person-circle"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-button class="ion-activated">
|
||||
<ion-icon slot="icon-only" name="search"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button color="secondary" class="ion-activated">
|
||||
<ion-icon slot="icon-only" ios="ellipsis-horizontal" md="ellipsis-vertical"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Activated Buttons</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const header = page.locator('ion-header');
|
||||
await expect(header).toHaveScreenshot(screenshot(`toolbar-basic-icon-buttons`));
|
||||
});
|
||||
|
||||
test('should not have visual regressions with buttons with icons and text', async ({ page }) => {
|
||||
await page.setContent(
|
||||
`
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="secondary">
|
||||
<ion-button fill="solid">
|
||||
<ion-icon slot="start" name="person-circle"></ion-icon>
|
||||
Solid
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Solid</ion-title>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button fill="solid" color="secondary">
|
||||
Help
|
||||
<ion-icon slot="end" name="help-circle"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="secondary">
|
||||
<ion-button fill="solid" class="ion-activated">
|
||||
<ion-icon slot="start" name="person-circle"></ion-icon>
|
||||
Solid
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Solid Activated</ion-title>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button fill="solid" color="secondary" class="ion-activated">
|
||||
Help
|
||||
<ion-icon slot="end" name="help-circle"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="secondary">
|
||||
<ion-button fill="outline">
|
||||
<ion-icon slot="start" name="star"></ion-icon>
|
||||
Star
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Outline</ion-title>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button color="secondary" fill="outline">
|
||||
Info
|
||||
<ion-icon slot="end" name="information-circle"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="secondary">
|
||||
<ion-button fill="outline" class="ion-activated">
|
||||
<ion-icon slot="start" name="star"></ion-icon>
|
||||
Star
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Outline Activated</ion-title>
|
||||
<ion-buttons slot="primary">
|
||||
<ion-button color="secondary" fill="outline" class="ion-activated">
|
||||
Info
|
||||
<ion-icon slot="end" name="information-circle"></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
`,
|
||||
config
|
||||
);
|
||||
|
||||
const header = page.locator('ion-header');
|
||||
await expect(header).toHaveScreenshot(screenshot(`toolbar-basic-text-icon-buttons`));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.2 KiB |