Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ui5-date-picker): provide accessible name to the popover (#8693) #9221

Merged
merged 5 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion packages/main/src/DatePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,12 @@ import type { IFormElement } from "./features/InputElementsFormSupport.js";
import "@ui5/webcomponents-icons/dist/appointment-2.js";
import "@ui5/webcomponents-icons/dist/decline.js";
import HasPopup from "./types/HasPopup.js";
import { DATEPICKER_OPEN_ICON_TITLE, DATEPICKER_DATE_DESCRIPTION, INPUT_SUGGESTIONS_TITLE } from "./generated/i18n/i18n-defaults.js";
import {
DATEPICKER_OPEN_ICON_TITLE,
DATEPICKER_DATE_DESCRIPTION,
INPUT_SUGGESTIONS_TITLE,
DATEPICKER_POPOVER_ACCESSIBLE_NAME,
} from "./generated/i18n/i18n-defaults.js";
import DateComponentBase from "./DateComponentBase.js";
import Icon from "./Icon.js";
import Button from "./Button.js";
Expand Down Expand Up @@ -700,6 +705,10 @@ class DatePicker extends DateComponentBase implements IFormElement {
return DatePicker.i18nBundle.getText(DATEPICKER_DATE_DESCRIPTION);
}

get pickerAccessibleName() {
return DatePicker.i18nBundle.getText(DATEPICKER_POPOVER_ACCESSIBLE_NAME);
}

/**
* Defines whether the dialog on mobile should have header
* @private
Expand Down
1 change: 1 addition & 0 deletions packages/main/src/DatePickerPopover.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
allow-target-overlap
placement-type="Bottom"
horizontal-align="Left"
accessible-name="{{pickerAccessibleName}}"
hide-arrow
?_hide-header={{_shouldHideHeader}}
@keydown="{{_onkeydown}}"
Expand Down
12 changes: 11 additions & 1 deletion packages/main/src/DateRangePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { renderFinished } from "@ui5/webcomponents-base/dist/Render.js";
import CalendarDate from "@ui5/webcomponents-localization/dist/dates/CalendarDate.js";
import modifyDateBy from "@ui5/webcomponents-localization/dist/dates/modifyDateBy.js";
import getTodayUTCTimestamp from "@ui5/webcomponents-localization/dist/dates/getTodayUTCTimestamp.js";
import { DATERANGE_DESCRIPTION } from "./generated/i18n/i18n-defaults.js";
import { DATERANGE_DESCRIPTION, DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME } from "./generated/i18n/i18n-defaults.js";

// Styles
import DateRangePickerCss from "./generated/themes/DateRangePicker.css.js";
Expand Down Expand Up @@ -162,10 +162,20 @@ class DateRangePicker extends DatePicker {
return this.placeholder !== undefined ? this.placeholder : `${this._displayFormat} ${this._effectiveDelimiter} ${this._displayFormat}`;
}

/**
* @override
*/
get dateAriaDescription() {
return DateRangePicker.i18nBundle.getText(DATERANGE_DESCRIPTION);
}

/**
* @override
*/
get pickerAccessibleName() {
return DateRangePicker.i18nBundle.getText(DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME);
}

/**
* @override
*/
Expand Down
11 changes: 11 additions & 0 deletions packages/main/src/DateTimePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
DATETIME_DESCRIPTION,
DATETIME_PICKER_DATE_BUTTON,
DATETIME_PICKER_TIME_BUTTON,
DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME,
} from "./generated/i18n/i18n-defaults.js";

// Template
Expand Down Expand Up @@ -277,10 +278,20 @@ class DateTimePicker extends DatePicker {
return super.phone || this._phoneMode;
}

/**
* @override
*/
get dateAriaDescription() {
return DateTimePicker.i18nBundle.getText(DATETIME_DESCRIPTION);
}

/**
* @override
*/
get pickerAccessibleName() {
return DateTimePicker.i18nBundle.getText(DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME);
}

