Skip to content

Commit 8d4b512

Browse files
authored
fix: panel position in positioned container (#763) (#1336)
* fix: panel position in positioned container (#763) * docs(examples): add example for positioned container
1 parent c67126b commit 8d4b512

11 files changed

Lines changed: 356 additions & 74 deletions

File tree

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Autocomplete panel placement in positioned container example
2+
3+
This example shows how to use Autocomplete's [`panelPlacement` parameter](https://www.algolia.com/doc/ui-libraries/autocomplete/api-reference/autocomplete-js/autocomplete/#param-panelplacement)
4+
within a positioned container.
5+
6+
7+
<p align="center"><img src="capture.jpg?raw=true" alt="A capture of the Autocomplete placement demo" /></p>
8+
9+
## Demo
10+
11+
[Access the demo](https://codesandbox.io/s/github/algolia/autocomplete/tree/next/examples/panel-placement-positioned)
12+
13+
## How to run this example locally
14+
15+
### 1. Clone this repository
16+
17+
```sh
18+
git clone git@github.com:algolia/autocomplete.git
19+
```
20+
21+
### 2. Install the dependencies and run the server
22+
23+
```sh
24+
yarn
25+
yarn workspace @algolia/autocomplete-example-panel-placement-positioned start
26+
```
27+
28+
Alternatively, you may use npm:
29+
30+
```sh
31+
cd examples/panel-placement-positioned
32+
npm install
33+
npm start
34+
```
35+
36+
Open <http://localhost:1234> to see your app.
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/** @jsxRuntime classic */
2+
/** @jsx h */
3+
import {
4+
autocomplete,
5+
AutocompleteComponents,
6+
AutocompleteOptions,
7+
getAlgoliaResults,
8+
GetSources,
9+
} from '@algolia/autocomplete-js';
10+
import { Hit } from '@algolia/client-search';
11+
import algoliasearch from 'algoliasearch/lite';
12+
import { h } from 'preact';
13+
14+
import '@algolia/autocomplete-theme-classic';
15+
16+
const appId = 'latency';
17+
const apiKey = '6be0576ff61c053d5f9a3225e2a90f76';
18+
const searchClient = algoliasearch(appId, apiKey);
19+
20+
type AutocompleteItem = Hit<{
21+
brand: string;
22+
categories: string[];
23+
description: string;
24+
image: string;
25+
name: string;
26+
price: number;
27+
rating: number;
28+
type: string;
29+
url: string;
30+
}>;
31+
32+
const getSources: GetSources<AutocompleteItem> = ({ query }) => {
33+
return [
34+
{
35+
sourceId: 'products',
36+
getItems() {
37+
return getAlgoliaResults<AutocompleteItem>({
38+
searchClient,
39+
queries: [
40+
{
41+
indexName: 'instant_search',
42+
query,
43+
},
44+
],
45+
});
46+
},
47+
templates: {
48+
item({ item, components }) {
49+
return <ProductItem item={item} components={components} />;
50+
},
51+
noResults() {
52+
return 'No products matching.';
53+
},
54+
},
55+
},
56+
];
57+
};
58+
59+
const search = autocomplete<AutocompleteItem>({
60+
container: '#autocomplete',
61+
panelContainer: '.parent',
62+
placeholder: 'Search',
63+
getSources,
64+
insights: true,
65+
});
66+
67+
const searchLeft = autocomplete<AutocompleteItem>({
68+
container: '#autocomplete-left',
69+
panelContainer: '.parent',
70+
placeholder: 'Search',
71+
getSources,
72+
insights: true,
73+
});
74+
75+
const searchRight = autocomplete<AutocompleteItem>({
76+
container: '#autocomplete-right',
77+
panelContainer: '.parent',
78+
placeholder: 'Search',
79+
getSources,
80+
insights: true,
81+
});
82+
83+
type ProductItemProps = {
84+
item: AutocompleteItem;
85+
components: AutocompleteComponents;
86+
};
87+
88+
const ProductItem = ({ item, components }: ProductItemProps) => (
89+
<a href={item.url} className="aa-ItemLink">
90+
<div className="aa-ItemContent">
91+
<div className="aa-ItemIcon aa-ItemIcon--picture aa-ItemIcon--alignTop">
92+
<img src={item.image} alt={item.name} width="40" height="40" />
93+
</div>
94+
95+
<div className="aa-ItemContentBody">
96+
<div className="aa-ItemContentTitle">
97+
<components.ReverseHighlight hit={item} attribute="name" />
98+
</div>
99+
<div className="aa-ItemContentDescription">
100+
By <strong>{item.brand}</strong> in{' '}
101+
<strong>{item.categories[0]}</strong>
102+
</div>
103+
</div>
104+
</div>
105+
</a>
106+
);
107+
108+
document
109+
.querySelectorAll<HTMLInputElement>('input[name="placement"]')
110+
.forEach((radio) => {
111+
radio.addEventListener('change', (event) => {
112+
const target = event.target as HTMLInputElement;
113+
const panelPlacement = target.value as Required<
114+
AutocompleteOptions<AutocompleteItem>['panelPlacement']
115+
>;
116+
117+
search.update({ panelPlacement });
118+
searchLeft.update({ panelPlacement });
119+
searchRight.update({ panelPlacement });
120+
});
121+
});
288 KB
Loading
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import * as preact from 'preact';
2+
3+
// Parcel picks the `source` field of the monorepo packages and thus doesn't
4+
// apply the Babel config. We therefore need to manually override the constants
5+
// in the app, as well as the React pragmas.
6+
// See https://twitter.com/devongovett/status/1134231234605830144
7+
(global as any).__DEV__ = process.env.NODE_ENV !== 'production';
8+
(global as any).__TEST__ = false;
9+
(global as any).h = preact.h;
10+
(global as any).React = preact;
43.1 KB
Loading
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<html lang="en">
2+
<head>
3+
<meta charset="UTF-8" />
4+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
5+
6+
<link rel="shortcut icon" href="favicon.png" type="image/x-icon" />
7+
<link rel="stylesheet" href="style.css" />
8+
9+
<title>Panel placement | Autocomplete</title>
10+
</head>
11+
12+
<body>
13+
<div class="parent" style="left: 50px; right: 50px; top: 50px; bottom: 50px; padding: 16px; border: 3px solid black; position: absolute">
14+
<form>
15+
Panel placement:
16+
<input
17+
type="radio"
18+
value="input-wrapper-width"
19+
name="placement"
20+
checked
21+
/>
22+
<label for="input-wrapper-width">input-wrapper-width</label>
23+
<input type="radio" value="start" name="placement" />
24+
<label for="start">start</label>
25+
<input type="radio" value="end" name="placement" />
26+
<label for="end">end</label>
27+
<input type="radio" value="full-width" name="placement" />
28+
<label for="full-width">full-width</label>
29+
</form>
30+
31+
<div class="container">
32+
<div id="autocomplete-left"></div>
33+
<div id="autocomplete"></div>
34+
<div id="autocomplete-right"></div>
35+
</div>
36+
</div>
37+
38+
<script type="module" src="env.ts"></script>
39+
<script type="module" src="app.tsx"></script>
40+
</body>
41+
</html>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"name": "@algolia/autocomplete-example-panel-placement-positioned",
3+
"description": "Autocomplete panel placement example in positioned containers",
4+
"version": "1.19.6",
5+
"private": true,
6+
"license": "MIT",
7+
"scripts": {
8+
"build": "parcel build index.html",
9+
"start": "parcel index.html"
10+
},
11+
"dependencies": {
12+
"@algolia/autocomplete-core": "1.19.6",
13+
"@algolia/autocomplete-js": "1.19.6",
14+
"@algolia/autocomplete-theme-classic": "1.19.6",
15+
"algoliasearch": "4.16.0",
16+
"preact": "10.13.2"
17+
},
18+
"devDependencies": {
19+
"@algolia/client-search": "4.16.0",
20+
"parcel": "2.8.3"
21+
},
22+
"keywords": [
23+
"algolia",
24+
"autocomplete",
25+
"javascript"
26+
]
27+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
* {
2+
box-sizing: border-box;
3+
}
4+
5+
body {
6+
background-color: rgb(244, 244, 249);
7+
color: rgb(65, 65, 65);
8+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
9+
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
10+
sans-serif;
11+
-webkit-font-smoothing: antialiased;
12+
-moz-osx-font-smoothing: grayscale;
13+
padding: 1rem;
14+
}
15+
16+
.container {
17+
margin: 0 auto;
18+
width: 100%;
19+
display: grid;
20+
grid-template-columns: 400px 1fr 400px;
21+
grid-gap: 10px;
22+
}
23+
24+
.action {
25+
align-content: center;
26+
}

0 commit comments

Comments
 (0)