Skip to content

Commit a904c5e

Browse files
authored
feat(ui5-input): show associated label as mobile dialog header title (#13412)
1 parent f47c28e commit a904c5e

14 files changed

Lines changed: 338 additions & 9 deletions

packages/main/cypress/specs/ComboBox.mobile.cy.tsx

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import ComboBox from "../../src/ComboBox.js";
22
import ComboBoxItem from "../../src/ComboBoxItem.js";
33
import ComboBoxItemGroup from "../../src/ComboBoxItemGroup.js";
44
import type ResponsivePopover from "../../src/ResponsivePopover.js";
5-
import { COMBOBOX_DIALOG_OK_BUTTON, COMBOBOX_DIALOG_CANCEL_BUTTON } from "../../src/generated/i18n/i18n-defaults.js";
5+
import { COMBOBOX_DIALOG_OK_BUTTON, COMBOBOX_DIALOG_CANCEL_BUTTON, INPUT_SUGGESTIONS_TITLE } from "../../src/generated/i18n/i18n-defaults.js";
6+
import Label from "../../src/Label.js";
67

78
describe("Basic mobile picker rendering and interaction", () => {
89
beforeEach(() => {
@@ -618,3 +619,54 @@ describe("Mobile Highlighting", () => {
618619
.should("contain.html", "<b>A</b>");
619620
});
620621
});
622+
623+
describe("Dialog header title", () => {
624+
beforeEach(() => {
625+
cy.ui5SimulateDevice("phone");
626+
});
627+
628+
it("Should display label text as dialog header title when label for is used", () => {
629+
cy.mount(
630+
<>
631+
<Label for="myCB">Country</Label>
632+
<ComboBox id="myCB">
633+
<ComboBoxItem text="Algeria" />
634+
<ComboBoxItem text="Argentina" />
635+
</ComboBox>
636+
</>
637+
);
638+
639+
cy.get("#myCB").realClick();
640+
641+
cy.get("#myCB")
642+
.shadow()
643+
.find<ResponsivePopover>("[ui5-responsive-popover]")
644+
.ui5ResponsivePopoverOpened();
645+
646+
cy.get("#myCB")
647+
.shadow()
648+
.find("[ui5-responsive-popover] .ui5-responsive-popover-header-text")
649+
.should("have.text", "Country");
650+
});
651+
652+
it("Should fallback to 'All Items' when no label is associated", () => {
653+
cy.mount(
654+
<ComboBox id="myCB">
655+
<ComboBoxItem text="Algeria" />
656+
<ComboBoxItem text="Argentina" />
657+
</ComboBox>
658+
);
659+
660+
cy.get("#myCB").realClick();
661+
662+
cy.get("#myCB")
663+
.shadow()
664+
.find<ResponsivePopover>("[ui5-responsive-popover]")
665+
.ui5ResponsivePopoverOpened();
666+
667+
cy.get("#myCB")
668+
.shadow()
669+
.find("[ui5-responsive-popover] .ui5-responsive-popover-header-text")
670+
.should("have.text", INPUT_SUGGESTIONS_TITLE.defaultText);
671+
});
672+
});

packages/main/cypress/specs/Input.mobile.cy.tsx

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import Input from "../../src/Input.js";
22
import "../../src/features/InputSuggestions.js";
33
import type ResponsivePopover from "../../src/ResponsivePopover.js";
44
import SuggestionItem from "../../src/SuggestionItem.js";
5-
import { INPUT_SUGGESTIONS_OK_BUTTON, INPUT_SUGGESTIONS_CANCEL_BUTTON } from "../../src/generated/i18n/i18n-defaults.js";
5+
import { INPUT_SUGGESTIONS_OK_BUTTON, INPUT_SUGGESTIONS_CANCEL_BUTTON, INPUT_SUGGESTIONS_TITLE } from "../../src/generated/i18n/i18n-defaults.js";
6+
import Label from "../../src/Label.js";
67

78
describe("Input on mobile device", () => {
89
beforeEach(() => {
@@ -442,3 +443,54 @@ describe("Property open", () => {
442443
.ui5ResponsivePopoverClosed();
443444
});
444445
});
446+
447+
describe("Dialog header title", () => {
448+
beforeEach(() => {
449+
cy.ui5SimulateDevice("phone");
450+
});
451+
452+
it("Should display label text as dialog header title when label for is used", () => {
453+
cy.mount(
454+
<>
455+
<Label for="myInput">Country</Label>
456+
<Input id="myInput" showSuggestions>
457+
<SuggestionItem text="Item 1" />
458+
<SuggestionItem text="Item 2" />
459+
</Input>
460+
</>
461+
);
462+
463+
cy.get("#myInput").realClick();
464+
465+
cy.get("#myInput")
466+
.shadow()
467+
.find<ResponsivePopover>("[ui5-responsive-popover]")
468+
.ui5ResponsivePopoverOpened();
469+
470+
cy.get("#myInput")
471+
.shadow()
472+
.find("[ui5-responsive-popover] .ui5-responsive-popover-header-text")
473+
.should("have.text", "Country");
474+
});
475+
476+
it("Should fallback to 'All Items' when no label is associated", () => {
477+
cy.mount(
478+
<Input id="myInput" showSuggestions>
479+
<SuggestionItem text="Item 1" />
480+
<SuggestionItem text="Item 2" />
481+
</Input>
482+
);
483+
484+
cy.get("#myInput").realClick();
485+
486+
cy.get("#myInput")
487+
.shadow()
488+
.find<ResponsivePopover>("[ui5-responsive-popover]")
489+
.ui5ResponsivePopoverOpened();
490+
491+
cy.get("#myInput")
492+
.shadow()
493+
.find("[ui5-responsive-popover] .ui5-responsive-popover-header-text")
494+
.should("have.text", INPUT_SUGGESTIONS_TITLE.defaultText);
495+
});
496+
});

packages/main/cypress/specs/MultiComboBox.mobile.cy.tsx

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1-
import { SHOW_SELECTED_BUTTON } from "../../src/generated/i18n/i18n-defaults.js";
1+
import { SHOW_SELECTED_BUTTON, INPUT_SUGGESTIONS_TITLE } from "../../src/generated/i18n/i18n-defaults.js";
22
import MultiComboBox from "../../src/MultiComboBox.js";
33
import MultiComboBoxItem from "../../src/MultiComboBoxItem.js";
44
import ResponsivePopover from "../../src/ResponsivePopover.js";
5+
import Label from "../../src/Label.js";
56

67
describe("MultiComboBox mobile general interaction", () => {
78
beforeEach(() => {
@@ -874,4 +875,91 @@ describe("Accessibility", () => {
874875
.should("have.attr", "accessible-name", SHOW_SELECTED_BUTTON.defaultText);
875876

876877
});
878+
});
879+
880+
describe("Dialog header title", () => {
881+
beforeEach(() => {
882+
cy.ui5SimulateDevice("phone");
883+
});
884+
885+
it("Should display label text as dialog header title when label for is used", () => {
886+
cy.mount(
887+
<>
888+
<Label for="myMCB">Country</Label>
889+
<MultiComboBox id="myMCB">
890+
<MultiComboBoxItem text="Item 1" />
891+
<MultiComboBoxItem text="Item 2" />
892+
</MultiComboBox>
893+
</>
894+
);
895+
896+
cy.get("#myMCB")
897+
.shadow()
898+
.find("input")
899+
.realClick();
900+
901+
cy.get("#myMCB")
902+
.shadow()
903+
.find<ResponsivePopover>("[ui5-responsive-popover]")
904+
.ui5ResponsivePopoverOpened();
905+
906+
cy.get("#myMCB")
907+
.shadow()
908+
.find("[ui5-responsive-popover] .ui5-responsive-popover-header-text")
909+
.should("have.text", "Country");
910+
});
911+
912+
it("Should fallback to 'All Items' when no label is associated", () => {
913+
cy.mount(
914+
<MultiComboBox id="myMCB">
915+
<MultiComboBoxItem text="Item 1" />
916+
<MultiComboBoxItem text="Item 2" />
917+
</MultiComboBox>
918+
);
919+
920+
cy.get("#myMCB")
921+
.shadow()
922+
.find("input")
923+
.realClick();
924+
925+
cy.get("#myMCB")
926+
.shadow()
927+
.find<ResponsivePopover>("[ui5-responsive-popover]")
928+
.ui5ResponsivePopoverOpened();
929+
930+
cy.get("#myMCB")
931+
.shadow()
932+
.find("[ui5-responsive-popover] .ui5-responsive-popover-header-text")
933+
.should("have.text", INPUT_SUGGESTIONS_TITLE.defaultText);
934+
});
935+
936+
it("Should display label text as dialog header title when opened via n-more", () => {
937+
cy.mount(
938+
<>
939+
<Label for="myMCB">Country</Label>
940+
<MultiComboBox id="myMCB">
941+
<MultiComboBoxItem text="Item 1" selected />
942+
<MultiComboBoxItem text="Item 2" selected />
943+
<MultiComboBoxItem text="Item 3" />
944+
</MultiComboBox>
945+
</>
946+
);
947+
948+
cy.get("#myMCB")
949+
.shadow()
950+
.find("[ui5-tokenizer]")
951+
.shadow()
952+
.find(".ui5-tokenizer-more-text")
953+
.realClick();
954+
955+
cy.get("#myMCB")
956+
.shadow()
957+
.find<ResponsivePopover>("[ui5-responsive-popover]")
958+
.ui5ResponsivePopoverOpened();
959+
960+
cy.get("#myMCB")
961+
.shadow()
962+
.find("[ui5-responsive-popover] .ui5-responsive-popover-header-text")
963+
.should("have.text", "Country");
964+
});
877965
});

packages/main/cypress/specs/MultiInput.mobile.cy.tsx

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import SuggestionItem from "../../src/SuggestionItem.js";
44
import Button from "../../src/Button.js";
55
import "../../src/features/InputSuggestions.js";
66
import type ResponsivePopover from "@ui5/webcomponents/dist/ResponsivePopover.js";
7+
import { INPUT_SUGGESTIONS_TITLE } from "../../src/generated/i18n/i18n-defaults.js";
8+
import Label from "../../src/Label.js";
79

810
const createTokenFromText = (text: string): HTMLElement => {
911
const token = document.createElement("ui5-token");
@@ -213,3 +215,88 @@ describe("Multi Input on mobile device", () => {
213215
});
214216
});
215217
});
218+
219+
describe("Dialog header title", () => {
220+
beforeEach(() => {
221+
cy.ui5SimulateDevice("phone");
222+
});
223+
224+
it("Should display label text as dialog header title when label for is used", () => {
225+
cy.mount(
226+
<>
227+
<Label for="myMultiInput">Tags</Label>
228+
<MultiInput id="myMultiInput" showSuggestions>
229+
<SuggestionItem text="Item 1" />
230+
<SuggestionItem text="Item 2" />
231+
</MultiInput>
232+
</>
233+
);
234+
235+
cy.get("#myMultiInput")
236+
.shadow()
237+
.find(".ui5-input-inner")
238+
.realClick();
239+
240+
cy.get("#myMultiInput")
241+
.shadow()
242+
.find<ResponsivePopover>("[ui5-responsive-popover]")
243+
.ui5ResponsivePopoverOpened();
244+
245+
cy.get("#myMultiInput")
246+
.shadow()
247+
.find("[ui5-responsive-popover] .ui5-responsive-popover-header-text")
248+
.should("have.text", "Tags");
249+
});
250+
251+
it("Should display label text as n-more tokenizer popover title", () => {
252+
cy.mount(
253+
<>
254+
<Label for="myMultiInput">Tags</Label>
255+
<MultiInput id="myMultiInput" showSuggestions>
256+
<Token slot="tokens" text="Token 1" />
257+
<Token slot="tokens" text="Token 2" />
258+
<Token slot="tokens" text="Token 3" />
259+
</MultiInput>
260+
</>
261+
);
262+
263+
cy.get("#myMultiInput")
264+
.shadow()
265+
.find("[ui5-tokenizer]")
266+
.shadow()
267+
.find(".ui5-tokenizer-more-text")
268+
.realClick();
269+
270+
cy.get("#myMultiInput")
271+
.shadow()
272+
.find("[ui5-tokenizer]")
273+
.shadow()
274+
.find("[ui5-responsive-popover]")
275+
.find(".ui5-responsive-popover-header-text")
276+
.should("have.text", "Tags");
277+
});
278+
279+
it("Should fallback to 'All Items' when no label is associated", () => {
280+
cy.mount(
281+
<MultiInput id="myMultiInput" showSuggestions>
282+
<SuggestionItem text="Item 1" />
283+
<SuggestionItem text="Item 2" />
284+
</MultiInput>
285+
);
286+
287+
cy.get("#myMultiInput")
288+
.shadow()
289+
.find(".ui5-input-inner")
290+
.realClick();
291+
292+
cy.get("#myMultiInput")
293+
.shadow()
294+
.find<ResponsivePopover>("[ui5-responsive-popover]")
295+
.ui5ResponsivePopoverOpened();
296+
297+
cy.get("#myMultiInput")
298+
.shadow()
299+
.find("[ui5-responsive-popover] .ui5-responsive-popover-header-text")
300+
.should("have.text", INPUT_SUGGESTIONS_TITLE.defaultText);
301+
});
302+
});

packages/main/src/ComboBox.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1537,7 +1537,7 @@ class ComboBox extends UI5Element implements IFormInputElement {
15371537
}
15381538

15391539
get _headerTitleText() {
1540-
return ComboBox.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE);
1540+
return getAssociatedLabelForTexts(this) || ComboBox.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE);
15411541
}
15421542

15431543
get _iconAccessibleNameText() {

packages/main/src/ComboBoxPopoverTemplate.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Icon from "./Icon.js";
22
import Button from "./Button.js";
33
import List from "./List.js";
44
import Input from "./Input.js";
5+
import Title from "./Title.js";
56
import PopoverHorizontalAlign from "./types/PopoverHorizontalAlign.js";
67
import Popover from "./Popover.js";
78
import ResponsivePopover from "./ResponsivePopover.js";
@@ -40,7 +41,13 @@ export default function ComboBoxPopoverTemplate(this: ComboBox) {
4041
<>
4142
<div slot="header" class="ui5-responsive-popover-header">
4243
<div class="row">
43-
<span>{this._headerTitleText}</span>
44+
<Title
45+
level="H1"
46+
wrappingType="None"
47+
class="ui5-responsive-popover-header-text"
48+
>
49+
{this._headerTitleText}
50+
</Title>
4451
</div>
4552

4653
<div class="row">

packages/main/src/Input.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1765,7 +1765,7 @@ class Input extends UI5Element implements SuggestionComponent, IFormInputElement
17651765
}
17661766

17671767
get _headerTitleText() {
1768-
return Input.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE);
1768+
return this._associatedLabelsTexts || Input.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE);
17691769
}
17701770

17711771
get _suggestionsOkButtonText() {

packages/main/src/MultiComboBox.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2263,7 +2263,7 @@ class MultiComboBox extends UI5Element implements IFormInputElement {
22632263
}
22642264

22652265
get _headerTitleText() {
2266-
return MultiComboBox.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE);
2266+
return getAssociatedLabelForTexts(this) || MultiComboBox.i18nBundle.getText(INPUT_SUGGESTIONS_TITLE);
22672267
}
22682268

22692269
get _iconAccessibleNameText() {

packages/main/src/MultiInputTemplate.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ function preContent(this: MultiInput) {
3333
class="ui5-multi-input-tokenizer"
3434
opener={this.morePopoverOpener}
3535
popoverMinWidth={this._inputWidth}
36+
popoverTitle={this._headerTitleText}
3637
hidePopoverArrow={true}
3738
expanded={this.tokenizerExpanded}
3839
onKeyDown={this._onTokenizerKeydown}

0 commit comments

Comments
 (0)