Skip to content

Commit d76c408

Browse files
Merge branch 'main' into user-settings-appearance-view
2 parents c14de7c + 49b5c1d commit d76c408

9 files changed

Lines changed: 122 additions & 2 deletions

File tree

packages/fiori/src/themes/UserSettingsDialog.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
padding: 0;
1010
}
1111

12+
.ui5-user-settings-dialog::part(footer) {
13+
padding: 0;
14+
}
15+
1216
.ui5-user-settings-root {
1317
display: flex;
1418
height: 100%;

packages/main/cypress/specs/DateTimePicker.cy.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,26 @@ describe("DateTimePicker general interaction", () => {
550550
});
551551

552552
describe("Accessibility", () => {
553+
it("initial focus goes to calendar's current date in phone mode", () => {
554+
// Using viewport instead of device simulation (focus is not available on actual phone devices), to trigger SegmentedButton view.
555+
cy.viewport(500, 800);
556+
557+
cy.mount(<DateTimePickerTemplate value="13/04/2020, 03:16:16 PM" formatPattern="dd/MM/yyyy, hh:mm:ss a" />);
558+
559+
cy.get<DateTimePicker>("[ui5-datetime-picker]").as("dtp");
560+
561+
cy.get<DateTimePicker>("@dtp").ui5DateTimePickerOpen();
562+
563+
cy.get<DateTimePicker>("@dtp")
564+
.ui5DateTimePickerGetPopover()
565+
.find("[ui5-calendar]")
566+
.shadow()
567+
.find("[ui5-daypicker]")
568+
.shadow()
569+
.find(".ui5-dp-item--selected")
570+
.should("be.focused");
571+
});
572+
553573
it("picker popover accessible name", () => {
554574
const LABEL = "Deadline";
555575
cy.mount(<DateTimePicker accessible-name={LABEL} />);

packages/main/cypress/specs/Link.cy.tsx

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,4 +260,65 @@ describe("General API", () => {
260260
cy.get("@signInDialog")
261261
.should("be.visible");
262262
});
263+
264+
it("tabindex should update when text content is added after mount", () => {
265+
// Mount link without text content
266+
cy.mount(<Link id="dynamic-link"></Link>);
267+
268+
// Initially, tabindex should be -1 because there's no text content
269+
cy.get("#dynamic-link")
270+
.shadow()
271+
.find(".ui5-link-root")
272+
.should("have.attr", "tabindex", "-1");
273+
274+
// Add text content dynamically
275+
cy.get("#dynamic-link")
276+
.then($link => {
277+
$link[0].textContent = "Click me";
278+
});
279+
280+
// After text is added, tabindex should become 0
281+
cy.get("#dynamic-link")
282+
.shadow()
283+
.find(".ui5-link-root")
284+
.should("have.attr", "tabindex", "0");
285+
});
286+
287+
it("tabindex should remain 0 when text content changes", () => {
288+
cy.mount(<Link id="text-change-link">Initial Text</Link>);
289+
290+
cy.get("#text-change-link")
291+
.shadow()
292+
.find(".ui5-link-root")
293+
.should("have.attr", "tabindex", "0");
294+
295+
cy.get("#text-change-link")
296+
.then($link => {
297+
$link[0].textContent = "Updated Text";
298+
});
299+
300+
cy.get("#text-change-link")
301+
.shadow()
302+
.find(".ui5-link-root")
303+
.should("have.attr", "tabindex", "0");
304+
});
305+
306+
it("tabindex should be -1 when text content is removed", () => {
307+
cy.mount(<Link id="remove-text-link">Some text</Link>);
308+
309+
cy.get("#remove-text-link")
310+
.shadow()
311+
.find(".ui5-link-root")
312+
.should("have.attr", "tabindex", "0");
313+
314+
cy.get("#remove-text-link")
315+
.then($link => {
316+
$link[0].textContent = "";
317+
});
318+
319+
cy.get("#remove-text-link")
320+
.shadow()
321+
.find(".ui5-link-root")
322+
.should("have.attr", "tabindex", "-1");
323+
});
263324
});

packages/main/src/Calendar.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,14 @@ class Calendar extends CalendarPart {
612612
return this.shadowRoot!.querySelector(`[ui5-${this._currentPicker}picker]`)! as unknown as ICalendarPicker;
613613
}
614614

615+
/**
616+
* Returns the focusable element inside the Calendar (the current picker)
617+
* @override
618+
*/
619+
getFocusDomRef() {
620+
return this._currentPickerDOM as HTMLElement | undefined;
621+
}
622+
615623
/**
616624
* The year clicked the "Previous" button in the header
617625
*/

packages/main/src/DatePickerPopoverTemplate.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ import information from "@ui5/webcomponents-icons/dist/information.js";
1414

1515
type TemplateHook = () => void;
1616

17-
export default function DatePickerPopoverTemplate(this: DatePicker, hooks?: { header?: TemplateHook, content?: TemplateHook, footer?: TemplateHook }) {
17+
export default function DatePickerPopoverTemplate(this: DatePicker, hooks?: { header?: TemplateHook, content?: TemplateHook, footer?: TemplateHook, initialFocus?: string }) {
1818
const header = hooks?.header || defaultHeader;
1919
const content = hooks?.content || defaultContent;
2020
const footer = hooks?.footer || defaultFooter;
21+
const initialFocus = hooks?.initialFocus;
2122

2223
return (
2324
<ResponsivePopover
@@ -31,6 +32,7 @@ export default function DatePickerPopoverTemplate(this: DatePicker, hooks?: { he
3132
accessibleName={this.pickerAccessibleName}
3233
hideArrow={true}
3334
_hideHeader={this._shouldHideHeader}
35+
initialFocus={initialFocus}
3436
onKeyDown={this._onkeydown}
3537
onClose={this.onResponsivePopoverAfterClose}
3638
onOpen={this.onResponsivePopoverAfterOpen}

packages/main/src/DateTimePicker.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,14 @@ class DateTimePicker extends DatePicker implements IFormInputElement {
322322
return false;
323323
}
324324

325+
/**
326+
* Returns the ID of the element to focus initially when the picker opens in phone mode
327+
* @private
328+
*/
329+
get _initialFocusId() {
330+
return this._phoneMode ? `${this._id}-calendar` : undefined;
331+
}
332+
325333
/**
326334
* EVENT HANDLERS
327335
*/

packages/main/src/DateTimePickerTemplate.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import TimeSelectionClocks from "./TimeSelectionClocks.js";
1212
export default function DateTimePickerTemplate(this: DateTimePicker) {
1313
return [
1414
DatePickerInputTemplate.call(this),
15-
DatePickerPopoverTemplate.call(this, { content, footer }),
15+
DatePickerPopoverTemplate.call(this, { content, footer, initialFocus: this._initialFocusId }),
1616
];
1717
}
1818

packages/main/src/Link.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import UI5Element from "@ui5/webcomponents-base/dist/UI5Element.js";
22
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
33
import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
44
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
5+
import slot from "@ui5/webcomponents-base/dist/decorators/slot.js";
56
import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
67
import type { AccessibilityAttributes } from "@ui5/webcomponents-base/dist/types.js";
78
import { isSpace, isEnter } from "@ui5/webcomponents-base/dist/Keys.js";
@@ -268,6 +269,15 @@ class Link extends UI5Element implements ITabbable {
268269
@property()
269270
endIcon?: string;
270271

272+
/**
273+
* Defines the text of the component.
274+
*
275+
* **Note:** Although this slot accepts HTML Elements, it is strongly recommended that you only use text in order to preserve the intended design.
276+
* @public
277+
*/
278+
@slot({ type: Node, "default": true })
279+
text!: Array<Node>;
280+
271281
@property({ noAttribute: true })
272282
_rel: string | undefined;
273283

packages/main/src/StepInput.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,13 @@ class StepInput extends UI5Element implements IFormInputElement {
513513
}
514514

515515
get _isValueWithCorrectPrecision() {
516+
// check if the value will be displayed with correct precision
517+
// _displayValue has special formatting logic
518+
if ((this.value === 0) || (Number.isInteger(this.value))) {
519+
// integers and zero will be formatted with toFixed, so they're always valid
520+
return true;
521+
}
522+
516523
// gets either "." or "," as delimiter which is based on locale, and splits the number by it
517524
const delimiter = this.input?.value?.includes(".") ? "." : ",";
518525
const numberParts = this.input?.value?.split(delimiter);

0 commit comments

Comments
 (0)