Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backpack carousel #3059

Open
wants to merge 168 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
168 commits
Select commit Hold shift + click to select a range
e6fa988
backpack carousel
Nov 3, 2023
dc3964b
Update packages/bpk-component-carousel/README.md
R1CC1M Nov 3, 2023
419970d
Update packages/bpk-component-carousel/src/BpkCarouselContainer.modul…
R1CC1M Nov 3, 2023
54a4e82
Update packages/bpk-component-carousel/src/BpkCarouselImage.module.scss
R1CC1M Nov 3, 2023
fbb1966
add license header
R1CC1M Nov 3, 2023
91b350e
direct import
R1CC1M Nov 3, 2023
a197a5c
alt tag a11y
R1CC1M Nov 3, 2023
f6d27c5
use bpk-component-page-indicator
R1CC1M Nov 3, 2023
dea5f21
ts import bpk-component-page-indicator supression
R1CC1M Nov 3, 2023
c092d32
remove unused imports
R1CC1M Nov 3, 2023
8068214
add license header
R1CC1M Nov 3, 2023
c59f9f2
Update packages/bpk-component-carousel/README.md
R1CC1M Nov 3, 2023
324b380
visual test added
R1CC1M Nov 3, 2023
d93a115
Merge branch 'bpk-carousel' of https://github.com/Skyscanner/backpack…
R1CC1M Nov 3, 2023
d45bbaf
remove mobile breakpoint on image
R1CC1M Nov 3, 2023
30d922b
Merge branch 'main' into bpk-carousel
R1CC1M Nov 3, 2023
4c77737
regen bpk carousel image css
R1CC1M Nov 3, 2023
78735ba
Merge branch 'bpk-carousel' of https://github.com/Skyscanner/backpack…
R1CC1M Nov 3, 2023
b4e9732
ZOOT-705: 💄 Change demo images
JafferN Nov 13, 2023
0f88af4
Merge branch 'main' into bpk-carousel
JafferN Nov 13, 2023
6999c0d
Merge branch 'main' into bpk-carousel
olliecurtis Mar 14, 2024
4fe4ea2
Update bpk carousel
Kathy0208 May 27, 2024
62b8513
[NO JIRA][Github CI]: Update NPM cache generation logic (#3231)
olliecurtis Mar 14, 2024
a4a94c8
[BpkInput]: Updating input HoC for keyboard events (#3194)
olliecurtis Mar 14, 2024
9f9a914
[BpkMobileScrollContainer] Add aria label (#3281)
R1CC1M Mar 15, 2024
5779638
[BpkHorizontalNav] Add aria label (#3279)
R1CC1M Mar 15, 2024
69ced8e
[ST-5579][BpkBreakpoint] Remove react-responsive (#3284)
robaw Mar 18, 2024
6d49dad
ST-5444: Update bpk-svgs from 19.0.1 to 19.1.0 (#3294)
dominicfraser Mar 18, 2024
eb5e0d8
[NO JIRA]: Fix transpilation scripts to capture nested files (#3295)
olliecurtis Mar 18, 2024
45afce5
LOOM-1275 BkpCloseButton - Move Icon style override into span (#3283)
jronald01 Mar 19, 2024
184f0c5
Bump @percy/cli from 1.27.7 to 1.28.2 (#3291)
dependabot[bot] Mar 19, 2024
82121da
Bump @babel/core from 7.23.9 to 7.24.0 (#3286)
dependabot[bot] Mar 22, 2024
8848e2f
Bump webpack-dev-middleware from 6.1.1 to 6.1.2 (#3303)
dependabot[bot] Mar 22, 2024
2b94ca5
Creating dependabot group patterns to group deps for PRs (#3304)
olliecurtis Mar 25, 2024
7e4c4aa
[ARGG-1057]: Setup dependabot to ignore patch versions (#3296)
olliecurtis Mar 25, 2024
378b287
Use the import order defined by skyscanner to ensure consistency with…
runmoore Mar 25, 2024
db88464
Bump the babel group with 5 updates (#3313)
dependabot[bot] Mar 25, 2024
0ba2e0d
Bump actions/cache from 4.0.1 to 4.0.2 (#3312)
dependabot[bot] Mar 25, 2024
c405b88
BpKContentCards LOOM-1276 (#3298)
jronald01 Mar 25, 2024
7f0f9a6
BpkBreakpoint: Fix Server Side Rendering (#3299)
robaw Mar 26, 2024
bf3dd5a
Bump typescript from 5.3.3 to 5.4.3 (#3308)
dependabot[bot] Mar 26, 2024
61e0e8a
Fix linting (#3319)
robaw Mar 26, 2024
dd6e9ac
[DTO-5126][bpk-component-chip] Create BpkIconChip (#3277)
Iain530 Mar 26, 2024
0b862d6
[NOJIRA] [BpkPageIndicator] Add cursor hover behaviour (#3321)
JonasLKD Mar 27, 2024
5b7142f
LOOM-1261 BpkAccordionItem - Moved className props out into existing …
Sybsw Mar 28, 2024
45f9f7f
LOOM-1277 BpkDataTableHeader (#3324)
jronald01 Mar 28, 2024
671736e
LOOM-1274 BpkBreadcrumb Class 2 Overrides (#3320)
jronald01 Mar 28, 2024
4b44b48
LOOM-1283 BpfFieldset Class 2 Overrides (#3326)
jronald01 Apr 1, 2024
532943e
LOOM-1281 BpkDialog className moved to new wrapper span (#3325)
Sybsw Apr 2, 2024
a2b26ca
DTO-5235 Add dark background flag for BpkModal and BpkModal v2 (#3323)
ameliajfitzpatrick Apr 2, 2024
ae87708
LOOM-1282 BkpDrawerContent BpkDrawer Class 2 Overrides (#3327)
jronald01 Apr 3, 2024
b56442d
LOOM-1287 BpkFormValidation moved className on BpkSmallExclamationIco…
Sybsw Apr 3, 2024
bb8ba86
LOOM-1289 BpkGridToggle moved className from BpkButtonLink out to wra…
Sybsw Apr 4, 2024
ea7e121
LOOM-1288 BpkGraphicPromo removed usages of BpkText (#3332)
Sybsw Apr 4, 2024
204df25
LOOM-1290 BpkHorizontalNav moved className on BpkMobileScrollContaine…
Sybsw Apr 5, 2024
6072d8e
[LOOM-1291][AnimateAndFade] className moved up one level (#3335)
metalix2 Apr 8, 2024
b65216d
LOOM-1298 BpkPriceMarker Class 2 Overrides (#3344)
jronald01 Apr 9, 2024
c71f6f5
Bump express from 4.18.2 to 4.19.2 (#3318)
dependabot[bot] Apr 9, 2024
0f7547f
LOOM-1292 BpkInfoBannerInner - Class 2 Overrides (#3339)
jronald01 Apr 9, 2024
50a8ad4
LOOM-1299 BpkModal V2 Class 2 Overrides (#3345)
jronald01 Apr 9, 2024
e777530
LOOM-1301 BpkNavigationBar Class 2 Overrides (#3346)
jronald01 Apr 10, 2024
343785a
[LOOM-1341]: update & --fix to @skyscanner/eslint-config-skyscanner@1…
mungodewar Apr 10, 2024
18d07c2
Bump webpack from 5.90.3 to 5.91.0 (#3316)
dependabot[bot] Apr 11, 2024
770f986
[LOOM-1341]: update eslint-config-skyscanner@18 & include forbid rule…
mungodewar Apr 11, 2024
c1d2175
NOJIRA: Add rating example with stars (#3355)
runmoore Apr 12, 2024
ae38ac3
LOOM-1314 BpkSectionListItem Class 2 Overrides (#3354)
jronald01 Apr 12, 2024
8408c94
LOOM-1304 BpkNudger Class 2 Overrides (#3349)
jronald01 Apr 12, 2024
1d4bbc8
link to new documentation inside eslint-plugin-rules (#3353)
mungodewar Apr 15, 2024
b26d506
Bump peaceiris/actions-gh-pages from 3 to 4 (#3359)
dependabot[bot] Apr 15, 2024
33a3ba4
LOOM-1315 BpkSpinner moved className prop to wrapper span (#3360)
Sybsw Apr 15, 2024
e96a40d
[LOOM-1302] - Update BpkNavigationBarButtonLink and Icon (#3361)
metalix2 Apr 15, 2024
f5e9dae
LOOM-1316 BpkInteractiveStar moved className on BpkStarNonRtl to new …
Sybsw Apr 16, 2024
6256ccc
update svgs to include modified ai logo & new dot logo (#3366)
mungodewar Apr 16, 2024
dce26c4
[LOOM-1318] [BpkThemeToggle] classname prop update (#3364)
metalix2 Apr 16, 2024
68fde9c
[NOJIRA][BpkBreakpoint]: add isClient defensively around useEffect & …
mungodewar Apr 18, 2024
5c11a3b
LOOM-1317 BpkStar Added spans around icons (#3367)
Sybsw Apr 19, 2024
b1403ff
[LOOM-1318][BpkCloseButton] Update Style and add onDark prop (#3372)
metalix2 Apr 19, 2024
1ee0374
remove unnecessary className (#3374)
metalix2 Apr 22, 2024
5701ca5
[BDES-137][bpk-component-mobile-scroll-container] Removed edge fade
FireRedNinja Apr 22, 2024
ce4f51b
[LOOM-1376][BpkMobileScrollContainer] Comment to declare the classNam…
metalix2 Apr 22, 2024
a192784
[LOOM-1373][BpkSlider] Comment to declare the className as an accepte…
metalix2 Apr 22, 2024
c63bcb6
[LOOM-1368][BpkModal] Comment to declare the className as an accepted…
metalix2 Apr 22, 2024
04ff5c3
LOOM-1367 BpkList Class 2 Overrides (#3377)
jronald01 Apr 22, 2024
c2d6b1e
fix ssr re-render behaviour (#3381)
mungodewar Apr 23, 2024
8a23b05
[LOOM-1313][BpkSectionHeader] Class2 Fixes (#3380)
metalix2 Apr 23, 2024
5d5c885
[MAT-1205] [BpkSkeleton] Add new component - bpk-component-skeleton (…
felix-luo-sc Apr 24, 2024
f9e6ccc
[ZOOT-992] Increases floating notification's z-index to 2 (#3385)
michmaml Apr 24, 2024
9e5ea14
[BD-7842][BpkMap] Add scaleControl prop for BpkMap component (#3384)
KathyWang0208 Apr 25, 2024
34f3ba5
[LOOM-1278][BpkBarChart] Class 2 Fix Remove unused classname prop (#3…
metalix2 Apr 25, 2024
c6d1e66
[LOOM-1287][BpkDismissibleChip][BpkSelectableChip] - Class 2 fixes (…
metalix2 Apr 25, 2024
375c9a9
LOOM-1307 BpkPhoneInput Class 2 Overrides (#3386)
jronald01 Apr 26, 2024
80ad9d8
Bump gulp from 4.0.2 to 5.0.0 (#3328)
dependabot[bot] Apr 29, 2024
9c66a3c
Remove useless styling (#3388)
metalix2 Apr 29, 2024
ebbc761
LOOM-1315 BpkSpinner animation fix (#3394)
Sybsw Apr 30, 2024
94304fd
Revert "[LOOM-1278][BpkBarChart] Class 2 Fix Remove unused classname …
mungodewar Apr 30, 2024
19367e2
[LOOM-1377][multiple-components]: remove unrequired ts ignores and ad…
mungodewar Apr 30, 2024
7f31ec1
[LOOM-1284][BpkFlare] Fix class 2 CSS issues for BpkFlare (#3389)
metalix2 Apr 30, 2024
18bf4b3
[LOOM-1394][BpkCalendar] - Update BpkCalendarWeek and fix fill stylin…
metalix2 Apr 30, 2024
052944b
[LOOM-1286][BpkFloatingNotification]: remove className usage from Bpk…
mungodewar Apr 30, 2024
802538c
Accepted rules (#3401)
metalix2 May 1, 2024
4494997
[LOOM-1295][BpkClearButton] Remove the BpkClearButton integrate direc…
metalix2 May 2, 2024
a3d617f
[IRN-5018][BpkNavigationBar][BpkBottomSheet] Add handling for long ti…
steviehailey-skyscanner May 2, 2024
ad06a05
Bump ejs from 3.1.9 to 3.1.10 (#3409)
dependabot[bot] May 2, 2024
25951e3
remove unused styling (#3404)
metalix2 May 2, 2024
f110224
LOOM-1306 BpkPaginationNudger Class 2 Overrides (#3410)
jronald01 May 2, 2024
5205779
[LOOM-1296][withOpenEvents]: Place `openable` styling within BpkInput…
mungodewar May 2, 2024
fd79539
[NOJIRA][chore]: ensure that icon dir is clean before copy (#3413)
mungodewar May 2, 2024
f00b443
[LOOM-1306][BpkPaginationNudget]: Remove customised padding values (#…
mungodewar May 2, 2024
ecedb79
[LOOM-1297][BpkSpinner]: Migrate to ts (#3414)
mungodewar May 3, 2024
cf11e5f
[ZOOT-1102][BpkDialogInner]: Adds optional aria-modal to the dialog (…
michmaml May 3, 2024
be974b1
Bump glob from 8.1.0 to 10.3.12 (#3329)
dependabot[bot] May 3, 2024
b4b7fc1
[LOOM-1297][maintenance]: Automated .d.ts file generation (#3417)
mungodewar May 3, 2024
26fb882
Update dist clean command as we never had rimraf (#3419)
olliecurtis May 3, 2024
ea864e2
[LOOM-1297][BpkLoadingButton]: migrate to bpkbutton v2 & adopt ts in …
mungodewar May 3, 2024
37891f2
Bump date-fns from 3.3.1 to 3.6.0 (#3305)
dependabot[bot] May 6, 2024
fec7434
fix the mixins vars (#3424)
metalix2 May 6, 2024
d2bf07f
Bump core-js from 3.35.1 to 3.37.0 (#3379)
dependabot[bot] May 6, 2024
a23b14c
Bump mini-css-extract-plugin from 2.8.1 to 2.9.0 (#3378)
dependabot[bot] May 6, 2024
06f6f51
Bump style-loader from 3.3.4 to 4.0.0 (#3357)
dependabot[bot] May 6, 2024
31a5778
Bump sass-migrator from 1.8.0 to 2.0.3 (#3293)
dependabot[bot] May 6, 2024
4c4618d
Fix rendering of Map Marker v2 (#3425)
olliecurtis May 6, 2024
09315a1
Bump sass-loader from 14.1.1 to 14.2.1 (#3422)
dependabot[bot] May 6, 2024
255efae
LOOM-1309 BpkPrice Class 2 Overrides (#3418)
jronald01 May 7, 2024
c044b1d
[NoJIra][BpkModal] Update modal stories to tsx and add visual tests (…
metalix2 May 7, 2024
ca7653b
style fix (#3426)
metalix2 May 8, 2024
760626e
Revert "Revert "[LOOM-1278][BpkBarChart] Class 2 Fix Remove unused cl…
metalix2 May 9, 2024
684dc46
[ARGG-1063][BpkPopover]: Migrate to floating UI library (#3390)
olliecurtis May 9, 2024
c4f7a35
[Luna 1326][BpkSlider]: Changes BpkSlider base library for mobile acc…
LouiseReid May 9, 2024
f29e4ba
[LOOM-1312] [BpkScrollableCalendarGridList] Moved className to existi…
Sybsw May 10, 2024
6bddd5e
[NOJIRA][BpkLoadingButton|BpkCloseButton]: fix loading console errors…
mungodewar May 10, 2024
647e156
[NOJIRA][internal]: Add danger rule for console.error messages during…
mungodewar May 10, 2024
3f409cb
[IRN-5039] BottomSheet supports aria-label (#3427)
steviehailey-skyscanner May 13, 2024
b020538
[LOOM-1310][BpkRating]: remove className usage on BpkText & migrate t…
mungodewar May 13, 2024
09982ba
[LOOM-1310][BpkRating]: correct letter-spacing in bpk rating (#3433)
mungodewar May 13, 2024
e9d3dc6
spinner fixes (#3434)
metalix2 May 13, 2024
77e71a6
[WALL-1371][BpkText] Add Larken TextStyles to Backpack (#3435)
youngji0827 May 14, 2024
4d66ded
LOOM-1362 BpkBannerAlertInner Class 2 Overrides (#3444)
jronald01 May 15, 2024
56ffe4e
[LOOM-1319][BpkDividedCard]: Remove className from BpkCard (#3440)
mungodewar May 15, 2024
f867ab1
[LOOM-1363][BpkButton]: Refactor BpkButtonV1 (#3443)
mungodewar May 15, 2024
f554a98
[NoJira][BpkNavigationBar] new storybook visual test for navbar with …
metalix2 May 15, 2024
3eb8672
LOOM-1365 BpkDialogInner (#3454)
jronald01 May 16, 2024
a807eec
Bump actions/upload-artifact from 3.1.3 to 4.3.3 and actions/download…
dependabot[bot] May 16, 2024
b65d9fe
Bump sass-embedded from 1.71.1 to 1.77.1 (#3439)
dependabot[bot] May 16, 2024
9fdcbf4
Bump danger from 11.3.1 to 12.2.0 (#3438)
dependabot[bot] May 16, 2024
7a61065
LOOM-1361 BpkAutoSuggestSuggestion Added wrapper div around Icon for …
Sybsw May 17, 2024
dc499a8
[ARGG-1144]: Move Percy later in the CI as last step (#3450)
olliecurtis May 17, 2024
f29412e
[NO JIRA]: Update release CI to move supernova (#3445)
olliecurtis May 17, 2024
89b814d
Fix popover z-index (#3459)
olliecurtis May 17, 2024
f8306dd
[ARGG-1085][BpkPopover] Update popover design (#3455)
anambl May 17, 2024
dd98af9
[LOOM-1361] [BpkAutosuggestSuggestion] Added interaction visual test …
Sybsw May 17, 2024
49d0a78
[BpkNudger] Fix accessibility issue (#3461)
gert-janvercauteren May 20, 2024
a2183df
[LOOM-1364][BpkSaveButton]: remove className from HeartIcons, refacto…
mungodewar May 20, 2024
affd4f0
[LOOM-1300][BpkModalInner] Style 2 fixes (#3447)
metalix2 May 20, 2024
cbe3432
use typeof check rather than boolean to determine if environment is c…
mungodewar May 20, 2024
24e5083
[WALL-1371][BpkText] Add the Noto fallbacks for the Larken font (#3462)
youngji0827 May 20, 2024
1bdafe1
[maintainence][BpkModalV2] Add Visual Snapshots (#3464)
metalix2 May 21, 2024
7232b0d
[NOJIRA][BpkFloatingNotification]: Fix CTA position (#3465)
mungodewar May 22, 2024
f9e782f
LOOM-1369 BpkModalv2 (#3458)
jronald01 May 22, 2024
3fa649c
[LOOM-1370][BpkPaginationPage] Replace BpkButton in BpkPaginationPage…
metalix2 May 22, 2024
9a630a4
Override for ComposedComponent in BpkIcon (#3468)
metalix2 May 22, 2024
ee8af32
[LOOM-1374][BpkDescriptionList] - Typescript and Class2 style fixes. …
metalix2 May 22, 2024
2cf166e
Bump css-loader from 6.10.0 to 7.1.1 (#3437)
dependabot[bot] May 23, 2024
9a6dcfd
Revert "Bump css-loader from 6.10.0 to 7.1.1 (#3437)" (#3473)
olliecurtis May 24, 2024
cecfda6
[NO JIRA][BpkPopover]: Fix popover container classname (#3472)
olliecurtis May 24, 2024
0a1ef19
[BpkDialog]: Fix optional modal prop (#3471)
olliecurtis May 24, 2024
304e809
Merge branch 'main' into bpk-carousel
KathyWang0208 May 27, 2024
5dcb070
fix css error of the new component
Kathy0208 May 27, 2024
e6f3372
fix unit test error and lint error
Kathy0208 May 27, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions examples/bpk-component-carousel/example.js
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,14 @@
import BpkCarousel from '../../packages/bpk-component-carousel'

const DemoImages = () => (
<img src="https://d2xf5gjipzd8cd.cloudfront.net/available/949043373/949043373_343x132.jpg" alt='' />
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved
)

const imagesList = [<DemoImages />,<img src='https://d2xf5gjipzd8cd.cloudfront.net/available/758391025/758391025_343x132.jpg' alt='' />, <DemoImages />, <DemoImages />, <DemoImages />, <DemoImages />]
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved


const DefaultExample = () => (
<BpkCarousel images={imagesList} initialImageIndex={1}/>
);

export default DefaultExample
11 changes: 11 additions & 0 deletions examples/bpk-component-carousel/stories.js
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,11 @@
import BpkCarousel from '../../packages/bpk-component-carousel'

import DefaultExample from './example'

export default {
title: 'bpk-component-carousel',
component: BpkCarousel,
};


export const Default = DefaultExample;
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved
25 changes: 25 additions & 0 deletions packages/bpk-component-carousel/README.md
@@ -0,0 +1,25 @@
# bpk-component-boilerplate
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved

> Backpack carousel component.

## Installation

Check the main [Readme](https://github.com/skyscanner/backpack#usage) for a complete installation guide.

## Usage

```tsx
import BpkBoilerplate from '@skyscanner/backpack-web/bpk-component-carousel';
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved

const imageChangeHandler = () => {
console.log('Image Changed')
}

export default () => (
<BpkCarousel
images={[ <img src="https://url/1_WxH.jpg" alt='image' />]}
initialImageIndex={2}
onImageChanged={imageChangeHandler}
/>
);
```
21 changes: 21 additions & 0 deletions packages/bpk-component-carousel/index.ts
@@ -0,0 +1,21 @@
/*
* Backpack - Skyscanner's Design System
*
* Copyright 2016 Skyscanner Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import BpkCarousel from "./src";

export default BpkCarousel
65 changes: 65 additions & 0 deletions packages/bpk-component-carousel/src/BpkCarousel-test.tsx
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,65 @@
import { render, screen, getAllByRole } from '@testing-library/react';
import { axe } from 'jest-axe';
import userEvent from '@testing-library/user-event';
import type { ReactNode } from 'react';

import BpkCarousel from './BpkCarousel';


describe('BpkCarousel', () => {
let images: ReactNode[]

const DemoImages = () => (
<img src="https://d2xf5gjipzd8cd.cloudfront.net/available/949043373/949043373_343x132.jpg" alt='' />
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved
)

function generateDemoImages(count: number) {
return Array.from({ length: count }, (_, i) => (<DemoImages />));
}

type TestCase = [
expectedCount: 7 | 5 | 4 | 12,
actualCount: number,
props: React.ComponentProps<typeof BpkCarousel>,
];

beforeAll(() => {

window.HTMLElement.prototype.scrollIntoView = jest.fn();

(window as any).IntersectionObserver = class IntersectionObserver {
observe = jest.fn();

disconnect = jest.fn();

unobserve = jest.fn();
};
images = [<DemoImages />, <DemoImages />, <DemoImages />, <DemoImages />, <DemoImages />];
});

it('should render correctly', () => {
const { asFragment } = render(<BpkCarousel images={images} />);

expect(asFragment()).toMatchSnapshot();
});

it.each<TestCase>([
[12, 10, { images: generateDemoImages(10) }],
[7, 5, { images: generateDemoImages(5) }],
[5, 3, { images: generateDemoImages(3) }],
[4, 2, { images: generateDemoImages(2) }],
])(
'renders %i image(s) when there are %i image(s) available',
(expectedCount, actualCount, props) => {
render(<BpkCarousel {...props} />);

expect(screen.getByTestId('image-gallery-scroll-container').childElementCount).toBe(expectedCount);
},
);

it('renders only one image when only one available (no fake images for the infinite scroll)', async () => {
render(<BpkCarousel images={[images[0]]} />);

expect(screen.getByTestId('image-gallery-scroll-container').childElementCount).toBe(1);
});
});
35 changes: 35 additions & 0 deletions packages/bpk-component-carousel/src/BpkCarousel.d.ts
@@ -0,0 +1,35 @@
/*
* Backpack - Skyscanner's Design System
*
* Copyright 2022 Skyscanner Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import { OnImageChangedHandler } from "./types";
import type { ReactNode } from 'react';

export type Props = {
images: ReactNode[]
initialImageIndex?: number;
onImageChanged?: OnImageChangedHandler
};

declare const BpkCarousel: {
({ initialImageIndex, onImageChanged, ...rest }: Props): JSX.Element;
defaultProps: {
initialImageIndex: 0;
onImageChanged: null
};
};
export default BpkCarousel;
35 changes: 35 additions & 0 deletions packages/bpk-component-carousel/src/BpkCarousel.tsx
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,35 @@
import { useRef, useState } from 'react';


import { useScrollToInitialImage } from './utils';
import BpkCarouselContainer from './BpkCarouselContainer';
import BpkSlidesIndicator from './BpkCarouselSlidesIndicator';
import type { Props } from './types';

const BpkCarousel = ({
images,
initialImageIndex = 0,
onImageChanged = null
}: Props) => {
const [shownImageIndex, updateShownImageIndex] = useState(initialImageIndex);
const imagesRef = useRef<Array<HTMLElement | null>>([]);

useScrollToInitialImage(initialImageIndex, imagesRef);

return (
<>
<BpkCarouselContainer
images={images}
onVisible={updateShownImageIndex}
imagesRef={imagesRef}
onImageChanged={onImageChanged}
/>
<BpkSlidesIndicator
length={images.length}
activeIndex={shownImageIndex}
/>
</>
);
};

export default BpkCarousel;
@@ -0,0 +1,18 @@
/*
* Backpack - Skyscanner's Design System
*
* Copyright 2016 Skyscanner Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@keyframes bpk-keyframe-spin{100%{transform:rotate(1turn)}}.bpk-carousel-container{display:grid;width:100%;height:100%;grid:1fr / auto-flow 100%;border-radius:.75rem;overflow-x:auto;overflow-y:hidden;backface-visibility:hidden;overscroll-behavior:contain;scroll-snap-type:x mandatory;scrollbar-width:none;user-select:none}@media (max-width: 32.25rem){.bpk-carousel-container{border-radius:0}}.bpk-carousel-container::-webkit-scrollbar{display:none}
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,19 @@
@import '~bpk-mixins/index.scss';
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved

.bpk-carousel-container {
display: grid;
width: 100%;
height: 100%;
grid: 1fr / auto-flow 100%;
overflow-x: auto;
overflow-y: hidden;
backface-visibility: hidden;
overscroll-behavior: contain;
scroll-snap-type: x mandatory;
scrollbar-width: none;
user-select: none;

&::-webkit-scrollbar {
display: none;
}
}
87 changes: 87 additions & 0 deletions packages/bpk-component-carousel/src/BpkCarouselContainer.tsx
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved
@@ -0,0 +1,87 @@
import type { MutableRefObject, ReactNode } from 'react';
import { memo, useState } from 'react';

import { cssModules } from '../../bpk-react-utils';

import { useIntersectionObserver } from './utils';
import STYLES from './BpkCarouselContainer.module.scss';
import BpkCarouselImage from './BpkCarouselImage';
import type { OnImageChangedHandler } from './types';

const getClassName = cssModules(STYLES);

type Props = {
images: ReactNode[];
onVisible: (visibleIndex: number) => void;
imagesRef: MutableRefObject<Array<HTMLElement | null>>;
onImageChanged: OnImageChangedHandler
};

const BpkScrollContainer = memo(({ images, imagesRef, onImageChanged, onVisible }: Props) => {
const [root, setRoot] = useState<HTMLElement | null>(null);
const observeImageChange = useIntersectionObserver(onVisible, {
root,
threshold: 0.5,
}, onImageChanged);
const observeCycleScroll = useIntersectionObserver(
(index) => {
const imageElement = imagesRef.current && imagesRef.current[index];
if (imageElement) {
imageElement.scrollIntoView({
block: 'nearest',
inline: 'start',
});
}
},
{ root, threshold: 1 },
);

if (images.length === 1) {
return (
<div className={getClassName('bpk-carousel-container')} role="list" data-testid="image-gallery-scroll-container">
<BpkCarouselImage image={images[0]} index={0} />
</div>
);
}

return (
<div
className={getClassName('bpk-carousel-container')}
ref={setRoot}
data-testid="image-gallery-scroll-container"
role="list"
>
<BpkCarouselImage
image={images[images.length - 1]}
index={images.length - 1}
ref={(el) => {
observeCycleScroll(el);
observeImageChange(el);
}}
/>
{images.map((image, index) => (
<BpkCarouselImage
// eslint-disable-next-line react/no-array-index-key
key={index}
image={image}
index={index}
ref={(el) => {
// eslint-disable-next-line no-param-reassign
imagesRef.current[index] = el;
observeImageChange(el);
}}
/>
))}
<BpkCarouselImage
image={images[0]}
index={0}
ref={(el) => {
observeCycleScroll(el);
observeImageChange(el);
}}
Comment on lines +95 to +101
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this needs to be before the logic to map each of the images?
As it seems to always have the first selected image as the last one when it renders which is this expected behaviour?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ricci is away on AL now, but it seems to be in order for the scroll snap to create an infinite loop.

/>
</div>
);
});

export default BpkScrollContainer;
18 changes: 18 additions & 0 deletions packages/bpk-component-carousel/src/BpkCarouselImage.module.css
@@ -0,0 +1,18 @@
/*
* Backpack - Skyscanner's Design System
*
* Copyright 2016 Skyscanner Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
@keyframes bpk-keyframe-spin{100%{transform:rotate(1turn)}}.bpk-carousel-image{display:inline-flex;width:100%;min-width:0;height:100%;min-height:0;justify-content:center;scroll-snap-align:start;scroll-snap-stop:always;isolation:isolate}.bpk-carousel-image img{max-width:100%;max-height:100%;border-radius:.75rem;object-fit:cover}@media (max-width: 32.25rem){.bpk-carousel-image img{border-radius:0;object-fit:contain}}
28 changes: 28 additions & 0 deletions packages/bpk-component-carousel/src/BpkCarouselImage.module.scss
@@ -0,0 +1,28 @@
@import '~bpk-mixins/index.scss';
R1CC1M marked this conversation as resolved.
Show resolved Hide resolved

.bpk-carousel-image {
display: inline-flex;
width: 100%;
min-width: 0;
height: 100%;
min-height: 0;
justify-content: center;
scroll-snap-align: start;
scroll-snap-stop: always;

/* helps with flickering when cycle scroll */
/* stylelint-disable-next-line order/properties-order */
isolation: isolate;

img {
max-width: 100%;
max-height: 100%;
border-radius: $bpk-border-radius-md;
object-fit: cover;

@include bpk-breakpoint-mobile {
border-radius: 0;
object-fit: contain;
}
}
}