Skip to content

Commit 6c87ba6

Browse files
authored
bug: Issue-2367 - Fixed the search functionality (#93)
1 parent 3d624b2 commit 6c87ba6

7 files changed

Lines changed: 199 additions & 9 deletions

File tree

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,13 @@
4242
"@visual-framework/vf-sass-config": "2.6.1",
4343
"@visual-framework/vf-sass-starter": "^0.1.30",
4444
"@visual-framework/vf-search": "^1.0.0",
45+
"@visual-framework/vf-search-client-side": "^2.0.2",
4546
"@visual-framework/vf-stack": "^3.0.0",
4647
"@visual-framework/vf-tabs": "^2.1.5",
4748
"@visual-framework/vf-text": "^1.1.1",
4849
"@visual-framework/vf-u-fullbleed": "^1.2.2",
4950
"@visual-framework/vf-utility-classes": "2.0.0",
51+
"lunr": "^2.3.9",
5052
"react": "^18.2.0",
5153
"react-dom": "^18.2.0",
5254
"react-router-dom": "^6.21.1",

src/App.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import VFBlockquote from './components/VFBlockquote';
1212
import VFHero from './components/VFHero';
1313
import VFBanner from './components/VFBanner';
1414
import VFTabs from './components/VFTabs';
15+
import SearchResults from './components/SearchResults';
1516
// import VFChatbot from './vf-chatbot-components/vf-chatbot/vf-chatbot.react';
1617
import VFChatbot from '@visual-framework/vf-chatbot/vf-chatbot.react';
1718

@@ -137,6 +138,7 @@ function App() {
137138
<Route path="/components/vf-hero" element={<VFHero />} />
138139
<Route path="/components/vf-banner" element={<VFBanner />} />
139140
<Route path="/components/vf-tabs" element={<VFTabs />} />
141+
<Route path="/search" element={<SearchResults />} />
140142
</Routes>
141143
<Footer />
142144
</RouteChangeHandler>

src/components/Footer/index.jsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,6 @@ function Footer() {
7878
<li className="vf-list__item">
7979
<a className="vf-list__link" href="https://github.com/visual-framework/vf-core">GitHub</a>
8080
</li>
81-
<li className="vf-list__item">
82-
<a className="vf-list__link" href="https://join.slack.com/t/visual-framework/shared_invite/enQtNDAxNzY0NDg4NTY0LWFhMjEwNGY3ZTk3NWYxNWVjOWQ1ZWE4YjViZmY1YjBkMDQxMTNlNjQ0N2ZiMTQ1ZTZiMGM4NjU5Y2E0MjM3ZGQ">Slack</a>
83-
</li>
8481
</ul>
8582
</div>
8683
<div className="vf-links"></div>

src/components/Header/index.jsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,9 +101,6 @@ function Header() {
101101
{/* External links should remain as <a> tags */}
102102
<a href="https://github.com/visual-framework/vf-core" className="vf-navigation__link vf-mega-menu__link">GitHub</a>
103103
</li>
104-
<li className="vf-navigation__item">
105-
<a href="https://join.slack.com/t/visual-framework/shared_invite/enQtNDAxNzY0NDg4NTY0LWFhMjEwNGY3ZTk3NWYxNWVjOWQ1ZWE4YjViZmY1YjBkMDQxMTNlNjQ0N2ZiMTQ1ZTZiMGM4NjU5Y2E0MjM3ZGQ" className="vf-navigation__link vf-mega-menu__link">Slack</a>
106-
</li>
107104
<li className="vf-navigation__item">
108105
<Link
109106
to="/search"
@@ -315,7 +312,7 @@ function Header() {
315312
<h2 className="vf-section-header__heading" id="search"> Search</h2>
316313
</div>
317314

318-
<form action="/search/" method="GET" className="vf-form vf-form--search vf-form--search--responsive | vf-sidebar vf-sidebar--end">
315+
<form action="/vf-react/search/" method="GET" className="vf-form vf-form--search vf-form--search--responsive | vf-sidebar vf-sidebar--end">
319316
<div className="vf-sidebar__inner">
320317
<div className="vf-form__item | vf-search__item">
321318
<label className="vf-form__label vf-u-sr-only | vf-search__label" htmlFor="search_query" />

src/components/Home/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function Home() {
5151
</div>
5252

5353
<form
54-
action="/search/"
54+
action="/vf-react/search/"
5555
method="GET"
5656
className="vf-form vf-form--search vf-form--search--responsive | vf-sidebar vf-sidebar--end"
5757
>
@@ -63,7 +63,7 @@ function Home() {
6363
></label>
6464
<input
6565
type="search"
66-
id="search"
66+
id="search_query"
6767
placeholder="Search components and documentation"
6868
name="search_query"
6969
className="vf-search__input | vf-form__input"
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
import React, { useEffect } from "react";
2+
import { Link, useSearchParams } from "react-router-dom";
3+
import lunr from "lunr";
4+
import { componentSearchIndex } from "../searchIndex";
5+
import "@visual-framework/vf-search-client-side/vf-search-client-side.css";
6+
7+
function SearchResults() {
8+
const [searchParams] = useSearchParams();
9+
const query = (searchParams.get("search_query") || "").trim();
10+
11+
useEffect(() => {
12+
// vf-search-client-side expects global `lunr` and `searchIndex` variables.
13+
window.lunr = lunr;
14+
window.searchIndex = {
15+
pages: componentSearchIndex.map((item, index) => ({
16+
id: String(index),
17+
title: item.name,
18+
text: `${item.description}`,
19+
url: item.path,
20+
})),
21+
};
22+
23+
let isMounted = true;
24+
25+
import("@visual-framework/vf-search-client-side/vf-search-client-side.js")
26+
.then(({ vfSearchClientSide }) => {
27+
if (isMounted) {
28+
vfSearchClientSide();
29+
}
30+
})
31+
.catch(() => {
32+
const resultsContainer = document.querySelector(
33+
"[data-vf-search-client-side-results]",
34+
);
35+
if (resultsContainer) {
36+
resultsContainer.textContent =
37+
"Search is temporarily unavailable. Please try again.";
38+
}
39+
});
40+
41+
return () => {
42+
isMounted = false;
43+
};
44+
}, []);
45+
46+
return (
47+
<div>
48+
<section class="vf-intro" id="an-id-for-anchor">
49+
<div></div>
50+
51+
<div class="vf-stack">
52+
<h1 class="vf-intro__heading ">Search</h1>
53+
<p class="vf-lede">Search documentation and guidance.</p>
54+
55+
<p class="vf-intro__text"></p>
56+
</div>
57+
</section>
58+
<div className="embl-grid embl-grid--has-centered-content">
59+
<div></div>
60+
<div className="vf-stack vf-stack--400">
61+
<form
62+
action=""
63+
method="GET"
64+
className="vf-form vf-form--search vf-form--search--responsive | vf-sidebar vf-sidebar--end"
65+
>
66+
<div className="vf-sidebar__inner">
67+
<div className="vf-form__item | vf-search__item">
68+
<label
69+
className="vf-form__label vf-u-sr-only | vf-search__label"
70+
htmlFor="search_query"
71+
>
72+
Search
73+
</label>
74+
<input
75+
type="search"
76+
id="search_query"
77+
placeholder="Search components and documentation"
78+
name="search_query"
79+
defaultValue={query}
80+
className="vf-search__input | vf-form__input"
81+
data-vf-search-client-side-input
82+
data-vf-search-client-side-destination-prefix=""
83+
/>
84+
</div>
85+
<button
86+
type="submit"
87+
className="vf-search__button | vf-button vf-button--primary"
88+
>
89+
<span className="vf-button__text">Search</span>
90+
<svg
91+
className="vf-icon vf-icon--search-btn | vf-button__icon"
92+
aria-hidden="true"
93+
xmlns="http://www.w3.org/2000/svg"
94+
version="1.1"
95+
viewBox="0 0 140 140"
96+
width="140"
97+
height="140"
98+
>
99+
<g transform="matrix(5.833333333333333,0,0,5.833333333333333,0,0)">
100+
<path
101+
d="M23.414,20.591l-4.645-4.645a10.256,10.256,0,1,0-2.828,2.829l4.645,4.644a2.025,2.025,0,0,0,2.828,0A2,2,0,0,0,23.414,20.591ZM10.25,3.005A7.25,7.25,0,1,1,3,10.255,7.258,7.258,0,0,1,10.25,3.005Z"
102+
fill="#FFFFFF"
103+
stroke="none"
104+
strokeLinecap="round"
105+
strokeLinejoin="round"
106+
strokeWidth="0"
107+
/>
108+
</g>
109+
</svg>
110+
</button>
111+
</div>
112+
</form>
113+
114+
<div className="vf-search-client-side vf-grid | vf-content">
115+
<div
116+
className="results-container"
117+
data-vf-search-client-side-results
118+
>
119+
Loading...
120+
</div>
121+
</div>
122+
</div>
123+
<div></div>
124+
</div>
125+
</div>
126+
);
127+
}
128+
129+
export default SearchResults;

src/components/searchIndex.js

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
export const componentSearchIndex = [
2+
{
3+
name: "vf-badge",
4+
path: "/vf-react/components/vf-badge",
5+
description: "vf-badge"
6+
},
7+
{
8+
name: "vf-back-to-top",
9+
path: "/vf-react/components/vf-back-to-top",
10+
description: "vf-back-to-top"
11+
},
12+
{
13+
name: "vf-button",
14+
path: "/vf-react/components/vf-button",
15+
description: "vf-button"
16+
},
17+
{
18+
name: "vf-card",
19+
path: "/vf-react/components/vf-card",
20+
description: "vf-card"
21+
},
22+
{
23+
name: "vf-blockquote",
24+
path: "/vf-react/components/vf-blockquote",
25+
description: "vf-blockquote"
26+
},
27+
{
28+
name: "vf-hero",
29+
path: "/vf-react/components/vf-hero",
30+
description: "vf-hero"
31+
},
32+
{
33+
name: "vf-banner",
34+
path: "/vf-react/components/vf-banner",
35+
description: "vf-banner"
36+
},
37+
{
38+
name: "vf-tabs",
39+
path: "/vf-react/components/vf-tabs",
40+
description: "vf-tabs"
41+
},
42+
{
43+
name: "chatbot",
44+
path: "/vf-react/chatbot",
45+
description: "chatbot"
46+
}
47+
];
48+
49+
export function searchComponents(rawQuery) {
50+
const query = (rawQuery || "").trim().toLowerCase();
51+
52+
if (!query) {
53+
return [];
54+
}
55+
56+
return componentSearchIndex.filter((component) => {
57+
const haystack = [component.name, component.description]
58+
.join(" ")
59+
.toLowerCase();
60+
61+
return haystack.includes(query);
62+
});
63+
}

0 commit comments

Comments
 (0)