Skip to content

feat(ui5-search-item-show-more): new show more item POC #11931

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

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
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
8 changes: 6 additions & 2 deletions packages/fiori/src/Search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,17 +329,21 @@ class Search extends SearchField {
}

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

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

_isGroupItem(item: ISearchSuggestionItem) {
return item.hasAttribute("ui5-search-item-group");
}

_isShowMoreItem(item: ISearchSuggestionItem) {
return item.hasAttribute("ui5-search-item-show-more");
}

_deselectItems() {
this._flattenItems.forEach(item => {
item.selected = false;
Expand Down
60 changes: 60 additions & 0 deletions packages/fiori/src/SearchItemShowMore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import customElement from "@ui5/webcomponents-base/dist/decorators/customElement.js";
import property from "@ui5/webcomponents-base/dist/decorators/property.js";
import ListItemBase from "@ui5/webcomponents/dist/ListItemBase.js";
import jsxRenderer from "@ui5/webcomponents-base/dist/renderer/JsxRenderer.js";
import SearchItemShowMoreTemplate from "./SearchItemShowMoreTemplate.js";
import SearchItemCss from "./generated/themes/SearchItem.css.js";
import SearchItemShowMoreCss from "./generated/themes/SearchItemShowMore.css.js";
import event from "@ui5/webcomponents-base/dist/decorators/event-strict.js";
import { isEnter, isSpace } from "@ui5/webcomponents-base/dist/Keys.js";
import SearchItem from "./SearchItem.js";

/**
* @class
* A suggestion item that acts as a "show more" button or group separator.
* @constructor
* @extends SearchItem
* @public
*/
@customElement({
tag: "ui5-search-item-show-more",
renderer: jsxRenderer,
template: SearchItemShowMoreTemplate,
styles: [
ListItemBase.styles,
SearchItemCss,
SearchItemShowMoreCss,
],
})

/* could be removed */
@event("show-more")

class SearchItemShowMore extends SearchItem {
eventDetails!: SearchItem["eventDetails"] & {
"show-more": void,
};
/**
* Defines the heading text of the search item.
* @public
*/

@property()
text?: string;

/* could be removed */
_onclick() {
this.fireDecoratorEvent("show-more");
}

/* could be removed */
_onkeydown(e: KeyboardEvent) {
if (isEnter(e) || isSpace(e)) {
this.fireDecoratorEvent("show-more");
}
}
}

SearchItemShowMore.define();

export default SearchItemShowMore;
17 changes: 17 additions & 0 deletions packages/fiori/src/SearchItemShowMoreTemplate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type SearchItemShowMore from "./SearchItemShowMore.js";

export default function SearchItemShowMoreTemplate(this: SearchItemShowMore) {
return (
<li
part="native-li"
class="ui5-li-root ui5-li--focusable ui5-search-item-show-more"
role="option"
tabindex={this._effectiveTabIndex}
aria-selected={this.selected}
onKeyDown={this._onkeydown}
onClick={this._onclick}
>
<span class="ui5-search-item-show-more-text">{this.text}</span>
</li>
);
}
1 change: 1 addition & 0 deletions packages/fiori/src/bundle.esm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import Search from "./Search.js";
import ShellBarSearch from "./ShellBarSearch.js";
import SearchMessageArea from "./SearchMessageArea.js";
import SearchItem from "./SearchItem.js";
import SearchItemShowMore from "./SearchItemShowMore.js";
import SearchItemGroup from "./SearchItemGroup.js";
import ShellBarBranding from "./ShellBarBranding.js";
import ShellBarSpacer from "./ShellBarSpacer.js";
Expand Down
3 changes: 3 additions & 0 deletions packages/fiori/src/themes/SearchItemShowMore.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.ui5-search-item-show-more-text {
color: var(--sapLinkColor);
}
77 changes: 74 additions & 3 deletions packages/fiori/test/pages/Search.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,77 @@
</ui5-search>
</div>

<ui5-label>Search with Grouped Suggestions and Show More (N) item</ui5-label>
<ui5-search id="searchShowMore" show-clear-icon placeholder="Placeholder">
<ui5-search-message-area slot="messageArea" description="You can try the following" text="Oh, there are no results"></ui5-search-message-area>
<ui5-search-item-group id="group1" header-text="Group Header">
</ui5-search-item-group>
<ui5-search-item-group id="group2" header-text="Group Header">
<ui5-search-item text="List Item" icon="history" ></ui5-search-item>
<ui5-search-item text="List Item" icon="history" ></ui5-search-item>
<ui5-search-item text="List Item" icon="globe" ></ui5-search-item>
</ui5-search-item-group>
</ui5-search>

<script>

const allItems = [
{ text: "List Item 1", icon: "history" },
{ text: "List Item 2", icon: "search" },
{ text: "List Item 3", icon: "history" },
{ text: "List Item 4", icon: "history" },
{ text: "List Item 5", icon: "search" },
{ text: "List Item 6", icon: "globe" }
];

const group1 = document.getElementById("group1");

function renderItems(items) {
group1.innerHTML = "";
const visibleCount = 3;
items.slice(0, visibleCount).forEach(item => {
const el = document.createElement("ui5-search-item");
el.addEventListener("ui5-delete", (e) => {
const el = e.target;
el.remove();
});
el.setAttribute("text", item.text);
el.setAttribute("icon", item.icon);
group1.appendChild(el);
});
if (items.length > visibleCount) {
const showMoreLi = document.createElement("ui5-search-item-show-more");
showMoreLi.setAttribute("text", `Show more (${items.length - visibleCount})`);
group1.appendChild(showMoreLi);

showMoreLi.addEventListener("ui5-show-more", () => {
let first = null;
items.slice(visibleCount).forEach((item, index) => {
const el = document.createElement("ui5-search-item");
el.addEventListener("ui5-delete", (e) => {
const el = e.target;
el.remove();
});
el.setAttribute("text", item.text);
el.setAttribute("icon", item.icon);
group1.insertBefore(el, showMoreLi);
if(index === 0) {
first = el;
}
});
showMoreLi.remove();
//wait the new items to show
setTimeout(() => {
first.focus();
}, 0);
});
}
}

renderItems(allItems);

</script>

<div class="container" style="padding-top: 1rem;">
<ui5-label>Search - Initially collapsed with Busy State</ui5-label>
<div class="container" style="border: 1px solid black; display: flex; padding: 4px; justify-content: flex-end;">
Expand Down Expand Up @@ -174,7 +245,7 @@
filtering.addEventListener('ui5-input', (event) => {
const value = event.target.value.toLowerCase();
const filteredData = data.filter(item => item.name.toLowerCase().includes(value));

// clear search items
filtering.innerHTML = '';

Expand Down Expand Up @@ -216,7 +287,7 @@
createScopeItems();
searchScope.addEventListener('ui5-scope-change', (event) => {
let scope = event.detail.scope.text === "All" ? "" : event.detail.scope.text.toLowerCase();

searchScope.getSlottedNodes("items").forEach(item => {
item.remove();
});
Expand All @@ -240,7 +311,7 @@
});
});
}

const filters = document.getElementById('filters');
filters.addEventListener('ui5-input', (event) => {
const value = event.target.value.toLowerCase();
Expand Down
Loading