Skip to content

Commit f133a70

Browse files
feat(ui5-search-item-show-more): introduce new show more item (#11931)
1 parent df8804a commit f133a70

File tree

13 files changed

+412
-7
lines changed

13 files changed

+412
-7
lines changed

packages/fiori/cypress/specs/Search.cy.tsx

Lines changed: 92 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Title from "@ui5/webcomponents/dist/Title.js";
22
import Search from "../../src/Search.js";
33
import SearchItem from "../../src/SearchItem.js";
44
import SearchItemGroup from "../../src/SearchItemGroup.js";
5+
import SearchItemShowMore from "../../src/SearchItemShowMore.js";
56
import history from "@ui5/webcomponents-icons/dist/history.js";
67
import IllustratedMessage from "../../src/IllustratedMessage.js";
78
import searchIcon from "@ui5/webcomponents-icons/dist/search.js";
@@ -10,6 +11,7 @@ import Button from "@ui5/webcomponents/dist/Button.js";
1011
import ButtonDesign from "@ui5/webcomponents/dist/types/ButtonDesign.js";
1112
import Avatar from "@ui5/webcomponents/dist/Avatar.js";
1213
import AvatarSize from "@ui5/webcomponents/dist/types/AvatarSize.js";
14+
import { SEARCH_ITEM_SHOW_MORE_COUNT, SEARCH_ITEM_SHOW_MORE_NO_COUNT } from "../../src/generated/i18n/i18n-defaults.js";
1315

1416
describe("Properties", () => {
1517
it("items slot with groups", () => {
@@ -179,6 +181,95 @@ describe("Properties", () => {
179181
.should("not.exist");
180182
});
181183

184+
it("tests show more item text with counter", () => {
185+
cy.mount(
186+
<Search>
187+
<SearchItem text="List Item"></SearchItem>
188+
<SearchItemShowMore itemsToShowCount={3}></SearchItemShowMore>
189+
</Search>
190+
);
191+
192+
cy.get("[ui5-search]")
193+
.realClick()
194+
.realType("s");
195+
196+
cy.get("[ui5-search-item-show-more]")
197+
.should("be.visible");
198+
199+
cy.get("[ui5-search-item-show-more]")
200+
.shadow()
201+
.find("span")
202+
.as("itemText");
203+
204+
cy.get("[ui5-search-item-show-more]")
205+
.then($item => {
206+
const item = $item[0];
207+
const resourceBundle = (item.constructor as any).i18nBundle;
208+
209+
cy.get("@itemText")
210+
.should("have.text", resourceBundle.getText(SEARCH_ITEM_SHOW_MORE_COUNT.defaultText, 3));
211+
});
212+
213+
cy.get("@itemText")
214+
.should("have.class", "ui5-search-item-show-more-text");
215+
216+
});
217+
218+
it("tests show more item with no counter", () => {
219+
cy.mount(
220+
<Search>
221+
<SearchItem text="List Item"></SearchItem>
222+
<SearchItemShowMore></SearchItemShowMore>
223+
</Search>
224+
);
225+
226+
cy.get("[ui5-search]")
227+
.realClick()
228+
.realType("s");
229+
230+
cy.get("[ui5-search-item-show-more]")
231+
.should("be.visible");
232+
233+
cy.get("[ui5-search-item-show-more]")
234+
.shadow()
235+
.find("span")
236+
.as("itemText");
237+
238+
cy.get("[ui5-search-item-show-more]")
239+
.then($item => {
240+
const item = $item[0];
241+
const resourceBundle = (item.constructor as any).i18nBundle;
242+
243+
cy.get("@itemText")
244+
.should("have.text", resourceBundle.getText(SEARCH_ITEM_SHOW_MORE_NO_COUNT.defaultText));
245+
});
246+
247+
cy.get("@itemText")
248+
.should("have.class", "ui5-search-item-show-more-text");
249+
});
250+
251+
it("test show more item accessibility attributes", () => {
252+
cy.mount(
253+
<Search>
254+
<SearchItem text="List Item"></SearchItem>
255+
<SearchItemShowMore itemsToShowCount={2}></SearchItemShowMore>
256+
</Search>
257+
);
258+
259+
cy.get("[ui5-search]")
260+
.realClick()
261+
.realType("l");
262+
263+
cy.realPress("ArrowDown");
264+
cy.realPress("ArrowDown");
265+
266+
cy.get("[ui5-search-item-show-more]")
267+
.shadow()
268+
.find("li")
269+
.should("have.attr", "aria-selected", "true")
270+
.should("have.attr", "role", "option");
271+
});
272+
182273
it("tests loading property", () => {
183274
cy.mount(
184275
<Search loading={true}>
@@ -474,7 +565,7 @@ describe("Properties", () => {
474565
.realClick();
475566

476567
cy.realPress("I");
477-
568+
478569
cy.get("[ui5-search-item]")
479570
.eq(0)
480571
.realHover();

packages/fiori/src/Search.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,11 @@ class Search extends SearchField {
128128
*
129129
* @public
130130
*/
131-
@slot({ type: HTMLElement, "default": true })
131+
@slot({
132+
type: HTMLElement,
133+
"default": true,
134+
invalidateOnChildChange: true,
135+
})
132136
items!: Array<SearchItem | SearchItemGroup>;
133137

134138
/**
@@ -329,17 +333,21 @@ class Search extends SearchField {
329333
}
330334

331335
_startsWithMatchingItems(str: string): Array<ISearchSuggestionItem> {
332-
return StartsWith(str, this._flattenItems.filter(item => !this._isGroupItem(item)), "text");
336+
return StartsWith(str, this._flattenItems.filter(item => !this._isGroupItem(item) && !this._isShowMoreItem(item)), "text");
333337
}
334338

335339
_startsWithPerTermMatchingItems(str: string): Array<ISearchSuggestionItem> {
336-
return StartsWithPerTerm(str, this._flattenItems.filter(item => !this._isGroupItem(item)), "text");
340+
return StartsWithPerTerm(str, this._flattenItems.filter(item => !this._isGroupItem(item) && !this._isShowMoreItem(item)), "text");
337341
}
338342

339343
_isGroupItem(item: HTMLElement): item is SearchItemGroup {
340344
return item.hasAttribute("ui5-search-item-group");
341345
}
342346

347+
_isShowMoreItem(item: ISearchSuggestionItem) {
348+
return item.hasAttribute("ui5-search-item-show-more");
349+
}
350+
343351
_deselectItems() {
344352
this._flattenItems.forEach(item => {
345353
item.selected = false;
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
2+
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
3+
import ListItemBase from "@ui5/webcomponents/dist/ListItemBase.js";
4+
import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
5+
import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
6+
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
7+
import SearchItemShowMoreTemplate from "./SearchItemShowMoreTemplate.js";
8+
import SearchItemCss from "./generated/themes/SearchItem.css.js";
9+
import SearchItemShowMoreCss from "./generated/themes/SearchItemShowMore.css.js";
10+
import { SEARCH_ITEM_SHOW_MORE_COUNT, SEARCH_ITEM_SHOW_MORE_NO_COUNT } from "./generated/i18n/i18n-defaults.js";
11+
12+
/**
13+
* @class
14+
* ### Overview
15+
*
16+
* A `ui5-search-item-show-more` is a special type of ui5-li that acts as a button to progressively reveal additional (overflow) items within a group.
17+
*
18+
* ### ES6 Module Import
19+
*
20+
* `import "@ui5/webcomponents-fiori/dist/SearchItemShowMore.js";`
21+
*
22+
* @constructor
23+
* @extends ListItemBase
24+
* @public
25+
* @since 2.14.0
26+
* @experimental
27+
*/
28+
29+
@customElement({
30+
tag: "ui5-search-item-show-more",
31+
languageAware: true,
32+
renderer: jsxRenderer,
33+
template: SearchItemShowMoreTemplate,
34+
styles: [
35+
ListItemBase.styles,
36+
SearchItemCss,
37+
SearchItemShowMoreCss,
38+
],
39+
})
40+
41+
class SearchItemShowMore extends ListItemBase {
42+
/**
43+
* Specifies the number of additional items available to show.
44+
* This value replaces the placeholder (N) in the "Show more (N)" text.
45+
* If not set, the placeholder will remain as (N).
46+
* @public
47+
* @default undefined
48+
*/
49+
@property()
50+
itemsToShowCount ?: number;
51+
52+
/**
53+
* Defines whether the show more item is selected.
54+
* @default false
55+
* @public
56+
*/
57+
@property({ type: Boolean })
58+
selected = false;
59+
60+
@i18n("@ui5/webcomponents-fiori")
61+
static i18nBundle: I18nBundle;
62+
63+
get showMoreTextCount() {
64+
if (this.itemsToShowCount) {
65+
return SearchItemShowMore.i18nBundle.getText(SEARCH_ITEM_SHOW_MORE_COUNT, this.itemsToShowCount);
66+
}
67+
68+
return SearchItemShowMore.i18nBundle.getText(SEARCH_ITEM_SHOW_MORE_NO_COUNT);
69+
}
70+
71+
_onfocusin(e: FocusEvent) {
72+
super._onfocusin(e);
73+
this.selected = true;
74+
}
75+
76+
_onfocusout() {
77+
this.selected = false;
78+
}
79+
}
80+
81+
SearchItemShowMore.define();
82+
83+
export default SearchItemShowMore;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type SearchItemShowMore from "./SearchItemShowMore.js";
2+
3+
export default function SearchItemShowMoreTemplate(this: SearchItemShowMore) {
4+
return (
5+
<li
6+
class="ui5-li-root ui5-li--focusable ui5-search-item-show-more"
7+
role="option"
8+
tabindex={this._effectiveTabIndex}
9+
aria-selected={this.selected}
10+
onFocusIn={this._onfocusin}
11+
onFocusOut={this._onfocusout}
12+
>
13+
<span class="ui5-search-item-show-more-text">{this.showMoreTextCount}</span>
14+
</li>
15+
);
16+
}

packages/fiori/src/bundle.esm.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import Search from "./Search.js";
3636
import ShellBarSearch from "./ShellBarSearch.js";
3737
import SearchMessageArea from "./SearchMessageArea.js";
3838
import SearchItem from "./SearchItem.js";
39+
import SearchItemShowMore from "./SearchItemShowMore.js";
3940
import SearchItemGroup from "./SearchItemGroup.js";
4041
import ShellBarBranding from "./ShellBarBranding.js";
4142
import ShellBarSpacer from "./ShellBarSpacer.js";

packages/fiori/src/i18n/messagebundle.properties

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -488,6 +488,12 @@ SEARCH_FIELD_CLEAR_ICON=Clear search
488488
#XACT: ARIA announcement for search field search icon
489489
SEARCH_FIELD_SEARCH_ICON=Search
490490

491+
#TXT: Text for the "Show more" item in the search results list
492+
SEARCH_ITEM_SHOW_MORE_NO_COUNT=Show More
493+
494+
#TXT: Text for the "Show more" item in the search results list with counter
495+
SEARCH_ITEM_SHOW_MORE_COUNT=Show More ({0})
496+
491497
#XACT: ARIA announcement for search field collapsed search button
492498
SHELLBAR_SEARCH_COLLAPSED=Open Search
493499

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.ui5-search-item-show-more-text {
2+
color: var(--sapLinkColor);
3+
}
4+
5+
.ui5-search-item-show-more-text:active {
6+
color: var(--sapList_Active_TextColor);
7+
}

0 commit comments

Comments
 (0)