Skip to content

Commit 9bf41e2

Browse files
francoischalifourShipowsarahdayan
authored
feat(theme): patch theme (#497)
* feat(theme): patch theme Co-authored-by: Kevin Granger <[email protected]> * feat: convert CSS color vars to RGB and alpha tuples * feat: remove capitalize on header * feat: rename columns CSS classes * fix: fix scrollable class case * chore: update comments * fix: rename ItemIcon CSS modifiers * fix: fix DetachedContainer modal CSS modifier case * chore: improve stylelint config * chore: update comments * chore: run lint * chore(examples): update icon class * fix: remove `aa-key-shadow` var * feat: use base `z-index` var * refactor: update CSS vars descriptions * docs: update comments * fix: inherit font family * fix: use CSS vars for font-weight * fix: extract description mark to CSS var * feat: design scrollbar * fix: edit spacing and alignments * feat: design products * fix: fix bottom scroll on Safari mobile * fix: fix stuck hover state issue on Safari mobile * chore(examples): set `categoriesPerItem` to 2 * chore: increase bundle size * fix: give full opacity to scroll bar * docs(examples): update playground products Co-authored-by: Kevin Granger <[email protected]> Co-authored-by: Sarah Dayan <[email protected]>
1 parent e3df81e commit 9bf41e2

24 files changed

Lines changed: 941 additions & 401 deletions

File tree

.stylelintrc.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@
1313
"rules": {
1414
"order/properties-alphabetical-order": true,
1515
"no-descending-specificity": null,
16-
"selector-class-pattern": ["^aa-[A-Za-z0-9-]*$"],
16+
"selector-class-pattern": [
17+
"^aa-(?:[A-Z][a-z]+)+(?:--[a-z]+(?:[A-Z][a-z]+)?)?$"
18+
],
1719
"prettier/prettier": true,
1820
"max-nesting-depth": null,
1921
"rule-empty-line-before": [

bundlesize.config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
{
2424
"path": "packages/autocomplete-plugin-query-suggestions/dist/umd/index.production.js",
2525
"maxSize": "4 kB"
26+
},
27+
{
28+
"path": "packages/autocomplete-theme-classic/dist/theme.css",
29+
"maxSize": "4.25 kB"
2630
}
2731
]
2832
}

cypress/test-apps/js/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ type ProductItemProps = {
131131
function ProductItem({ hit, insights, components }: ProductItemProps) {
132132
return (
133133
<Fragment>
134-
<div className="aa-ItemIcon aa-ItemIcon--align-top">
134+
<div className="aa-ItemIcon aa-ItemIcon--alignTop">
135135
<img src={hit.image} alt={hit.name} width="40" height="40" />
136136
</div>
137137
<div className="aa-ItemContent">

cypress/test-apps/js/categoriesPlugin.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export function createCategoriesPlugin({
5454
item({ item, components }) {
5555
return (
5656
<Fragment>
57-
<div className="aa-ItemIcon aa-ItemIcon--no-border">
57+
<div className="aa-ItemIcon aa-ItemIcon--noBorder">
5858
<svg
5959
viewBox="0 0 24 24"
6060
width="18"

examples/playground/app.tsx

Lines changed: 155 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const querySuggestionsPlugin = createQuerySuggestionsPlugin({
4545
'exact_matches',
4646
'categories',
4747
],
48+
categoriesPerItem: 2,
4849
});
4950
const categoriesPlugin = createCategoriesPlugin({ searchClient });
5051

@@ -82,6 +83,16 @@ autocomplete({
8283
},
8384
},
8485
],
86+
}).then(([hits]) => {
87+
return hits.map((hit) => ({
88+
...hit,
89+
comments: hit.popularity % 100,
90+
sale: hit.free_shipping,
91+
// eslint-disable-next-line @typescript-eslint/camelcase
92+
sale_price: hit.free_shipping
93+
? (hit.price - hit.price / 10).toFixed(2)
94+
: hit.price,
95+
}));
8596
});
8697
},
8798
templates: {
@@ -122,24 +133,159 @@ type ProductItemProps = {
122133
function ProductItem({ hit, insights, components }: ProductItemProps) {
123134
return (
124135
<Fragment>
125-
<div className="aa-ItemIcon aa-ItemIcon--align-top">
126-
<img src={hit.image} alt={hit.name} width="40" height="40" />
127-
</div>
128136
<div className="aa-ItemContent">
129-
<div className="aa-ItemContentTitle">
130-
<components.Snippet hit={hit} attribute="name" />
137+
<div className="aa-ItemVisual aa-ItemIcon aa-ItemIcon--alignTop">
138+
<img src={hit.image} alt={hit.name} width="40" height="40" />
131139
</div>
132-
<div className="aa-ItemContentDescription">
133-
<components.Snippet hit={hit} attribute="description" />
140+
141+
<div className="aa-ItemContentBody">
142+
<div className="aa-ItemContentTitle">
143+
<components.Snippet hit={hit} attribute="name" />
144+
</div>
145+
<div className="aa-ItemContentDescription">
146+
By <strong>{hit.brand}</strong> in{' '}
147+
<strong>{hit.categories[0]}</strong>
148+
</div>
149+
150+
<div
151+
className="aa-ItemContentDescription"
152+
style={{
153+
display: 'grid',
154+
gridAutoFlow: 'column',
155+
justifyContent: 'start',
156+
alignItems: 'center',
157+
gap: 8,
158+
}}
159+
>
160+
{hit.rating > 0 && (
161+
<div className="aa-ItemContentDescription">
162+
<div
163+
style={{
164+
color: 'rgba(var(--aa-muted-color-rgb), 0.5)',
165+
}}
166+
>
167+
{Array.from({ length: 5 }, (_value, index) => {
168+
const isFilled = hit.rating >= index + 1;
169+
170+
return (
171+
<svg
172+
key={index}
173+
width="16"
174+
height="16"
175+
viewBox="0 0 24 24"
176+
fill={isFilled ? 'currentColor' : 'none'}
177+
stroke="currentColor"
178+
strokeWidth="1"
179+
strokeLinecap="round"
180+
strokeLinejoin="round"
181+
>
182+
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" />
183+
</svg>
184+
);
185+
})}
186+
</div>
187+
</div>
188+
)}
189+
<div
190+
style={{
191+
display: 'grid',
192+
gridAutoFlow: 'column',
193+
justifyContent: 'start',
194+
alignItems: 'center',
195+
gap: 4,
196+
}}
197+
>
198+
<svg
199+
width="16"
200+
height="16"
201+
viewBox="0 0 24 24"
202+
fill="none"
203+
stroke="currentColor"
204+
strokeWidth="2"
205+
strokeLinecap="round"
206+
strokeLinejoin="round"
207+
style={{
208+
position: 'relative',
209+
top: '1px',
210+
}}
211+
>
212+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path>
213+
</svg>
214+
<span>{hit.comments.toLocaleString()}</span>
215+
</div>
216+
</div>
217+
218+
<div
219+
style={{
220+
display: 'flex',
221+
alignItems: 'center',
222+
gap: 8,
223+
}}
224+
>
225+
<div
226+
style={{
227+
display: 'grid',
228+
gridAutoFlow: 'column',
229+
justifyContent: 'start',
230+
alignItems: 'center',
231+
gap: 4,
232+
}}
233+
>
234+
<div>
235+
<span
236+
style={{
237+
color: '#000',
238+
fontSize: '0.9em',
239+
fontWeight: 'bold',
240+
}}
241+
>
242+
${hit.sale_price.toLocaleString()}
243+
</span>{' '}
244+
{hit.sale && (
245+
<span
246+
style={{
247+
color: 'rgb(var(--aa-muted-color-rgb))',
248+
fontSize: '0.9em',
249+
textDecoration: 'line-through',
250+
}}
251+
>
252+
${hit.price.toLocaleString()}
253+
</span>
254+
)}
255+
</div>
256+
{hit.sale && (
257+
<span
258+
style={{
259+
textTransform: 'uppercase',
260+
fontSize: '0.64em',
261+
background: '#539753',
262+
color: '#fff',
263+
fontWeight: 600,
264+
borderRadius: 9999,
265+
padding: '2px 6px',
266+
display: 'inline-block',
267+
lineHeight: '1.25em',
268+
}}
269+
>
270+
On sale
271+
</span>
272+
)}
273+
</div>
274+
</div>
134275
</div>
135276
</div>
277+
136278
<div className="aa-ItemActions">
137279
<button
138280
className="aa-ItemActionButton aa-TouchOnly aa-ActiveOnly"
139281
type="button"
140282
title="Select"
283+
disabled={true}
284+
style={{
285+
pointerEvents: 'none',
286+
}}
141287
>
142-
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor">
288+
<svg viewBox="0 0 24 24" fill="currentColor">
143289
<path d="M18.984 6.984h2.016v6h-15.188l3.609 3.609-1.406 1.406-6-6 6-6 1.406 1.406-3.609 3.609h13.172v-4.031z" />
144290
</svg>
145291
</button>
@@ -159,7 +305,7 @@ function ProductItem({ hit, insights, components }: ProductItemProps) {
159305
});
160306
}}
161307
>
162-
<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor">
308+
<svg viewBox="0 0 24 24" fill="currentColor">
163309
<path d="M19 5h-14l1.5-2h11zM21.794 5.392l-2.994-3.992c-0.196-0.261-0.494-0.399-0.8-0.4h-12c-0.326 0-0.616 0.156-0.8 0.4l-2.994 3.992c-0.043 0.056-0.081 0.117-0.111 0.182-0.065 0.137-0.096 0.283-0.095 0.426v14c0 0.828 0.337 1.58 0.879 2.121s1.293 0.879 2.121 0.879h14c0.828 0 1.58-0.337 2.121-0.879s0.879-1.293 0.879-2.121v-14c0-0.219-0.071-0.422-0.189-0.585-0.004-0.005-0.007-0.010-0.011-0.015zM4 7h16v13c0 0.276-0.111 0.525-0.293 0.707s-0.431 0.293-0.707 0.293h-14c-0.276 0-0.525-0.111-0.707-0.293s-0.293-0.431-0.293-0.707zM15 10c0 0.829-0.335 1.577-0.879 2.121s-1.292 0.879-2.121 0.879-1.577-0.335-2.121-0.879-0.879-1.292-0.879-2.121c0-0.552-0.448-1-1-1s-1 0.448-1 1c0 1.38 0.561 2.632 1.464 3.536s2.156 1.464 3.536 1.464 2.632-0.561 3.536-1.464 1.464-2.156 1.464-3.536c0-0.552-0.448-1-1-1s-1 0.448-1 1z" />
164310
</svg>
165311
</button>

examples/playground/categoriesPlugin.tsx

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export function createCategoriesPlugin({
3636
params: {
3737
facetName: 'categories',
3838
facetQuery: query,
39-
maxFacetHits: query ? 3 : 10,
39+
maxFacetHits: query ? 3 : 5,
4040
},
4141
},
4242
],
@@ -58,23 +58,24 @@ export function createCategoriesPlugin({
5858
item({ item, components }) {
5959
return (
6060
<Fragment>
61-
<div className="aa-ItemIcon aa-ItemIcon--no-border">
62-
<svg
63-
viewBox="0 0 24 24"
64-
width="18"
65-
height="18"
66-
fill="none"
67-
stroke="currentColor"
68-
strokeWidth="2"
69-
strokeLinecap="round"
70-
strokeLinejoin="round"
71-
>
72-
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
73-
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
74-
<line x1="12" y1="22.08" x2="12" y2="12" />
75-
</svg>
76-
</div>
7761
<div className="aa-ItemContent">
62+
<div className="aa-ItemIcon aa-ItemIcon--noBorder">
63+
<svg
64+
viewBox="0 0 24 24"
65+
width="18"
66+
height="18"
67+
fill="none"
68+
stroke="currentColor"
69+
strokeWidth="2"
70+
strokeLinecap="round"
71+
strokeLinejoin="round"
72+
>
73+
<path d="M21 16V8a2 2 0 0 0-1-1.73l-7-4a2 2 0 0 0-2 0l-7 4A2 2 0 0 0 3 8v8a2 2 0 0 0 1 1.73l7 4a2 2 0 0 0 2 0l7-4A2 2 0 0 0 21 16z" />
74+
<polyline points="3.27 6.96 12 12.01 20.73 6.96" />
75+
<line x1="12" y1="22.08" x2="12" y2="12" />
76+
</svg>
77+
</div>
78+
7879
<div className="aa-ItemContentTitle">
7980
<components.Highlight hit={item} attribute="label" />
8081
</div>

examples/playground/shortcutsPlugin.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ export const shortcutsPlugin: AutocompletePlugin<DarkModeItem, undefined> = {
7878
return createElement(
7979
Fragment,
8080
{},
81-
createElement(
82-
'div',
83-
{ className: 'aa-ItemIcon' },
84-
isDarkThemeSelected() ? lightIcon : darkIcon
85-
),
8681
createElement(
8782
'div',
8883
{ className: 'aa-ItemContent' },
84+
createElement(
85+
'div',
86+
{ className: 'aa-ItemIcon' },
87+
isDarkThemeSelected() ? lightIcon : darkIcon
88+
),
8989
createElement(
9090
'div',
9191
{ className: 'aa-ItemContentTitle' },

examples/playground/types/ProductHit.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Hit } from '@algolia/client-search';
33
export type ProductRecord = {
44
brand: string;
55
categories: string[];
6+
comments: number;
67
description: string;
78
free_shipping: boolean;
89
hierarchicalCategories: {
@@ -20,6 +21,8 @@ export type ProductRecord = {
2021
price: number;
2122
prince_range: string;
2223
rating: number;
24+
sale: boolean;
25+
sale_price: number;
2326
type: string;
2427
};
2528

examples/query-suggestions-with-hits/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ type ProductItemProps = {
114114
function ProductItem({ hit, insights, components }: ProductItemProps) {
115115
return (
116116
<Fragment>
117-
<div className="aa-ItemIcon aa-ItemIcon--align-top">
117+
<div className="aa-ItemIcon aa-ItemIcon--alignTop">
118118
<img src={hit.image} alt={hit.name} width="40" height="40" />
119119
</div>
120120
<div className="aa-ItemContent">

examples/query-suggestions-with-inline-categories/app.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ const querySuggestionsPlugin = createQuerySuggestionsPlugin({
3333
item({ item, components }) {
3434
return (
3535
<Fragment>
36-
<div className="aa-ItemIcon aa-ItemIcon--no-border">
36+
<div className="aa-ItemIcon aa-ItemIcon--noBorder">
3737
<svg
3838
viewBox="0 0 24 24"
3939
width="18"

0 commit comments

Comments
 (0)