Compare commits

..

3 Commits

Author SHA1 Message Date
amandaesmith3
fd6df84e2a more comments 2024-02-15 12:37:35 -06:00
amandaesmith3
d422302d98 add in progress fix with comments 2024-02-15 12:24:23 -06:00
amandaesmith3
c483ad6fb2 add safe area option to existing test 2024-02-12 09:12:39 -06:00
36 changed files with 295 additions and 338 deletions

20
.github/dependabot.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
version: 2
updates:
- package-ecosystem: "npm"
directory: "/core"
schedule:
interval: "daily"
versioning-strategy: increase
allow:
- dependency-name: "@playwright/test"
- dependency-name: "@axe-core/playwright"
- dependency-name: "@stencil/angular-output-target"
- dependency-name: "@stencil/core"
- dependency-name: "@stencil/react-output-target"
- dependency-name: "@stencil/sass"
- dependency-name: "@stencil/vue-output-target"
- dependency-name: "ionicons"
- dependency-name: "@capacitor/core"
- dependency-name: "@capacitor/keyboard"
- dependency-name: "@capacitor/haptics"
- dependency-name: "@capacitor/status-bar"

View File

@@ -3,19 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
### Bug Fixes
* **overlays:** do not return focus if application has already moved focus manually ([#28850](https://github.com/ionic-team/ionic-framework/issues/28850)) ([a016670](https://github.com/ionic-team/ionic-framework/commit/a016670a8a46e101d23235b17bc8a2081fb992eb)), closes [#28849](https://github.com/ionic-team/ionic-framework/issues/28849)
* **overlays:** ensure that only topmost overlay is announced by screen readers ([#28997](https://github.com/ionic-team/ionic-framework/issues/28997)) ([ba4ba61](https://github.com/ionic-team/ionic-framework/commit/ba4ba6161c1a6c67f7804b07f49c64ac9ad2b14c)), closes [#23472](https://github.com/ionic-team/ionic-framework/issues/23472)
* **popover:** render arrow above backdrop ([#28986](https://github.com/ionic-team/ionic-framework/issues/28986)) ([0a8964d](https://github.com/ionic-team/ionic-framework/commit/0a8964d30c76218fe62f7f4aed4f81df7bb80cd0)), closes [#28985](https://github.com/ionic-team/ionic-framework/issues/28985)
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)

View File

@@ -3,19 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
### Bug Fixes
* **overlays:** do not return focus if application has already moved focus manually ([#28850](https://github.com/ionic-team/ionic-framework/issues/28850)) ([a016670](https://github.com/ionic-team/ionic-framework/commit/a016670a8a46e101d23235b17bc8a2081fb992eb)), closes [#28849](https://github.com/ionic-team/ionic-framework/issues/28849)
* **overlays:** ensure that only topmost overlay is announced by screen readers ([#28997](https://github.com/ionic-team/ionic-framework/issues/28997)) ([ba4ba61](https://github.com/ionic-team/ionic-framework/commit/ba4ba6161c1a6c67f7804b07f49c64ac9ad2b14c)), closes [#23472](https://github.com/ionic-team/ionic-framework/issues/23472)
* **popover:** render arrow above backdrop ([#28986](https://github.com/ionic-team/ionic-framework/issues/28986)) ([0a8964d](https://github.com/ionic-team/ionic-framework/commit/0a8964d30c76218fe62f7f4aed4f81df7bb80cd0)), closes [#28985](https://github.com/ionic-team/ionic-framework/issues/28985)
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)

48
core/package-lock.json generated
View File

@@ -1,20 +1,20 @@
{
"name": "@ionic/core",
"version": "7.7.2",
"version": "7.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/core",
"version": "7.7.2",
"version": "7.7.1",
"license": "MIT",
"dependencies": {
"@stencil/core": "^4.12.2",
"@stencil/core": "^4.12.1",
"ionicons": "^7.2.2",
"tslib": "^2.1.0"
},
"devDependencies": {
"@axe-core/playwright": "^4.8.5",
"@axe-core/playwright": "^4.8.4",
"@capacitor/core": "^5.7.0",
"@capacitor/haptics": "^5.0.7",
"@capacitor/keyboard": "^5.0.8",
@@ -56,12 +56,12 @@
"dev": true
},
"node_modules/@axe-core/playwright": {
"version": "4.8.5",
"resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.8.5.tgz",
"integrity": "sha512-GFdXXAEn9uk0Vyzgl2eEP+VwvgGzas0YSnacoJ/0U237G83zWZ1PhbP/RDymm0cqevoA+xRjMo+ONzh9Q711nw==",
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.8.4.tgz",
"integrity": "sha512-xpwd+T0BODt19hnXW0eX9xf+H/Ns1rdWwZNmuCV9UoTqjZ9mGm1F80pvh/A1r317ooltq8nwqcoVO9jbHWKSdA==",
"dev": true,
"dependencies": {
"axe-core": "~4.8.4"
"axe-core": "~4.8.3"
},
"peerDependencies": {
"playwright-core": ">= 1.0.0"
@@ -1825,9 +1825,9 @@
}
},
"node_modules/@stencil/core": {
"version": "4.12.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.12.2.tgz",
"integrity": "sha512-WEMpoqwMV4hY/ab2z9NxRhSeZwuKEugjyn6Vd+qA9xqZh6VNUL27QbP8vCa7IeqD4Zql4JBtKu3lVuBHutWE6w==",
"version": "4.12.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.12.1.tgz",
"integrity": "sha512-l7UUCEV+4Yr1i6BL2DGSQPAzM3x/V4Fx9n9Z0/gdAgX11I25xY0MnH5jbQ69ug6ms/8KUV6SouS1R7MjjM/JnQ==",
"bin": {
"stencil": "bin/stencil"
},
@@ -2799,9 +2799,9 @@
}
},
"node_modules/axe-core": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.4.tgz",
"integrity": "sha512-CZLSKisu/bhJ2awW4kJndluz2HLZYIHh5Uy1+ZwDRkJi69811xgIXXfdU9HSLX0Th+ILrHj8qfL/5wzamsFtQg==",
"version": "4.8.3",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.3.tgz",
"integrity": "sha512-d5ZQHPSPkF9Tw+yfyDcRoUOc4g/8UloJJe5J8m4L5+c7AtDdjDLRxew/knnI4CxvtdxEUVgWz4x3OIQUIFiMfw==",
"dev": true,
"engines": {
"node": ">=4"
@@ -10899,12 +10899,12 @@
},
"dependencies": {
"@axe-core/playwright": {
"version": "4.8.5",
"resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.8.5.tgz",
"integrity": "sha512-GFdXXAEn9uk0Vyzgl2eEP+VwvgGzas0YSnacoJ/0U237G83zWZ1PhbP/RDymm0cqevoA+xRjMo+ONzh9Q711nw==",
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/@axe-core/playwright/-/playwright-4.8.4.tgz",
"integrity": "sha512-xpwd+T0BODt19hnXW0eX9xf+H/Ns1rdWwZNmuCV9UoTqjZ9mGm1F80pvh/A1r317ooltq8nwqcoVO9jbHWKSdA==",
"dev": true,
"requires": {
"axe-core": "~4.8.4"
"axe-core": "~4.8.3"
}
},
"@babel/code-frame": {
@@ -12184,9 +12184,9 @@
"requires": {}
},
"@stencil/core": {
"version": "4.12.2",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.12.2.tgz",
"integrity": "sha512-WEMpoqwMV4hY/ab2z9NxRhSeZwuKEugjyn6Vd+qA9xqZh6VNUL27QbP8vCa7IeqD4Zql4JBtKu3lVuBHutWE6w=="
"version": "4.12.1",
"resolved": "https://registry.npmjs.org/@stencil/core/-/core-4.12.1.tgz",
"integrity": "sha512-l7UUCEV+4Yr1i6BL2DGSQPAzM3x/V4Fx9n9Z0/gdAgX11I25xY0MnH5jbQ69ug6ms/8KUV6SouS1R7MjjM/JnQ=="
},
"@stencil/react-output-target": {
"version": "0.5.3",
@@ -12863,9 +12863,9 @@
}
},
"axe-core": {
"version": "4.8.4",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.4.tgz",
"integrity": "sha512-CZLSKisu/bhJ2awW4kJndluz2HLZYIHh5Uy1+ZwDRkJi69811xgIXXfdU9HSLX0Th+ILrHj8qfL/5wzamsFtQg==",
"version": "4.8.3",
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.8.3.tgz",
"integrity": "sha512-d5ZQHPSPkF9Tw+yfyDcRoUOc4g/8UloJJe5J8m4L5+c7AtDdjDLRxew/knnI4CxvtdxEUVgWz4x3OIQUIFiMfw==",
"dev": true
},
"b4a": {

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/core",
"version": "7.7.2",
"version": "7.7.1",
"description": "Base components for Ionic",
"keywords": [
"ionic",
@@ -31,12 +31,12 @@
"loader/"
],
"dependencies": {
"@stencil/core": "^4.12.2",
"@stencil/core": "^4.12.1",
"ionicons": "^7.2.2",
"tslib": "^2.1.0"
},
"devDependencies": {
"@axe-core/playwright": "^4.8.5",
"@axe-core/playwright": "^4.8.4",
"@capacitor/core": "^5.7.0",
"@capacitor/haptics": "^5.0.7",
"@capacitor/keyboard": "^5.0.8",

View File

@@ -1,5 +1,5 @@
import type { ComponentInterface } from '@stencil/core';
import { Component, Element, Host, Listen, Prop, State, Watch, forceUpdate, h } from '@stencil/core';
import { Build, Component, Element, Host, Listen, Prop, State, Watch, forceUpdate, h } from '@stencil/core';
import type { AnchorInterface, ButtonInterface } from '@utils/element-interface';
import type { Attributes } from '@utils/helpers';
import { inheritAttributes, raf } from '@utils/helpers';
@@ -358,6 +358,15 @@ export class Item implements ComponentInterface, AnchorInterface, ButtonInterfac
}
private getFirstInteractive() {
if (Build.isTesting) {
/**
* Pseudo selectors can't be tested in unit tests.
* It will cause an error when running the tests.
*
* TODO: FW-5205 - Remove the build conditional when this is fixed in Stencil
*/
return undefined;
}
const controls = this.el.querySelectorAll<HTMLElement>(
'ion-toggle:not([disabled]), ion-checkbox:not([disabled]), ion-radio:not([disabled]), ion-select:not([disabled])'
);

View File

@@ -53,7 +53,15 @@ export const iosEnterAnimation = (baseEl: HTMLElement, opts?: any): Animation =>
);
const padding = size === 'cover' ? 0 : POPOVER_IOS_BODY_PADDING;
const margin = size === 'cover' ? 0 : 25;
/**
* NOTE: The original experience guessed at a safe area margin of 25
* for non-cover popovers. This was changed to always be 0 here for
* debugging purposes, so we can be sure any safe area adjustment we
* see is only from what we implement for this fix.
*/
// const margin = size === 'cover' ? 0 : 25;
const margin = 0;
const {
originX,
@@ -61,8 +69,8 @@ export const iosEnterAnimation = (baseEl: HTMLElement, opts?: any): Animation =>
top,
left,
bottom,
checkSafeAreaLeft,
checkSafeAreaRight,
// checkSafeAreaLeft,
// checkSafeAreaRight,
arrowTop,
arrowLeft,
addPopoverBottomClass,
@@ -122,29 +130,88 @@ export const iosEnterAnimation = (baseEl: HTMLElement, opts?: any): Animation =>
contentEl.style.setProperty('bottom', `${bottom}px`);
}
const safeAreaLeft = ' + var(--ion-safe-area-left, 0)';
const safeAreaRight = ' - var(--ion-safe-area-right, 0)';
let leftValue = `${left}px`;
if (checkSafeAreaLeft) {
leftValue = `${left}px${safeAreaLeft}`;
}
if (checkSafeAreaRight) {
leftValue = `${left}px${safeAreaRight}`;
}
contentEl.style.setProperty('top', `calc(${top}px + var(--offset-y, 0))`);
contentEl.style.setProperty('left', `calc(${leftValue} + var(--offset-x, 0))`);
/**
* NOTE: We account for safe area through pure CSS by clamping the popover position
* between the safe area bounds. This works except for the arrow position in certain
* circumstances. (See comments on arrow position below for what.) Breakdown of
* values used for the top position:
*
* - Min: calc(var(--ion-safe-area-top, 0px) + var(--offset-y, 0px) + ${arrowHeight}px)
* Top edge of safe area, plus custom y offset, plus a little gap to make room for the arrow.
* Note that arrowHeight resolves to 0px if the arrow is not displayed.
*
* - Preferred: calc(${top}px + var(--offset-y, 0px))
* Normal calculated value of the popover, including any custom offset. The value of top
* already accounts for all conditions aside from safe area, since it's what we were using
* before the fix.
*
* - Max: calc(100% - ${contentHeight + arrowHeight}px - var(--ion-safe-area-bottom) + var(--offset-y, 0px))
* Bottom edge of screen, minus the total height of the popover (content + arrow), minus
* the bottom safe area margin, including custom y offset.
*
* The left position is the same, but using x-axis values instead. We do this through
* pure CSS to avoid needing to call window.getComputedStyle() to figure out the computed
* safe area, which is very expensive and would introduce performance issues.
*
* The clamp() function is available in all browsers we support as of Ionic v7, except for
* Firefox. The function was introduced in Firefox 75, which is conveniently the new minimum
* supported version in Ionic v8. As such, we'll probably want to just push the fix to v8,
* if v8 isn't already out by the time we get to this.
*/
contentEl.style.setProperty('top', `clamp(calc(var(--ion-safe-area-top, 0px) + var(--offset-y, 0px) + ${arrowHeight}px), calc(${top}px + var(--offset-y, 0px)), calc(100% - ${contentHeight + arrowHeight}px - var(--ion-safe-area-bottom) + var(--offset-y, 0px)))`);
contentEl.style.setProperty('left', `clamp(calc(var(--ion-safe-area-left, 0px) + var(--offset-x, 0px)), calc(${left}px + var(--offset-x, 0px)), calc(100% - ${contentWidth}px - var(--ion-safe-area-right) + var(--offset-x, 0px)))`);
contentEl.style.setProperty('transform-origin', `${originY} ${originX}`);
if (arrowEl !== null) {
const didAdjustBounds = results.top !== top || results.left !== left;
const showArrow = shouldShowArrow(side, didAdjustBounds, ev, trigger);
/**
* NOTE: Currently the fix assumes a default value for the side prop, which always
* puts the arrow either above or below the popover. There are additional tweaks
* needed to handle the arrow being on the left or right side.
*/
if (showArrow) {
arrowEl.style.setProperty('top', `calc(${arrowTop}px + var(--offset-y, 0))`);
arrowEl.style.setProperty('left', `calc(${arrowLeft}px + var(--offset-x, 0))`);
/**
* NOTE: Basically the same positioning logic as the popover content, but using the
* existing arrowTop and arrowLeft values instead. The hardcoded 5px in the left
* position was an early attempt at preventing the arrow from being flush with
* the left/right edge of the content, which causes it to look disconnected due
* to the content's border radius.
*
* The problem with this approach is that the popover content hits the max value
* sooner than the arrow, due to being taller. If you present a popover low enough
* on the screen to need safe area adjustment, but not so low that the popover flips
* to present above the trigger, the arrow will render overlapping the popover because
* the content has been adjusted for safe area but the arrow has not.
*
* In theory, the most straightforward way of fixing this would be to calculate the
* final rendered position of the popover and position the arrow relative to that.
* However, this would require using window.getComputedStyle(), which is exactly
* what we're trying to avoid.
*/
arrowEl.style.setProperty('top', `clamp(calc(var(--ion-safe-area-top, 0px) + var(--offset-y, 0px)), calc(${arrowTop}px + var(--offset-y, 0px)), calc(100% - ${arrowHeight + contentHeight}px - var(--ion-safe-area-bottom) + var(--offset-y, 0px)))`);
arrowEl.style.setProperty('left', `clamp(calc(var(--ion-safe-area-left, 0px) + var(--offset-x, 0px) + 5px), calc(${arrowLeft}px + var(--offset-x, 0px)), calc(100% - ${arrowWidth}px - var(--ion-safe-area-right) + var(--offset-x, 0px) - 5px))`);
/**
* NOTE: An early attempt at positioning the arrow relative to the content.
* See comments in popover.tsx for details.
*/
// arrowEl.style.setProperty('top', `-${arrowHeight}px`);
// arrowEl.style.setProperty('left', `calc(${contentWidth / 2}px - ${arrowWidth / 2}px)`);
/**
* NOTE: Some quick and dirty debugging code which will position some debug elements
* in the adjustment test template at the min, preferred, and max values for the
* popover content's position. This can help visualize how things are being calculated.
*/
// const minLine = document.querySelector('#min-line') as HTMLElement;
// const preferredLine = document.querySelector('#preferred-line') as HTMLElement;
// const maxLine = document.querySelector('#max-line') as HTMLElement;
// minLine!.style.top = `calc(var(--ion-safe-area-top, 0px) + var(--offset-y, 0px))`;
// preferredLine!.style.top = `calc(${arrowTop}px + var(--offset-y, 0px))`;
// maxLine!.style.top = `calc(100% - ${arrowHeight + contentHeight}px - var(--ion-safe-area-bottom) + var(--offset-y, 0px))`;
} else {
arrowEl.style.setProperty('display', 'none');
}

View File

@@ -78,11 +78,19 @@ export const mdEnterAnimation = (baseEl: HTMLElement, opts?: any): Animation =>
wrapperAnimation.addElement(root.querySelector('.popover-wrapper')!).duration(150).fromTo('opacity', 0.01, 1);
/**
* NOTE: See ios.enter.ts for details on what this is doing. For MD, this should work great.
* Technically, the logic for whether to flip the direction of the opening animation doesn't
* account for safe area, so there's a safe-area-margin-sized window where it flips in
* the wrong direction. However, because the margin is usually pretty small, this is barely
* noticeable in real world contexts. The popover is always positioned in a way that "feels"
* correct, and IMO this is an acceptable compromise.
*/
contentAnimation
.addElement(contentEl)
.beforeStyles({
top: `calc(${top}px + var(--offset-y, 0px))`,
left: `calc(${left}px + var(--offset-x, 0px))`,
top: `clamp(calc(var(--ion-safe-area-top, 0) + var(--offset-y)), calc(${top}px + var(--offset-y, 0px)), calc(100% - ${contentHeight}px - var(--ion-safe-area-bottom)))`,
left: `clamp(calc(var(--ion-safe-area-left, 0) + var(--offset-x)), calc(${left}px + var(--offset-x, 0px)), calc(100% - ${contentWidth}px - var(--ion-safe-area-right)))`,
'transform-origin': `${originY} ${originX}`,
})
.beforeAddWrite(() => {

View File

@@ -42,6 +42,9 @@
* will allow the arrow to render above the backdrop.
*/
z-index: 11;
// NOTE: Useful for debugging purposes when the arrow overlaps the content.
// --background: pink;
}
.popover-arrow::after {

View File

@@ -694,6 +694,21 @@ export class Popover implements ComponentInterface, PopoverInterface {
{!parentPopover && <ion-backdrop tappable={this.backdropDismiss} visible={this.showBackdrop} part="backdrop" />}
<div class="popover-wrapper ion-overlay-wrapper" onClick={dismissOnSelect ? () => this.dismiss() : undefined}>
{/**
* NOTE: One possibility is moving the arrow inside .popover-content and positioning the arrow relative
* to the content instead of to the whole screen. This has a few issues that we didn't have time to
* sort out:
* 1. The content hides overflow, so the arrow is no longer visible. However, setting overflow:visible
* also breaks the border radius for some reason. (Unsure why yet since border radius is set on the
* content el itself, so in theory overflow:hidden shouldn't be needed.)
* 2. Additional logic is needed to handle the arrow being above or below the content based on whether
* the popover has to flip due to being close to the bottom edge of the screen. calculateWindowAdjustment
* returns an addPopoverBottomClass var in the iOS enter animation that we may be able to use for this.
* (There are additional considerations for when popover's side prop is used to move the arrow, though.)
* 3. Additional logic is needed to handle the arrow moving horizontally to point at the trigger/event
* position. For example, if the popover is presented near the right edge of the screen, the arrow
* might be positioned more to the right instead of centered.
*/}
{enableArrow && <div class="popover-arrow" part="arrow"></div>}
<div class="popover-content" part="content">
<slot></slot>

View File

@@ -16,27 +16,112 @@
import { popoverController } from '../../../../dist/ionic/index.esm.js';
window.popoverController = popoverController;
</script>
<!-- <style>
.line {
position: absolute;
width: 100%;
height: 1px;
left: 0;
}
#min-line {
background-color: blue;
}
#preferred-line {
background-color: green;
}
#max-line {
background-color: red;
}
</style> -->
</head>
<body>
<ion-app>
<ion-content>
<p style="text-align: center">Click everywhere to open the popover.</p>
<!-- NOTE: Debugging elements to help visualize how the popover's position
is calculated. See comments near the bottom of ios.enter.ts for details. -->
<!-- <div id="min-line" class="line"></div>
<div id="preferred-line" class="line"></div>
<div id="max-line" class="line"></div> -->
<div style="text-align: center">
<p>Click everywhere to open the popover.</p>
<ion-button id="options-btn">Options</ion-button>
<ion-popover trigger="options-btn" class="options-popover">
<ion-list>
<ion-item>
<ion-checkbox id="safe-area-cb">Enable Safe Area</ion-checkbox>
</ion-item>
<ion-item>
<ion-checkbox id="offset-cb">Enable Popover Offset</ion-checkbox>
</ion-item>
</ion-list>
</ion-popover>
</div>
</ion-content>
</ion-app>
<script>
document.querySelector('ion-content').addEventListener('click', handleButtonClick);
document.querySelector('#safe-area-cb').addEventListener('ionChange', toggleSafeArea);
document.querySelector('#offset-cb').addEventListener('ionChange', toggleOffset);
async function handleButtonClick(ev) {
const targetEl = ev.target.tagName;
if (targetEl === 'ION-CHECKBOX' || targetEl === 'ION-BUTTON') return;
const popover = await popoverController.create({
component: 'popover-example-page',
event: ev,
reference: 'event',
reference: 'event'
});
popover.present();
}
function toggleStyles(ev, styles, styleId) {
if(ev.detail.checked) {
document.head.insertAdjacentHTML('beforeend', `
<style id="${styleId}">
${styles}
</style>
`);
} else {
const styles = document.querySelector(`#${styleId}`);
if(styles) styles.remove();
}
}
function toggleSafeArea(ev) {
toggleStyles(ev, `
html {
--ion-safe-area-top: 50px;
--ion-safe-area-right: 50px;
--ion-safe-area-bottom: 50px;
--ion-safe-area-left: 50px;
}
ion-content::part(background) {
box-shadow: inset 0 0 0 50px lightblue;
}
`, 'safe-area-styles');
}
/**
* NOTE: Make sure to also check any further fixes against a negative offset.
*/
function toggleOffset(ev) {
toggleStyles(ev, `
ion-popover:not(.options-popover) {
--offset-x: 25px;
--offset-y: 25px;
}
`, 'offset-styles');
}
customElements.define(
'popover-example-page',
class PopoverContent extends HTMLElement {

View File

@@ -526,7 +526,7 @@ export const present = async <OverlayPresentOptions>(
* from returning focus as a result.
*/
if (overlay.el.tagName !== 'ION-TOAST') {
restoreElementFocus(overlay.el);
focusPreviousElementOnDismiss(overlay.el);
}
/**
@@ -559,7 +559,7 @@ export const present = async <OverlayPresentOptions>(
* to where they were before they
* opened the overlay.
*/
const restoreElementFocus = async (overlayEl: any) => {
const focusPreviousElementOnDismiss = async (overlayEl: any) => {
let previousElement = document.activeElement as HTMLElement | null;
if (!previousElement) {
return;
@@ -572,34 +572,7 @@ const restoreElementFocus = async (overlayEl: any) => {
}
await overlayEl.onDidDismiss();
/**
* After onDidDismiss, the overlay loses focus
* because it is removed from the document
*
* > An element will also lose focus [...]
* > if the element is removed from the document)
*
* https://developer.mozilla.org/en-US/docs/Web/API/Element/blur_event
*
* Additionally, `document.activeElement` returns:
*
* > The Element which currently has focus,
* > `<body>` or null if there is
* > no focused element.
*
* https://developer.mozilla.org/en-US/docs/Web/API/Document/activeElement#value
*
* However, if the user has already focused
* an element sometime between onWillDismiss
* and onDidDismiss (for example, focusing a
* text box after tapping a button in an
* action sheet) then don't restore focus to
* previous element
*/
if (document.activeElement === null || document.activeElement === document.body) {
previousElement.focus();
}
previousElement.focus();
};
export const dismiss = async <OverlayDismissOptions>(

View File

@@ -254,52 +254,5 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
await expect(modalInputOne).toBeFocused();
});
test('should not return focus to another element if focus already manually returned', async ({
page,
skip,
}, testInfo) => {
skip.browser(
'webkit',
'WebKit does not consider buttons to be focusable, so this test always passes since the input is the only focusable element.'
);
testInfo.annotations.push({
type: 'issue',
description: 'https://github.com/ionic-team/ionic-framework/issues/28849',
});
await page.setContent(
`
<button id="open-action-sheet">open</button>
<ion-action-sheet trigger="open-action-sheet"></ion-action-sheet>
<input id="test-input" />
<script>
const actionSheet = document.querySelector('ion-action-sheet');
actionSheet.addEventListener('ionActionSheetWillDismiss', () => {
requestAnimationFrame(() => {
document.querySelector('#test-input').focus();
});
});
</script>
`,
config
);
const ionActionSheetDidPresent = await page.spyOnEvent('ionActionSheetDidPresent');
const actionSheet = page.locator('ion-action-sheet');
const input = page.locator('#test-input');
const trigger = page.locator('#open-action-sheet');
// present action sheet
await trigger.click();
await ionActionSheetDidPresent.next();
// dismiss action sheet
await actionSheet.evaluate((el: HTMLIonActionSheetElement) => el.dismiss());
// verify focus is in correct location
await expect(input).toBeFocused();
});
});
});

View File

@@ -3,14 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
**Note:** Version bump only for package @ionic/docs
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)
**Note:** Version bump only for package @ionic/docs

View File

@@ -1,12 +1,12 @@
{
"name": "@ionic/docs",
"version": "7.7.2",
"version": "7.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/docs",
"version": "7.7.2",
"version": "7.7.1",
"license": "MIT"
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/docs",
"version": "7.7.2",
"version": "7.7.1",
"description": "Pre-packaged API documentation for the Ionic docs.",
"main": "core.json",
"types": "core.d.ts",

View File

@@ -4,5 +4,5 @@
"docs",
"packages/*"
],
"version": "7.7.2"
"version": "7.7.1"
}

View File

@@ -3,14 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
**Note:** Version bump only for package @ionic/angular-server
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)
**Note:** Version bump only for package @ionic/angular-server

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/angular-server",
"version": "7.7.2",
"version": "7.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular-server",
"version": "7.7.2",
"version": "7.7.1",
"license": "MIT",
"dependencies": {
"@ionic/core": "^7.7.2"
"@ionic/core": "^7.7.1"
},
"devDependencies": {
"@angular-eslint/eslint-plugin": "^14.0.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular-server",
"version": "7.7.2",
"version": "7.7.1",
"description": "Angular SSR Module for Ionic",
"keywords": [
"ionic",
@@ -62,6 +62,6 @@
},
"prettier": "@ionic/prettier-config",
"dependencies": {
"@ionic/core": "^7.7.2"
"@ionic/core": "^7.7.1"
}
}

View File

@@ -3,14 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
**Note:** Version bump only for package @ionic/angular
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)
**Note:** Version bump only for package @ionic/angular

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/angular",
"version": "7.7.2",
"version": "7.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/angular",
"version": "7.7.2",
"version": "7.7.1",
"license": "MIT",
"dependencies": {
"@ionic/core": "^7.7.2",
"@ionic/core": "^7.7.1",
"ionicons": "^7.0.0",
"jsonc-parser": "^3.0.0",
"tslib": "^2.3.0"

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/angular",
"version": "7.7.2",
"version": "7.7.1",
"description": "Angular specific wrappers for @ionic/core",
"keywords": [
"ionic",
@@ -47,7 +47,7 @@
}
},
"dependencies": {
"@ionic/core": "^7.7.2",
"@ionic/core": "^7.7.1",
"ionicons": "^7.0.0",
"jsonc-parser": "^3.0.0",
"tslib": "^2.3.0"

View File

@@ -3,14 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
**Note:** Version bump only for package @ionic/react-router
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)
**Note:** Version bump only for package @ionic/react-router

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/react-router",
"version": "7.7.2",
"version": "7.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/react-router",
"version": "7.7.2",
"version": "7.7.1",
"license": "MIT",
"dependencies": {
"@ionic/react": "^7.7.2",
"@ionic/react": "^7.7.1",
"tslib": "*"
},
"devDependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/react-router",
"version": "7.7.2",
"version": "7.7.1",
"description": "React Router wrapper for @ionic/react",
"keywords": [
"ionic",
@@ -36,7 +36,7 @@
"dist/"
],
"dependencies": {
"@ionic/react": "^7.7.2",
"@ionic/react": "^7.7.1",
"tslib": "*"
},
"peerDependencies": {

View File

@@ -3,14 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
**Note:** Version bump only for package @ionic/react
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/react",
"version": "7.7.2",
"version": "7.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/react",
"version": "7.7.2",
"version": "7.7.1",
"license": "MIT",
"dependencies": {
"@ionic/core": "^7.7.2",
"@ionic/core": "^7.7.1",
"ionicons": "^7.0.0",
"tslib": "*"
},

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/react",
"version": "7.7.2",
"version": "7.7.1",
"description": "React specific wrapper for @ionic/core",
"keywords": [
"ionic",
@@ -39,7 +39,7 @@
"css/"
],
"dependencies": {
"@ionic/core": "^7.7.2",
"@ionic/core": "^7.7.1",
"ionicons": "^7.0.0",
"tslib": "*"
},

View File

@@ -3,14 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
**Note:** Version bump only for package @ionic/vue-router
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)
**Note:** Version bump only for package @ionic/vue-router

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/vue-router",
"version": "7.7.2",
"version": "7.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/vue-router",
"version": "7.7.2",
"version": "7.7.1",
"license": "MIT",
"dependencies": {
"@ionic/vue": "^7.7.2"
"@ionic/vue": "^7.7.1"
},
"devDependencies": {
"@ionic/eslint-config": "^0.3.0",

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/vue-router",
"version": "7.7.2",
"version": "7.7.1",
"description": "Vue Router integration for @ionic/vue",
"scripts": {
"test.spec": "jest",
@@ -44,7 +44,7 @@
},
"homepage": "https://github.com/ionic-team/ionic#readme",
"dependencies": {
"@ionic/vue": "^7.7.2"
"@ionic/vue": "^7.7.1"
},
"devDependencies": {
"@ionic/eslint-config": "^0.3.0",

View File

@@ -3,14 +3,6 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [7.7.2](https://github.com/ionic-team/ionic-framework/compare/v7.7.1...v7.7.2) (2024-02-14)
**Note:** Version bump only for package @ionic/vue
## [7.7.1](https://github.com/ionic-team/ionic-framework/compare/v7.7.0...v7.7.1) (2024-02-07)
**Note:** Version bump only for package @ionic/vue

View File

@@ -1,15 +1,15 @@
{
"name": "@ionic/vue",
"version": "7.7.2",
"version": "7.7.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@ionic/vue",
"version": "7.7.2",
"version": "7.7.1",
"license": "MIT",
"dependencies": {
"@ionic/core": "^7.7.2",
"@ionic/core": "^7.7.1",
"ionicons": "^7.0.0"
},
"devDependencies": {

View File

@@ -1,6 +1,6 @@
{
"name": "@ionic/vue",
"version": "7.7.2",
"version": "7.7.1",
"description": "Vue specific wrapper for @ionic/core",
"scripts": {
"eslint": "eslint src",
@@ -66,7 +66,7 @@
"vue-router": "^4.0.16"
},
"dependencies": {
"@ionic/core": "^7.7.2",
"@ionic/core": "^7.7.1",
"ionicons": "^7.0.0"
},
"vetur": {

View File

@@ -1,94 +0,0 @@
{
$schema: "https://docs.renovatebot.com/renovate-schema.json",
extends: ["config:base", ":semanticCommitTypeAll(chore)"],
packageRules: [
{
// Group these two as they may rely on one another during major version bumps
matchPackageNames: ["actions/download-artifact", "actions/upload-artifact"],
groupName: "Download + Upload Artifacts"
},
{
matchPackagePatterns: ["@stencil/core", "@stencil/angular-output-target", "@stencil/react-output-target", "@stencil/sass", "@stencil/vue-output-target"],
groupName: "stencil",
matchFileNames: [
"core/package.json"
]
},
{
matchPackagePatterns: ["@capacitor/core", "@capacitor/keyboard", "@capacitor/haptics", "@capacitor/status-bar"],
groupName: "capacitor",
matchFileNames: [
"core/package.json"
]
},
{
matchDatasources: ["npm"],
matchPackagePatterns: ["@playwright/test", "@axe-core/playwright"],
groupName: "playwright",
matchFileNames: [
"core/package.json"
]
},
{
matchPackagePatterns: ["ionicons"],
groupName: "ionicons",
matchFileNames: [
"core/package.json"
]
},
/**
* While we update dependencies in certain directories, we currently
* do not want to update every single dependency. Some of the dependencies are
* very out of date, and the team needs to schedule work to account for
* breaking changes in some of these updates. To potentially avoid a large number of
* failing PRs the team has chosen to selectively enable dependencies to be updated
* as we have capacity to account for breaking changes.
*/
{
matchPackagePatterns: ["tslib", "@ionic/", "@rollup/", "@types/", "@typescript-eslint/", "clean-css-cli", "domino", "eslint", "eslint-config-prettier", "execa", "fs-extra", "jest", "jest-cli", "prettier", "puppeteer", "rollup", "sass", "serve", "stylelint", "stylelint-order"],
groupName: "core-disabled",
matchFileNames: [
"core/package.json"
],
enabled: false
},
/**
* Local Ionic dependencies are managed by the
* workspace to ensure the correct local version is used.
*/
{
matchPackagePatterns: ["@ionic/", "ionicons"],
groupName: "ignore-local-ionic-deps",
matchFileNames: [
"**/package.json"
],
enabled: false
},
{
matchPackagePatterns: ["lerna", "semver"],
groupName: "root-disabled",
matchFileNames: [
"package.json"
],
enabled: false
}
],
dependencyDashboard: false,
minimumReleaseAge: "3 days",
rebaseWhen: "never",
schedule: ["every weekday before 11am"],
semanticCommits: "enabled",
ignorePaths: [
// Ionic Packages
"packages/angular",
"packages/angular-server",
"packages/react",
"packages/react-router",
"packages/vue",
"packages/vue-router",
"docs",
// Local Development Scripts
"core/custom-rules",
"core/scripts"
]
}