Skip to content
Draft
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
69 changes: 69 additions & 0 deletions packages/main/cypress/specs/Toolbar.cy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import ToolbarSelectOption from "../../src/ToolbarSelectOption.js";
import ToolbarSeparator from "../../src/ToolbarSeparator.js";
import ToolbarSpacer from "../../src/ToolbarSpacer.js";
import ToolbarItem from "../../src/ToolbarItem.js";
import CheckBox from "../../src/CheckBox.js";
import add from "@ui5/webcomponents-icons/dist/add.js";
import decline from "@ui5/webcomponents-icons/dist/decline.js";
import employee from "@ui5/webcomponents-icons/dist/employee.js";
Expand Down Expand Up @@ -46,6 +47,74 @@ describe("Toolbar general interaction", () => {
});
});

it("Should move focus inside checkbox group and leave group on boundary with single arrow press", () => {
cy.mount(
<Toolbar id="checkbox-group-toolbar">
<ToolbarItem>
<CheckBox text="Checkbox 1"></CheckBox>
<CheckBox text="Checkbox 2" checked></CheckBox>
<CheckBox text="Checkbox 3"></CheckBox>
</ToolbarItem>
<ToolbarButton text="After group"></ToolbarButton>
</Toolbar>
);

cy.get("[ui5-checkbox][text='Checkbox 1']")
.realClick()
.should("be.focused");

cy.realPress("ArrowRight");
cy.get("[ui5-checkbox][text='Checkbox 2']")
.should("be.focused");

cy.realPress("ArrowRight");
cy.get("[ui5-checkbox][text='Checkbox 3']")
.should("be.focused");

cy.realPress("ArrowRight");
cy.get("[ui5-toolbar-button][text='After group']")
.should("be.focused");
});

it("Should navigate into and out of overflow button with single arrow press", () => {
cy.viewport(320, 1080);

cy.mount(
<Toolbar id="overflow-arrow-toolbar" style={{ width: "220px" }}>
<ToolbarButton text="One Long"></ToolbarButton>
<ToolbarButton text="Two Long"></ToolbarButton>
<ToolbarButton text="Three Long"></ToolbarButton>
<ToolbarButton text="Four Long"></ToolbarButton>
<ToolbarButton text="Five Long"></ToolbarButton>
</Toolbar>
);

cy.get("#overflow-arrow-toolbar")
.shadow()
.find(".ui5-tb-overflow-btn")
.should("not.have.class", "ui5-tb-overflow-btn-hidden");

cy.get("#overflow-arrow-toolbar")
.then($toolbar => {
const toolbar = $toolbar[0] as Toolbar & {
_setCurrentItem: (item: ToolbarItem | HTMLElement) => void;
overflowButtonDOM: HTMLElement;
};
toolbar._setCurrentItem(toolbar.overflowButtonDOM);
toolbar.overflowButtonDOM.focus();
});

cy.realPress("ArrowRight");
cy.get("#overflow-arrow-toolbar")
.then($toolbar => {
const toolbar = $toolbar[0] as Toolbar & {
_lastFocusedItem?: ToolbarItem | HTMLElement;
};
const firstToolbarItem = $toolbar.find("[ui5-toolbar-button][text='One Long']")[0] as ToolbarItem;
expect(toolbar._lastFocusedItem).to.equal(firstToolbarItem);
});
});

it("shouldn't have toolbar button as popover opener when there is spacer before last toolbar item", () => {
cy.mount(
<Toolbar id="otb_spacer">
Expand Down
22 changes: 22 additions & 0 deletions packages/main/src/Input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import InputType from "./types/InputType.js";
import type Popover from "./Popover.js";
import type Icon from "./Icon.js";
import type { IIcon } from "./Icon.js";
import type { ToolbarMovementInfo } from "./ToolbarItemBase.js";

// Templates
import InputTemplate from "./InputTemplate.js";
Expand Down Expand Up @@ -1660,6 +1661,27 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
return this.nativeInput;
}

getToolbarMovementInfo(): ToolbarMovementInfo | undefined {
const input = this.getInputDOMRefSync();
if (!input) {
return undefined;
}

const active = getActiveElement() as HTMLElement | null;
const isInputFocused = !!active && (active === input || input.contains(active));
if (!isInputFocused) {
return undefined;
}

const caretIndex = input.selectionStart ?? 0;
const valueLength = input.value?.length ?? 0;

return {
currentIndex: caretIndex,
itemCount: valueLength + 1,
};
}

/**
* Returns a reference to the native input element
* @protected
Expand Down
1 change: 0 additions & 1 deletion packages/main/src/RadioButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ let activeRadio: RadioButton;
* @public
* @csspart outer-ring - Used to style the outer ring of the `ui5-radio-button`.
* @csspart inner-ring - Used to style the inner ring of the `ui5-radio-button`.
* @csspart root - Used to style the root DOM element of the component.
*/
@customElement({
tag: "ui5-radio-button",
Expand Down
23 changes: 23 additions & 0 deletions packages/main/src/TextArea.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import { isEscape } from "@ui5/webcomponents-base/dist/Keys.js";
import type { IFormInputElement } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js";
import type Popover from "./Popover.js";
import type InputComposition from "./features/InputComposition.js";
import getActiveElement from "@ui5/webcomponents-base/dist/util/getActiveElement.js";
import type { ToolbarMovementInfo } from "./ToolbarItemBase.js";

import TextAreaTemplate from "./TextAreaTemplate.js";

Expand Down Expand Up @@ -436,6 +438,27 @@ class TextArea extends UI5Element implements IFormInputElement {
return this.getDomRef()!.querySelector<HTMLTextAreaElement>("textarea")!;
}

getToolbarMovementInfo(): ToolbarMovementInfo | undefined {
const textArea = this.getDomRef()?.querySelector<HTMLTextAreaElement>("textarea");
if (!textArea) {
return undefined;
}

const active = getActiveElement() as HTMLElement | null;
const isTextAreaFocused = !!active && (active === textArea || textArea.contains(active));
if (!isTextAreaFocused) {
return undefined;
}

const caretIndex = textArea.selectionStart ?? 0;
const valueLength = textArea.value?.length ?? 0;

return {
currentIndex: caretIndex,
itemCount: valueLength + 1,
};
}

_onkeydown(e: KeyboardEvent) {
this._keyDown = true;

Expand Down
Loading
Loading