Skip to content

Commit

Permalink
feat(react-instantsearch): add Carousel layout component (#6321)
Browse files Browse the repository at this point in the history
  • Loading branch information
shaejaz authored Aug 19, 2024
1 parent 62b6e4b commit 41b0c96
Show file tree
Hide file tree
Showing 25 changed files with 1,570 additions and 55 deletions.
2 changes: 1 addition & 1 deletion bundlesize.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
},
{
"path": "packages/react-instantsearch/dist/umd/ReactInstantSearch.min.js",
"maxSize": "64 kB"
"maxSize": "64.5 kB"
},
{
"path": "packages/vue-instantsearch/vue2/umd/index.js",
Expand Down
9 changes: 0 additions & 9 deletions examples/react/getting-started/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@

<link rel="shortcut icon" href="favicon.png" />

<!--
Do not use @8 in production, use a complete version like x.x.x, see website for latest version:
https://www.algolia.com/doc/guides/building-search-ui/installation/js/#load-the-styles
-->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/instantsearch.css@8/themes/satellite-min.css"
/>

<title>React InstantSearch — Getting started</title>
</head>

Expand Down
1 change: 1 addition & 0 deletions examples/react/getting-started/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"dependencies": {
"algoliasearch": "4.23.2",
"instantsearch.js": "4.73.4",
"instantsearch.css": "8.4.0",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-instantsearch": "7.12.4"
Expand Down
9 changes: 0 additions & 9 deletions examples/react/getting-started/products.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@

<link rel="shortcut icon" href="favicon.png" />

<!--
Do not use @8 in production, use a complete version like x.x.x, see website for latest version:
https://www.algolia.com/doc/guides/building-search-ui/installation/js/#load-the-styles
-->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/instantsearch.css@8/themes/satellite-min.css"
/>

<title>React InstantSearch — Getting started</title>
</head>

Expand Down
67 changes: 60 additions & 7 deletions examples/react/getting-started/src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -87,16 +87,22 @@ em {
flex-shrink: 0;
}

.ais-TrendingItems-list,
.ais-RelatedProducts-list {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
}

.ais-TrendingItems-item,
.ais-RelatedProducts-item {
background: none !important;
align-items: stretch !important;
padding: 0 !important;
box-shadow: none !important;
}

.ais-TrendingItems-item > div,
.ais-RelatedProducts-item > div {
align-items: start;
background: #fff;
align-items: center;
padding: 1.5rem;
display: flex;
box-shadow: 0 0 0 1px #23263b0d, 0 1px 3px #23263b26;
}

.ais-TrendingItems-item img,
Expand All @@ -113,3 +119,50 @@ em {
height: 100%;
justify-content: space-between;
}

.ais-TrendingItems-item h2,
.ais-RelatedProducts-item h2 {
display: -webkit-box;
-webkit-line-clamp: 4;
-webkit-box-orient: vertical;
overflow: hidden;
line-height: 1.2;
}

.ais-Carousel-item {
padding: 0.5rem !important;
}

.ais-Carousel-list {
margin: -0.5rem !important;
grid-auto-columns: calc(22% - 0.5rem) !important;
}

.ais-Carousel::before,
.ais-Carousel::after {
position: absolute;
top: 0;
bottom: 0;
width: 0.5rem;
display: block;
background: rgb(255, 255, 255);
content: '';
}

.ais-Carousel::before {
left: -0.5rem;
background: linear-gradient(
90deg,
rgba(255, 255, 255, 1) 0%,
rgba(255, 255, 255, 0) 100%
);
}

.ais-Carousel::after {
right: -0.5rem;
background: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0%,
rgba(255, 255, 255, 1) 100%
);
}
24 changes: 16 additions & 8 deletions examples/react/getting-started/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,13 @@ import {
RefinementList,
SearchBox,
TrendingItems,
Carousel,
} from 'react-instantsearch';

import { Panel } from './Panel';

import './App.css';
import 'instantsearch.css/themes/satellite.css';

const searchClient = algoliasearch(
'latency',
Expand Down Expand Up @@ -58,7 +60,11 @@ export function App() {
<Pagination />
</div>
<div>
<TrendingItems itemComponent={ItemComponent} limit={4} />
<TrendingItems
itemComponent={ItemComponent}
limit={6}
layoutComponent={Carousel}
/>
</div>
</div>
</div>
Expand Down Expand Up @@ -92,12 +98,14 @@ function HitComponent({ hit }: { hit: HitType }) {

function ItemComponent({ item }: { item: Hit }) {
return (
<article>
<div>
<img src={item.image} />
<h2>{item.name}</h2>
</div>
<a href={`/products.html?pid=${item.objectID}`}>See product</a>
</article>
<div>
<article>
<div>
<img src={item.image} />
<h2>{item.name}</h2>
</div>
<a href={`/products.html?pid=${item.objectID}`}>See product</a>
</article>
</div>
);
}
21 changes: 13 additions & 8 deletions examples/react/getting-started/src/Product.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ import {
Hits,
InstantSearch,
RelatedProducts,
Carousel,
} from 'react-instantsearch';

import './App.css';
import 'instantsearch.css/themes/satellite.css';

const searchClient = algoliasearch(
'latency',
Expand Down Expand Up @@ -48,7 +50,8 @@ export function Product({ pid }: { pid: string }) {
itemComponent={ItemComponent}
emptyComponent={() => <></>}
objectIDs={[pid]}
limit={4}
limit={6}
layoutComponent={Carousel}
/>
</InstantSearch>
</div>
Expand Down Expand Up @@ -76,12 +79,14 @@ function HitComponent({ hit }: { hit: HitType }) {

function ItemComponent({ item }: { item: HitType }) {
return (
<article>
<div>
<img src={item.image} />
<h2>{item.name}</h2>
</div>
<a href={`/products.html?pid=${item.objectID}`}>See product</a>
</article>
<div>
<article>
<div>
<img src={item.image} />
<h2>{item.name}</h2>
</div>
<a href={`/products.html?pid=${item.objectID}`}>See product</a>
</article>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ export function createFrequentlyBoughtTogetherComponent({

<Layout
classNames={cssClasses}
translations={translations}
itemComponent={ItemComponent}
items={items}
sendEvent={sendEvent}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ export function createLookingSimilarComponent({

<Layout
classNames={cssClasses}
translations={translations}
itemComponent={ItemComponent}
items={items}
sendEvent={sendEvent}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ export function createRelatedProductsComponent({

<Layout
classNames={cssClasses}
translations={translations}
itemComponent={ItemComponent}
items={items}
sendEvent={sendEvent}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ export function createTrendingItemsComponent({

<Layout
classNames={cssClasses}
translations={translations}
itemComponent={ItemComponent}
items={items}
sendEvent={sendEvent}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,14 @@

import type {
RecommendClassNames,
RecommendTranslations,
RecordWithObjectID,
Renderer,
RecommendLayoutProps,
} from '../../types';

export function createListComponent({ createElement }: Renderer) {
return function List<TItem extends RecordWithObjectID>(
userProps: RecommendLayoutProps<
TItem,
RecommendTranslations,
Partial<RecommendClassNames>
>
userProps: RecommendLayoutProps<TItem, Partial<RecommendClassNames>>
) {
const {
classNames = {},
Expand Down
3 changes: 0 additions & 3 deletions packages/instantsearch-ui-components/src/types/Recommend.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ export type RecommendTranslations = {

export type RecommendLayoutProps<
TItem extends RecordWithObjectID,
TTranslations extends Record<string, string>,
TClassNames extends Record<string, string>
> = {
classNames: TClassNames;
Expand All @@ -51,7 +50,6 @@ export type RecommendLayoutProps<
TComponentProps
) => JSX.Element;
items: TItem[];
translations: TTranslations;
sendEvent: SendEventForHits;
};

Expand All @@ -75,7 +73,6 @@ export type RecommendComponentProps<
layout?: (
props: RecommendLayoutProps<
RecordWithObjectID<TObject>,
Required<RecommendTranslations>,
Record<string, string>
> &
TComponentProps
Expand Down
36 changes: 36 additions & 0 deletions packages/react-instantsearch/src/components/Carousel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import {
createCarouselComponent,
generateCarouselId,
} from 'instantsearch-ui-components';
import React, { createElement, Fragment, useRef } from 'react';

import type {
CarouselProps as CarouselUiProps,
Pragma,
} from 'instantsearch-ui-components';

const CarouselUiComponent = createCarouselComponent({
createElement: createElement as Pragma,
Fragment,
});

export type CarouselProps<TObject extends Record<string, unknown>> = Omit<
CarouselUiProps<TObject>,
'listRef' | 'nextButtonRef' | 'previousButtonRef' | 'carouselIdRef'
>;

export function Carousel<TObject extends Record<string, unknown>>(
props: CarouselProps<TObject>
) {
const carouselRefs: Pick<
CarouselUiProps<TObject>,
'listRef' | 'nextButtonRef' | 'previousButtonRef' | 'carouselIdRef'
> = {
listRef: useRef(null),
nextButtonRef: useRef(null),
previousButtonRef: useRef(null),
carouselIdRef: useRef(generateCarouselId()),
};

return <CarouselUiComponent {...carouselRefs} {...props} />;
}
Loading

0 comments on commit 41b0c96

Please sign in to comment.