/**
* Defines whether the dialog on mobile should have header
* @private
Expand Down
5 changes: 5 additions & 0 deletions packages/main/src/TimePicker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {

import {
TIMEPICKER_INPUT_DESCRIPTION,
TIMEPICKER_POPOVER_ACCESSIBLE_NAME,
} from "./generated/i18n/i18n-defaults.js";

/**
Expand Down Expand Up @@ -144,6 +145,10 @@ class TimePicker extends TimePickerBase {
get dateAriaDescription() {
return TimePicker.i18nBundle.getText(TIMEPICKER_INPUT_DESCRIPTION);
}

get pickerAccessibleName() {
return TimePicker.i18nBundle.getText(TIMEPICKER_POPOVER_ACCESSIBLE_NAME);
}
}

TimePicker.define();
Expand Down
1 change: 1 addition & 0 deletions packages/main/src/TimePickerPopover.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
allow-target-overlap
_hide-header
hide-arrow
accessible-name="{{pickerAccessibleName}}"
@ui5-after-open="{{onResponsivePopoverAfterOpen}}"
@ui5-after-close="{{onResponsivePopoverAfterClose}}"
@wheel="{{_handleWheel}}"
Expand Down
12 changes: 12 additions & 0 deletions packages/main/src/i18n/messagebundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,15 @@ DATETIME_DESCRIPTION=Date Time Input
#XACT: Aria information for the Date Range Picker
DATERANGE_DESCRIPTION=Date Range Input

#XACT: Aria information for the Date Picker popover
DATEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date

#XACT: Aria information for the Date Time Picker popover
DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date and Time

#XACT: Aria information for the Date Range Picker popover
DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date Range

DELETE=Delete

FILEUPLOAD_BROWSE=Browse...
Expand Down Expand Up @@ -376,6 +385,9 @@ TIMEPICKER_CANCEL_BUTTON=Cancel
#XACT: Aria information for the Time Picker
TIMEPICKER_INPUT_DESCRIPTION=Time Input

#XACT: Aria information for the Time Picker popover
TIMEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Time

#XACT: Aria information for the Time Picker Clock Dial
TIMEPICKER_CLOCK_DIAL_LABEL=Clock Dial

Expand Down
14 changes: 14 additions & 0 deletions packages/main/test/specs/DatePicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1395,4 +1395,18 @@ describe("Date Picker Tests", () => {
assert.ok(await datepicker.isPickerOpen(), "Datepicker is open");
assert.equal(currentPicker, "day", "calendar is opened on days");
});

it("picker popover should have accessible name", async () => {
datepicker.id = "#dp";

const innerInput = await datepicker.getInnerInput();
await innerInput.click();
await browser.keys("F4");

const popover = await datepicker.getPopover();

assert.strictEqual(await popover.getAttribute("accessible-name"), "Choose Date", "Picker popover has an accessible name");

await browser.keys("Escape");
});
});
13 changes: 13 additions & 0 deletions packages/main/test/specs/DateRangePicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -264,4 +264,17 @@ describe("DateRangePicker general interaction", () => {

assert.strictEqual(await dateRangePickerInput.getProperty("valueState"), "Error", "Min and max dates are set correctly");
});

it("picker popover should have accessible name", async () => {
const daterangepicker = await browser.$("#daterange-picker3");
await daterangepicker.click();
await browser.keys("F4");

const staticAreaItemClassName = await browser.getStaticAreaItemClassName("#daterange-picker3");
const popover = await browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-responsive-popover");

assert.strictEqual(await popover.getAttribute("accessible-name"), "Choose Date Range", "Picker popover has an accessible name");

await browser.keys("Escape");
});
});
10 changes: 10 additions & 0 deletions packages/main/test/specs/DateTimePicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -290,5 +290,15 @@ describe("DateTimePicker general interaction", () => {
assert.strictEqual(await nextButton.hasClass("ui5-calheader-arrowbtn-disabled"), true, "The next button is disabled.");
});

it("picker popover should have accessible name", async () => {
await openPickerById("dt1");

const popover = await getPicker("dt1");

assert.strictEqual(await popover.getAttribute("accessible-name"), "Choose Date and Time", "Picker popover has an accessible name");

await closePickerById("dt1");
});

// TO DO: Create new testing page test secondary calendar type behaviour.
});
13 changes: 13 additions & 0 deletions packages/main/test/specs/TimePicker.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -228,4 +228,17 @@ describe("TimePicker general interaction", () => {
// assert that the value in the input is different than the string 'now'
assert.notStrictEqual(await timepicker.shadow$("ui5-input").getProperty("value"), "now", "the value is not 'now'");
});

it("picker popover should have accessible name", async () => {
const timepicker = await browser.$("#timepicker");
await timepicker.click();
await browser.keys("F4");

const staticAreaItemClassName = await browser.getStaticAreaItemClassName("#timepicker");
const popover = await browser.$(`.${staticAreaItemClassName}`).shadow$("ui5-responsive-popover");

assert.strictEqual(await popover.getAttribute("accessible-name"), "Choose Time", "Picker popover has an accessible name");

await browser.keys("Escape");
});
});