Skip to content

Commit 2b5b873

Browse files
authored
chore(javascript): add browser playground with instantsearch (#3687)
1 parent a5319e4 commit 2b5b873

File tree

14 files changed

+4349
-2068
lines changed

14 files changed

+4349
-2068
lines changed

.github/workflows/check.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ jobs:
8282
8383
if [[ $diff > 0 ]]; then
8484
echo "Build the custom github actions by running \`yarn workspace scripts build:actions\`"
85+
git status --porcelain ./scripts/ci/actions
8586
fi
8687
8788
exit $diff

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
"workspaces": [
66
"scripts/",
77
"playground/javascript/node/",
8-
"playground/javascript/browser/",
98
"eslint"
109
],
1110
"scripts": {
11+
"build": "yarn build:eslint && yarn scripts:build",
1212
"build:eslint": "yarn workspace eslint-plugin-automation-custom build && yarn install",
1313
"clean": "rm -rf **/dist **/build **/.build **/node_modules **/.gradle **/vendor **/bin **/obj **/__pycache__ || true",
1414
"cli": "yarn workspace scripts start",
Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
1+
<!DOCTYPE html>
12
<html lang="en">
23
<head>
3-
<meta charset="UTF-8" />
4-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
4+
<meta charset="utf-8" />
5+
<meta
6+
name="viewport"
7+
content="width=device-width, initial-scale=1, shrink-to-fit=no"
8+
/>
59

6-
<title>algoliasearch-client-javascript generated clients</title>
10+
<link rel="shortcut icon" href="favicon.png" />
11+
12+
<title>React InstantSearch — Getting started</title>
713
</head>
814

915
<body>
10-
<div class="container">
11-
<h1>algoliasearch-client-javascript generated clients</h1>
12-
13-
<button id="search">Click to search!</button>
16+
<noscript> You need to enable JavaScript to run this app. </noscript>
1417

15-
<div id="results"></div>
16-
</div>
18+
<div id="root"></div>
1719

18-
<script src="../../../clients/algoliasearch-client-javascript/packages/client-search/dist/client-search.umd.js"></script>
19-
<script type="module" src="app.ts"></script>
20+
<script type="module" src="src/index.tsx"></script>
2021
</body>
2122
</html>

playground/javascript/browser/package.json

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,30 @@
33
"version": "0.0.0",
44
"private": true,
55
"scripts": {
6-
"start": "parcel index.html"
6+
"build": "yarn clean && BABEL_ENV=parcel parcel build index.html products.html",
7+
"clean": "rm -rf .parcel-cache node_modules dist || true && yarn",
8+
"start": "yarn clean && BABEL_ENV=parcel parcel index.html products.html --port 3001"
79
},
810
"dependencies": {
9-
"@algolia/client-common": "link:../../../clients/algoliasearch-client-javascript/packages/client-common",
10-
"@algolia/client-search": "link:../../../clients/algoliasearch-client-javascript/packages/client-search",
11-
"@algolia/requester-browser-xhr": "link:../../../clients/algoliasearch-client-javascript/packages/requester-node-http",
12-
"algoliasearch": "link:../../../clients/algoliasearch-client-javascript/packages/algoliasearch"
11+
"algoliasearch": "link:../../../clients/algoliasearch-client-javascript/packages/algoliasearch",
12+
"instantsearch.css": "8.5.1",
13+
"instantsearch.js": "4.74.1",
14+
"react": "18.2.0",
15+
"react-dom": "18.2.0",
16+
"react-instantsearch": "7.13.1"
1317
},
1418
"devDependencies": {
15-
"parcel": "2.12.0",
16-
"typescript": "5.5.4"
19+
"@parcel/core": "2.10.0",
20+
"@parcel/packager-raw-url": "2.10.0",
21+
"@parcel/transformer-webmanifest": "2.10.0",
22+
"@types/react": "^18.0.9",
23+
"https-browserify": "^1.0.0",
24+
"parcel": "2.10.0",
25+
"stream-http": "^3.1.0",
26+
"typescript": "5.5.2",
27+
"url": "^0.11.0"
28+
},
29+
"@parcel/resolver-default": {
30+
"packageExports": true
1731
}
1832
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta
6+
name="viewport"
7+
content="width=device-width, initial-scale=1, shrink-to-fit=no"
8+
/>
9+
10+
<link rel="shortcut icon" href="favicon.png" />
11+
12+
<title>React InstantSearch — Getting started</title>
13+
</head>
14+
15+
<body>
16+
<noscript> You need to enable JavaScript to run this app. </noscript>
17+
18+
<div id="root"></div>
19+
20+
<script type="module" src="src/products.tsx"></script>
21+
</body>
22+
</html>
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
body,
2+
h1 {
3+
margin: 0;
4+
padding: 0;
5+
}
6+
7+
body {
8+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica,
9+
Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol';
10+
}
11+
12+
em {
13+
background: cyan;
14+
font-style: normal;
15+
}
16+
17+
.header {
18+
display: flex;
19+
align-items: center;
20+
min-height: 50px;
21+
padding: 0.5rem 1rem;
22+
background-image: linear-gradient(to right, #8e43e7, #00aeff);
23+
color: #fff;
24+
margin-bottom: 1rem;
25+
}
26+
27+
.header a {
28+
color: #fff;
29+
text-decoration: none;
30+
}
31+
32+
.header-title {
33+
font-size: 1.2rem;
34+
font-weight: normal;
35+
}
36+
37+
.header-title::after {
38+
content: ' ▸ ';
39+
padding: 0 0.5rem;
40+
}
41+
42+
.header-subtitle {
43+
font-size: 1.2rem;
44+
}
45+
46+
.container {
47+
max-width: 1200px;
48+
margin: 0 auto;
49+
padding: 1rem;
50+
}
51+
52+
.search-panel {
53+
display: flex;
54+
}
55+
56+
.search-panel__filters {
57+
flex: 1;
58+
}
59+
60+
.search-panel__results {
61+
flex: 3;
62+
}
63+
64+
.searchbox {
65+
margin-bottom: 2rem;
66+
}
67+
68+
.pagination {
69+
margin: 2rem auto;
70+
text-align: center;
71+
}
72+
73+
#related-products,
74+
.ais-Hits--single {
75+
margin-top: 1rem;
76+
}
77+
78+
.ais-Hits--single article {
79+
display: flex;
80+
gap: 1rem;
81+
}
82+
83+
.ais-Hits--single img {
84+
width: 150px;
85+
height: 150px;
86+
object-fit: contain;
87+
flex-shrink: 0;
88+
}
89+
90+
.ais-TrendingItems-item,
91+
.ais-RelatedProducts-item {
92+
background: none !important;
93+
align-items: stretch !important;
94+
padding: 0 !important;
95+
box-shadow: none !important;
96+
}
97+
98+
.ais-TrendingItems-item > div,
99+
.ais-RelatedProducts-item > div {
100+
align-items: start;
101+
background: #fff;
102+
align-items: center;
103+
padding: 1.5rem;
104+
display: flex;
105+
box-shadow: 0 0 0 1px #23263b0d, 0 1px 3px #23263b26;
106+
}
107+
108+
.ais-TrendingItems-item img,
109+
.ais-RelatedProducts-item img {
110+
width: 100%;
111+
height: 100px;
112+
object-fit: contain;
113+
}
114+
115+
.ais-TrendingItems-item article,
116+
.ais-RelatedProducts-item article {
117+
display: flex;
118+
flex-direction: column;
119+
height: 100%;
120+
justify-content: space-between;
121+
}
122+
123+
.ais-TrendingItems-item h2,
124+
.ais-RelatedProducts-item h2 {
125+
display: -webkit-box;
126+
-webkit-line-clamp: 4;
127+
-webkit-box-orient: vertical;
128+
overflow: hidden;
129+
line-height: 1.2;
130+
}
131+
132+
.ais-Carousel-item {
133+
padding: 0.5rem !important;
134+
}
135+
136+
.ais-Carousel-list {
137+
margin: -0.5rem !important;
138+
grid-auto-columns: calc(22% - 0.5rem) !important;
139+
}
140+
141+
.ais-Carousel::before,
142+
.ais-Carousel::after {
143+
position: absolute;
144+
top: 0;
145+
bottom: 0;
146+
width: 0.5rem;
147+
display: block;
148+
background: rgb(255, 255, 255);
149+
content: '';
150+
}
151+
152+
.ais-Carousel::before {
153+
left: -0.5rem;
154+
background: linear-gradient(
155+
90deg,
156+
rgba(255, 255, 255, 1) 0%,
157+
rgba(255, 255, 255, 0) 100%
158+
);
159+
}
160+
161+
.ais-Carousel::after {
162+
right: -0.5rem;
163+
background: linear-gradient(
164+
90deg,
165+
rgba(255, 255, 255, 0) 0%,
166+
rgba(255, 255, 255, 1) 100%
167+
);
168+
}
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
import { liteClient as algoliasearch } from 'algoliasearch/lite';
2+
import { Hit } from 'instantsearch.js';
3+
import React from 'react';
4+
import {
5+
Configure,
6+
Highlight,
7+
Hits,
8+
InstantSearch,
9+
Pagination,
10+
RefinementList,
11+
SearchBox,
12+
TrendingItems,
13+
Carousel,
14+
} from 'react-instantsearch';
15+
16+
import { Panel } from './Panel';
17+
18+
import './App.css';
19+
import 'instantsearch.css/themes/satellite.css';
20+
21+
const searchClient = algoliasearch(
22+
'latency',
23+
'6be0576ff61c053d5f9a3225e2a90f76'
24+
);
25+
26+
export function App() {
27+
return (
28+
<div>
29+
<header className="header">
30+
<h1 className="header-title">
31+
<a href="/">Getting started</a>
32+
</h1>
33+
<p className="header-subtitle">
34+
using{' '}
35+
<a href="https://github.com/algolia/instantsearch/tree/master/packages/react-instantsearch">
36+
React InstantSearch
37+
</a>
38+
</p>
39+
</header>
40+
41+
<div className="container">
42+
<InstantSearch
43+
searchClient={searchClient}
44+
indexName="instant_search"
45+
insights={true}
46+
>
47+
<Configure hitsPerPage={8} />
48+
<div className="search-panel">
49+
<div className="search-panel__filters">
50+
<Panel header="brand">
51+
<RefinementList attribute="brand" />
52+
</Panel>
53+
</div>
54+
55+
<div className="search-panel__results">
56+
<SearchBox placeholder="" className="searchbox" />
57+
<Hits hitComponent={HitComponent} />
58+
59+
<div className="pagination">
60+
<Pagination />
61+
</div>
62+
<div>
63+
<TrendingItems
64+
itemComponent={ItemComponent}
65+
limit={6}
66+
layoutComponent={Carousel}
67+
/>
68+
</div>
69+
</div>
70+
</div>
71+
</InstantSearch>
72+
</div>
73+
</div>
74+
);
75+
}
76+
77+
type HitType = Hit<{
78+
image: string;
79+
name: string;
80+
description: string;
81+
}>;
82+
83+
function HitComponent({ hit }: { hit: HitType }) {
84+
return (
85+
<article>
86+
<h1>
87+
<a href={`/products.html?pid=${hit.objectID}`}>
88+
<Highlight attribute="name" hit={hit} />
89+
</a>
90+
</h1>
91+
<p>
92+
<Highlight attribute="description" hit={hit} />
93+
</p>
94+
<a href={`/products.html?pid=${hit.objectID}`}>See product</a>
95+
</article>
96+
);
97+
}
98+
99+
function ItemComponent({ item }: { item: Hit }) {
100+
return (
101+
<div>
102+
<article>
103+
<div>
104+
<img src={item.image} />
105+
<h2>{item.name}</h2>
106+
</div>
107+
<a href={`/products.html?pid=${item.objectID}`}>See product</a>
108+
</article>
109+
</div>
110+
);
111+
}

0 commit comments

Comments
 (0)