Skip to content

Commit 0db12f3

Browse files
authored
feat(React InstantSearch Hooks): introduce range slider example with React Spectrum (#457)
1 parent b00fb98 commit 0db12f3

File tree

12 files changed

+11436
-0
lines changed

12 files changed

+11436
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# dependencies
4+
/node_modules
5+
/.pnp
6+
.pnp.js
7+
8+
# testing
9+
/coverage
10+
11+
# production
12+
/build
13+
14+
# misc
15+
.DS_Store
16+
.env.local
17+
.env.development.local
18+
.env.test.local
19+
.env.production.local
20+
21+
npm-debug.log*
22+
yarn-debug.log*
23+
yarn-error.log*
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# range-slider-with-react-spectrum
2+
3+
_This project was generated with [create-instantsearch-app](https://github.com/algolia/create-instantsearch-app) by [Algolia](https://algolia.com)._
4+
5+
## Get started
6+
7+
To run this project locally, install the dependencies and run the local server:
8+
9+
```sh
10+
npm install
11+
npm start
12+
```
13+
14+
Alternatively, you may use [Yarn](https://http://yarnpkg.com/):
15+
16+
```sh
17+
yarn
18+
yarn start
19+
```
20+
21+
Open http://localhost:3000 to see your app.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"name": "range-slider-with-react-spectrum",
3+
"version": "0.1.0",
4+
"private": true,
5+
"dependencies": {
6+
"@adobe/react-spectrum": "3.28.0",
7+
"algoliasearch": "^4.13.0",
8+
"instantsearch.css": "^7.4.5",
9+
"react": "^18.1.0",
10+
"react-dom": "^18.1.0",
11+
"react-instantsearch-hooks-web": "6.43.0",
12+
"react-scripts": "5.0.1"
13+
},
14+
"scripts": {
15+
"start": "react-scripts start",
16+
"build": "react-scripts build"
17+
},
18+
"eslintConfig": {
19+
"extends": [
20+
"react-app",
21+
"react-app/jest"
22+
]
23+
},
24+
"browserslist": {
25+
"production": [
26+
">0.2%",
27+
"not dead",
28+
"not op_mini all"
29+
],
30+
"development": [
31+
"last 1 chrome version",
32+
"last 1 firefox version",
33+
"last 1 safari version"
34+
]
35+
}
36+
}
Loading
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
7+
<meta name="theme-color" content="#000000">
8+
9+
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.png">
10+
11+
<!--
12+
Do not use @7 in production, use a complete version like x.x.x, see website for latest version:
13+
https://community.algolia.com/react-instantsearch/Getting_started.html#load-the-algolia-theme
14+
-->
15+
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/instantsearch.css@7/themes/algolia-min.css">
16+
17+
<title>range-slider-with-react-spectrum</title>
18+
</head>
19+
20+
<body>
21+
<noscript>
22+
You need to enable JavaScript to run this app.
23+
</noscript>
24+
25+
<div id="root"></div>
26+
</body>
27+
28+
</html>
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
em {
2+
background: cyan;
3+
font-style: normal;
4+
}
5+
6+
.header {
7+
display: flex;
8+
align-items: center;
9+
min-height: 50px;
10+
padding: 0.5rem 1rem;
11+
background-image: linear-gradient(to right, #8e43e7, #00aeff);
12+
color: #fff;
13+
margin-bottom: 1rem;
14+
}
15+
16+
.header a {
17+
color: #fff;
18+
text-decoration: none;
19+
}
20+
21+
.header-title {
22+
font-size: 1.2rem;
23+
font-weight: normal;
24+
}
25+
26+
.header-title::after {
27+
content: ' ▸ ';
28+
padding: 0 0.5rem;
29+
}
30+
31+
.header-subtitle {
32+
font-size: 1.2rem;
33+
}
34+
35+
.container {
36+
max-width: 1200px;
37+
margin: 0 auto;
38+
padding: 1rem;
39+
}
40+
41+
.search-panel {
42+
display: flex;
43+
}
44+
45+
.search-panel__filters {
46+
flex: 1;
47+
margin-right: 2rem;
48+
}
49+
50+
.search-panel__results {
51+
flex: 3;
52+
}
53+
54+
.searchbox {
55+
margin-bottom: 2rem;
56+
}
57+
58+
.pagination {
59+
margin: 2rem auto;
60+
text-align: center;
61+
}
62+
63+
.ais-RefinementList {
64+
margin-bottom: 2rem;
65+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import {
2+
Hits,
3+
InstantSearch,
4+
Pagination,
5+
RefinementList,
6+
SearchBox,
7+
} from 'react-instantsearch-hooks-web';
8+
import algoliasearch from 'algoliasearch/lite';
9+
10+
import { RangeSlider } from './RangeSlider';
11+
12+
import './App.css';
13+
14+
const searchClient = algoliasearch(
15+
'B1G2GM9NG0',
16+
'aadef574be1f9252bb48d4ea09b5cfe5'
17+
);
18+
19+
function App() {
20+
return (
21+
<div className="container">
22+
<InstantSearch
23+
searchClient={searchClient}
24+
indexName="demo_ecommerce"
25+
insights={true}
26+
>
27+
<div className="search-panel">
28+
<div className="search-panel__filters">
29+
<RefinementList attribute="brand" />
30+
<RangeSlider attribute="price" />
31+
</div>
32+
33+
<div className="search-panel__results">
34+
<SearchBox className="searchbox" placeholder="Search" />
35+
<Hits />
36+
37+
<div className="pagination">
38+
<Pagination />
39+
</div>
40+
</div>
41+
</div>
42+
</InstantSearch>
43+
</div>
44+
);
45+
}
46+
47+
export default App;
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
[class^='spectrum-Slider_'] {
2+
width: 100% !important;
3+
}
4+
5+
[class^='spectrum-Slider-labelContainer'] {
6+
margin-bottom: 1rem;
7+
}
8+
9+
[class^='spectrum-Slider-value'] {
10+
width: auto !important;
11+
min-width: 0 !important;
12+
}
13+
14+
[class^='spectrum-Slider-track'] {
15+
background-color: #dfe2ee;
16+
height: 3px;
17+
border-radius: 9999px;
18+
}
19+
20+
[class^='spectrum-Slider-track']:last-of-type {
21+
right: 0;
22+
}
23+
24+
[class^='spectrum-Slider-track']:nth-of-type(3) {
25+
background-color: #3a4570;
26+
}
27+
28+
[class^='spectrum-Slider-handle'] {
29+
display: block;
30+
width: 20px;
31+
height: 20px;
32+
margin-top: 1px;
33+
background-color: #fff;
34+
border: 1px solid #c4c8d8;
35+
box-shadow: 0 2px 5px 0 #e3e5ec;
36+
border-radius: 9999px;
37+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { useEffect, useState } from 'react';
2+
import { useRange } from 'react-instantsearch-hooks-web';
3+
import { RangeSlider as SpectrumRangeSlider } from '@adobe/react-spectrum';
4+
5+
import './RangeSlider.css';
6+
7+
export function RangeSlider(props) {
8+
const { start, range, canRefine, refine } = useRange(props);
9+
const { min, max } = range;
10+
const [value, setValue] = useState({ start: min, end: max });
11+
12+
const from = Math.max(min, Number.isFinite(start[0]) ? start[0] : min);
13+
const to = Math.min(max, Number.isFinite(start[1]) ? start[1] : max);
14+
15+
useEffect(() => {
16+
setValue({ start: from, end: to });
17+
}, [from, to]);
18+
19+
return (
20+
<SpectrumRangeSlider
21+
label="Price range"
22+
minValue={min}
23+
maxValue={max}
24+
value={value}
25+
onChange={setValue}
26+
onChangeEnd={({ start, end }) => refine([start, end])}
27+
isDisabled={!canRefine}
28+
/>
29+
);
30+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
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+
}

0 commit comments

Comments
 (0)