Skip to content

Commit 94bc485

Browse files
committed
feat: redesign the settings with grouping support
1 parent eb97e60 commit 94bc485

15 files changed

+1263
-273
lines changed

src/components/searchbar/index.js

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,6 @@ function searchBar($list, setHide, onhideCb, searchFunction) {
4949

5050
function hide() {
5151
actionStack.remove("searchbar");
52-
53-
if (!$list.parentElement) return;
5452
if (typeof onhideCb === "function") onhideCb();
5553

5654
$list.content = children;
@@ -70,6 +68,12 @@ function searchBar($list, setHide, onhideCb, searchFunction) {
7068
*/
7169
async function searchNow() {
7270
const val = $searchInput.value.toLowerCase();
71+
72+
if (!val) {
73+
$list.content = children;
74+
return;
75+
}
76+
7377
let result;
7478

7579
if (searchFunction) {
@@ -89,7 +93,7 @@ function searchBar($list, setHide, onhideCb, searchFunction) {
8993
}
9094

9195
$list.textContent = "";
92-
$list.append(...result);
96+
$list.append(...buildSearchContent(result, val));
9397
}
9498

9599
/**
@@ -103,6 +107,63 @@ function searchBar($list, setHide, onhideCb, searchFunction) {
103107
return text.match(val, "i");
104108
});
105109
}
110+
111+
/**
112+
* Keep grouped settings search results in section cards instead of flattening them.
113+
* @param {HTMLElement[]} result
114+
* @param {string} val
115+
* @returns {HTMLElement[]}
116+
*/
117+
function buildSearchContent(result, val) {
118+
if (!val || !result.length) return result;
119+
120+
const groups = new Map();
121+
let hasGroups = false;
122+
123+
result.forEach(($item) => {
124+
const label = $item.dataset.searchGroup;
125+
if (!label) return;
126+
hasGroups = true;
127+
128+
if (!groups.has(label)) {
129+
groups.set(label, []);
130+
}
131+
groups.get(label).push($item);
132+
});
133+
134+
if (!hasGroups) return result.map(cloneSearchItem);
135+
136+
const countLabel = `${result.length} ${result.length === 1 ? "RESULT" : "RESULTS"}`;
137+
const content = [
138+
<div className="settings-search-summary">{countLabel}</div>,
139+
];
140+
141+
groups.forEach((items, label) => {
142+
content.push(
143+
<section className="settings-section settings-search-section">
144+
<div className="settings-section-label">{label}</div>
145+
<div className="settings-section-card">
146+
{items.map(cloneSearchItem)}
147+
</div>
148+
</section>,
149+
);
150+
});
151+
152+
return content;
153+
}
154+
155+
/**
156+
* Render search results without moving the original list items out of their groups.
157+
* @param {HTMLElement} $item
158+
* @returns {HTMLElement}
159+
*/
160+
function cloneSearchItem($item) {
161+
const $clone = $item.cloneNode(true);
162+
$clone.addEventListener("click", () => {
163+
$item.click();
164+
});
165+
return $clone;
166+
}
106167
}
107168

108169
export default searchBar;

0 commit comments

Comments
 (0)