Skip to content

Commit 1e33a57

Browse files
chore(git): update next from main (#30050)
2 parents 2f538b3 + b0a2544 commit 1e33a57

35 files changed

+304
-116
lines changed

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,21 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
## [8.4.1](https://github.com/ionic-team/ionic-framework/compare/v8.4.0...v8.4.1) (2024-11-27)
7+
8+
9+
### Bug Fixes
10+
11+
* **header:** use aria attributes to hide small title when collapsed ([#30027](https://github.com/ionic-team/ionic-framework/issues/30027)) ([23763ab](https://github.com/ionic-team/ionic-framework/commit/23763abf797f9a4ba8262225760f718e9dcc4782)), closes [#29347](https://github.com/ionic-team/ionic-framework/issues/29347)
12+
* **menu:** hide from screen readers while animating ([#30036](https://github.com/ionic-team/ionic-framework/issues/30036)) ([845071c](https://github.com/ionic-team/ionic-framework/commit/845071c97a856d45eb5e0bb81d9c270bc38bb604))
13+
* **overlays:** announce info after opening based on platform ([#30025](https://github.com/ionic-team/ionic-framework/issues/30025)) ([f6188c4](https://github.com/ionic-team/ionic-framework/commit/f6188c47e9278fe69fd9d250c65156edbe5ef32e))
14+
* **overlays:** focus management with checkbox/radio ([#30026](https://github.com/ionic-team/ionic-framework/issues/30026)) ([8ee42bb](https://github.com/ionic-team/ionic-framework/commit/8ee42bbc1e0bf4731d20040c7853756722f1a4b2))
15+
* **toast:** swipe gesture works with custom container layout ([#29999](https://github.com/ionic-team/ionic-framework/issues/29999)) ([470decc](https://github.com/ionic-team/ionic-framework/commit/470decca7b6b89ef74095ef0bb7909b93640cd78)), closes [#29998](https://github.com/ionic-team/ionic-framework/issues/29998)
16+
17+
18+
19+
20+
621
# [8.4.0](https://github.com/ionic-team/ionic-framework/compare/v8.3.4...v8.4.0) (2024-11-04)
722

823

core/CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,21 @@
33
All notable changes to this project will be documented in this file.
44
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
55

6+
## [8.4.1](https://github.com/ionic-team/ionic-framework/compare/v8.4.0...v8.4.1) (2024-11-27)
7+
8+
9+
### Bug Fixes
10+
11+
* **header:** use aria attributes to hide small title when collapsed ([#30027](https://github.com/ionic-team/ionic-framework/issues/30027)) ([23763ab](https://github.com/ionic-team/ionic-framework/commit/23763abf797f9a4ba8262225760f718e9dcc4782)), closes [#29347](https://github.com/ionic-team/ionic-framework/issues/29347)
12+
* **menu:** hide from screen readers while animating ([#30036](https://github.com/ionic-team/ionic-framework/issues/30036)) ([845071c](https://github.com/ionic-team/ionic-framework/commit/845071c97a856d45eb5e0bb81d9c270bc38bb604))
13+
* **overlays:** announce info after opening based on platform ([#30025](https://github.com/ionic-team/ionic-framework/issues/30025)) ([f6188c4](https://github.com/ionic-team/ionic-framework/commit/f6188c47e9278fe69fd9d250c65156edbe5ef32e))
14+
* **overlays:** focus management with checkbox/radio ([#30026](https://github.com/ionic-team/ionic-framework/issues/30026)) ([8ee42bb](https://github.com/ionic-team/ionic-framework/commit/8ee42bbc1e0bf4731d20040c7853756722f1a4b2))
15+
* **toast:** swipe gesture works with custom container layout ([#29999](https://github.com/ionic-team/ionic-framework/issues/29999)) ([470decc](https://github.com/ionic-team/ionic-framework/commit/470decca7b6b89ef74095ef0bb7909b93640cd78)), closes [#29998](https://github.com/ionic-team/ionic-framework/issues/29998)
16+
17+
18+
19+
20+
621
# [8.4.0](https://github.com/ionic-team/ionic-framework/compare/v8.3.4...v8.4.0) (2024-11-04)
722

823

core/package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ionic/core",
3-
"version": "8.4.0",
3+
"version": "8.4.1",
44
"description": "Base components for Ionic",
55
"keywords": [
66
"ionic",

core/src/components.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2679,6 +2679,7 @@ export namespace Components {
26792679
* The name of the control, which is submitted with the form data.
26802680
*/
26812681
"name": string;
2682+
"setFocus": () => Promise<void>;
26822683
/**
26832684
* The theme determines the visual appearance of the component.
26842685
*/

core/src/components/header/header.utils.ts

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,34 @@ export const handleToolbarIntersection = (
167167

168168
export const setHeaderActive = (headerIndex: HeaderIndex, active = true) => {
169169
const headerEl = headerIndex.el;
170+
const toolbars = headerIndex.toolbars;
171+
const ionTitles = toolbars.map((toolbar) => toolbar.ionTitleEl);
170172

171173
if (active) {
172174
headerEl.classList.remove('header-collapse-condense-inactive');
173-
headerEl.removeAttribute('aria-hidden');
175+
176+
ionTitles.forEach((ionTitle) => {
177+
if (ionTitle) {
178+
ionTitle.removeAttribute('aria-hidden');
179+
}
180+
});
174181
} else {
175182
headerEl.classList.add('header-collapse-condense-inactive');
176-
headerEl.setAttribute('aria-hidden', 'true');
183+
184+
/**
185+
* The small title should only be accessed by screen readers
186+
* when the large title collapses into the small title due
187+
* to scrolling.
188+
*
189+
* Originally, the header was given `aria-hidden="true"`
190+
* but this caused issues with screen readers not being
191+
* able to access any focusable elements within the header.
192+
*/
193+
ionTitles.forEach((ionTitle) => {
194+
if (ionTitle) {
195+
ionTitle.setAttribute('aria-hidden', 'true');
196+
}
197+
});
177198
}
178199
};
179200

core/src/components/header/test/condense/header.e2e.ts

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,19 @@ import { configs, test } from '@utils/test/playwright';
33

44
configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, config }) => {
55
test.describe(title('header: condense'), () => {
6-
test('should be hidden from screen readers when collapsed', async ({ page }) => {
6+
test('should hide small title from screen readers when collapsed', async ({ page }) => {
7+
test.info().annotations.push({
8+
type: 'issue',
9+
description: 'https://github.com/ionic-team/ionic-framework/issues/29347',
10+
});
11+
712
await page.goto('/src/components/header/test/condense', config);
813
const largeTitleHeader = page.locator('#largeTitleHeader');
914
const smallTitleHeader = page.locator('#smallTitleHeader');
15+
const smallTitle = smallTitleHeader.locator('ion-title');
1016
const content = page.locator('ion-content');
1117

12-
await expect(smallTitleHeader).toHaveAttribute('aria-hidden', 'true');
18+
await expect(smallTitle).toHaveAttribute('aria-hidden', 'true');
1319

1420
await expect(largeTitleHeader).toHaveScreenshot(screenshot(`header-condense-large-title-initial-diff`));
1521

@@ -24,15 +30,15 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, screenshot, c
2430
* Playwright can't do .not.toHaveAttribute() because a value is expected,
2531
* and toHaveAttribute can't accept a value of type null.
2632
*/
27-
const ariaHidden = await smallTitleHeader.getAttribute('aria-hidden');
33+
const ariaHidden = await smallTitle.getAttribute('aria-hidden');
2834
expect(ariaHidden).toBeNull();
2935

3036
await content.evaluate(async (el: HTMLIonContentElement) => {
3137
await el.scrollToTop();
3238
});
3339
await page.locator('#smallTitleHeader.header-collapse-condense-inactive').waitFor();
3440

35-
await expect(smallTitleHeader).toHaveAttribute('aria-hidden', 'true');
41+
await expect(smallTitle).toHaveAttribute('aria-hidden', 'true');
3642
});
3743
});
3844
});

core/src/components/menu/menu.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type { Attributes } from '@utils/helpers';
88
import { inheritAriaAttributes, assert, clamp, isEndSide as isEnd } from '@utils/helpers';
99
import { menuController } from '@utils/menu-controller';
1010
import { BACKDROP, GESTURE, getPresentedOverlay } from '@utils/overlays';
11+
import { isPlatform } from '@utils/platform';
1112
import { hostContext } from '@utils/theme';
1213

1314
import { config } from '../../global/config';
@@ -635,6 +636,23 @@ export class Menu implements ComponentInterface, MenuI {
635636
private beforeAnimation(shouldOpen: boolean, role?: string) {
636637
assert(!this.isAnimating, '_before() should not be called while animating');
637638

639+
/**
640+
* When the menu is presented on an Android device, TalkBack's focus rings
641+
* may appear in the wrong position due to the transition (specifically
642+
* `transform` styles). This occurs because the focus rings are initially
643+
* displayed at the starting position of the elements before the transition
644+
* begins. This workaround ensures the focus rings do not appear in the
645+
* incorrect location.
646+
*
647+
* If this solution is applied to iOS devices, then it leads to a bug where
648+
* the overlays cannot be accessed by screen readers. This is due to
649+
* VoiceOver not being able to update the accessibility tree when the
650+
* `aria-hidden` is removed.
651+
*/
652+
if (isPlatform('android')) {
653+
this.el.setAttribute('aria-hidden', 'true');
654+
}
655+
638656
// this places the menu into the correct location before it animates in
639657
// this css class doesn't actually kick off any animations
640658
this.el.classList.add(SHOW_MENU);
@@ -691,6 +709,17 @@ export class Menu implements ComponentInterface, MenuI {
691709
}
692710

693711
if (isOpen) {
712+
/**
713+
* When the menu is presented on an Android device, TalkBack's focus rings
714+
* may appear in the wrong position due to the transition (specifically
715+
* `transform` styles). The menu is hidden from screen readers during the
716+
* transition to prevent this. Once the transition is complete, the menu
717+
* is shown again.
718+
*/
719+
if (isPlatform('android')) {
720+
this.el.removeAttribute('aria-hidden');
721+
}
722+
694723
// emit open event
695724
this.ionDidOpen.emit();
696725

@@ -707,6 +736,8 @@ export class Menu implements ComponentInterface, MenuI {
707736
// start focus trapping
708737
document.addEventListener('focus', this.handleFocus, true);
709738
} else {
739+
this.el.removeAttribute('aria-hidden');
740+
710741
// remove css classes and unhide content from screen readers
711742
this.el.classList.remove(SHOW_MENU);
712743

core/src/components/radio-group/radio-group.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type { ComponentInterface, EventEmitter } from '@stencil/core';
2-
import { Component, Element, Event, Host, Listen, Prop, Watch, h } from '@stencil/core';
2+
import { Component, Element, Event, Host, Listen, Method, Prop, Watch, h } from '@stencil/core';
33
import { renderHiddenInput } from '@utils/helpers';
44

55
import { getIonTheme } from '../../global/ionic-global';
@@ -221,6 +221,13 @@ export class RadioGroup implements ComponentInterface {
221221
}
222222
}
223223

224+
/** @internal */
225+
@Method()
226+
async setFocus() {
227+
const radioToFocus = this.getRadios().find((r) => r.tabIndex !== -1);
228+
radioToFocus?.setFocus();
229+
}
230+
224231
render() {
225232
const { label, labelId, el, name, value } = this;
226233
const theme = getIonTheme(this);

core/src/components/segment/test/segment-events.e2e.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { expect } from '@playwright/test';
2-
import { configs, test } from '@utils/test/playwright';
2+
import { configs, test, dragElementBy } from '@utils/test/playwright';
33

44
/**
55
* This behavior does not vary across modes/directions.
@@ -105,8 +105,7 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
105105
});
106106
});
107107

108-
// TODO FW-3021
109-
test.describe.skip('when the pointer is released', () => {
108+
test.describe('when the pointer is released', () => {
110109
test('should emit if the value has changed', async ({ page }) => {
111110
test.info().annotations.push({
112111
type: 'issue',
@@ -136,14 +135,22 @@ configs({ modes: ['ios'], directions: ['ltr'] }).forEach(({ title, config }) =>
136135

137136
const ionChangeSpy = await page.spyOnEvent('ionChange');
138137

138+
const segment = page.locator('ion-segment');
139139
const firstButton = page.locator('ion-segment-button[value="1"]');
140140
const lastButton = page.locator('ion-segment-button[value="3"]');
141141

142-
await firstButton.hover();
143-
await page.mouse.down();
144-
145-
await lastButton.hover();
146-
await page.mouse.up();
142+
/*
143+
* `dragByX` should represent the total width of all segment buttons,
144+
* excluding the first half of the first button and the second half
145+
* of the last button. This calculation accounts for dragging from
146+
* the center of the first button to the center of the last button.
147+
*/
148+
const segmentWidth = await segment.boundingBox().then((box) => (box ? box.width : 0));
149+
const firstButtonWidth = await firstButton.boundingBox().then((box) => (box ? box.width : 0));
150+
const lastButtonWidth = await lastButton.boundingBox().then((box) => (box ? box.width : 0));
151+
const dragByX = segmentWidth - firstButtonWidth / 2 - lastButtonWidth / 2;
152+
153+
await dragElementBy(firstButton, page, dragByX);
147154

148155
expect(ionChangeSpy).toHaveReceivedEventDetail({ value: '3' });
149156
expect(ionChangeSpy).toHaveReceivedEventTimes(1);

0 commit comments

Comments
 (0)