Repository: Skyscanner/backpack
Pull request #3783: [PANGOO-2945][BpkPageIndicator]Bpk component page indicator ts support
Author: login: senzg
Labels: name: minor
description: Non breaking change
Created: 2025-04-02T07:36:10Z | Merged: 2025-04-07T08:31:09Z

<!--
Thanks for contributing to Backpack :pray:

Please include a description of the changes you are introducing and some screenshots if appropriate.

Please ensure your pull request title is clear as it will be used to generate the changelog.

Add `major`, `minor` or `patch` label depending on the change according to [semver](semver.org) or `skip-changelog` if the change shouldn't be added to the changelog (e.g. a change to a test or documentation)
-->

Remember to include the following changes:

- [x] Ensure the PR title includes the name of the component you are changing so it's clear in the release notes for consumers of the changes in the version e.g `[Clover-123][BpkButton] Updating the colour`
- [ ] `README.md` (If you have created a new component)
- [ ] Component `README.md`
- [x] Tests
- [x] Accessibility tests
    - The following checks were performed:
        - [x] Ability to navigate using a [keyboard only](https://webaim.org/techniques/keyboard/)
        - [x] Zoom functionality ([Deque University explanation](https://dequeuniversity.com/checklists/web/text)):
            - [x] The page SHOULD be functional AND readable when only the text is magnified to 200% of its initial size
            - [x] Pages must reflow as zoom increases up to 400% so that content continues to be presented in only one column i.e. Content MUST NOT require scrolling in two directions (both vertically and horizontally)
        - [ ] Ability to navigate using a [screen reader only](https://webaim.org/articles/screenreader_testing/)
- [ ] Storybook examples created/updated
- [ ] For breaking changes or deprecating components/properties, migration guides added to the description of the PR. If the guide has large changes, consider creating a new Markdown page inside the component's docs folder and link it here



Diff:
diff --git a/examples/bpk-component-page-indicator/examples.js b/examples/bpk-component-page-indicator/examples.tsx
similarity index 91%
rename from examples/bpk-component-page-indicator/examples.js
rename to examples/bpk-component-page-indicator/examples.tsx
index b12da295ff..47c21692ef 100644
--- a/examples/bpk-component-page-indicator/examples.js
+++ b/examples/bpk-component-page-indicator/examples.tsx
@@ -24,6 +24,8 @@ import BpkPageIndicator, {
 } from '../../packages/bpk-component-page-indicator';
 import { cssModules } from '../../packages/bpk-react-utils';
 
+import type { BpkPageIndicatorProps } from '../../packages/bpk-component-page-indicator';
+
 import STYLES from './examples.module.scss';
 
 const getClassName = cssModules(STYLES);
@@ -32,7 +34,9 @@ const image =
   'https://content.skyscnr.com/m/50d9dff3186775ad/original/Condor-Homepage-Hero-Option-3.png';
 const imageWidth = 400;
 const imageHeight = 90;
-const PageIndicatorContainer = (props) => {
+type PageIndicatorContainerProps = Omit<BpkPageIndicatorProps, 'currentIndex'>;
+
+const PageIndicatorContainer = (props: PageIndicatorContainerProps) => {
   const [currentIndex, setCurrentIndex] = useState(0);
 
   return (
diff --git a/examples/bpk-component-page-indicator/stories.js b/examples/bpk-component-page-indicator/stories.tsx
similarity index 91%
rename from examples/bpk-component-page-indicator/stories.js
rename to examples/bpk-component-page-indicator/stories.tsx
index 43dfaf25de..f8e804d25a 100644
--- a/examples/bpk-component-page-indicator/stories.js
+++ b/examples/bpk-component-page-indicator/stories.tsx
@@ -36,7 +36,9 @@ export const ThreePages = ThreePagesExample;
 export const OverImage = OverImageExample;
 export const WithNav = WithNavExample;
 export const VisualTest = VisualTestExample;
-export const VisualTestWithZoom = VisualTest.bind({});
-VisualTestWithZoom.args = {
-  zoomEnabled: true
+export const VisualTestWithZoom = {
+  render: VisualTest,
+  args: {
+    zoomEnabled: true,
+  },
 };
diff --git a/packages/bpk-component-carousel/src/BpkCarousel.tsx b/packages/bpk-component-carousel/src/BpkCarousel.tsx
index 3fbb16df89..9d7b6378ea 100644
--- a/packages/bpk-component-carousel/src/BpkCarousel.tsx
+++ b/packages/bpk-component-carousel/src/BpkCarousel.tsx
@@ -18,7 +18,6 @@
 
 import { useRef, useState } from 'react';
 
-// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
 import BpkPageIndicator, { VARIANT } from '../../bpk-component-page-indicator';
 import { cssModules } from '../../bpk-react-utils';
 
diff --git a/packages/bpk-component-page-indicator/index.js b/packages/bpk-component-page-indicator/index.ts
similarity index 84%
rename from packages/bpk-component-page-indicator/index.js
rename to packages/bpk-component-page-indicator/index.ts
index 8c078970c7..43c641a6b4 100644
--- a/packages/bpk-component-page-indicator/index.js
+++ b/packages/bpk-component-page-indicator/index.ts
@@ -15,14 +15,12 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/* @flow strict */
 
-import BpkPageIndicator, {
-  type Props as BpkPageIndicatorProps,
-  VARIANT,
-} from './src/BpkPageIndicator';
+import BpkPageIndicator, { VARIANT } from './src/BpkPageIndicator';
 import { DIRECTIONS } from './src/NavButton';
 
+import type { Props as BpkPageIndicatorProps } from './src/BpkPageIndicator';
+
 export type { BpkPageIndicatorProps };
 export { DIRECTIONS, VARIANT };
 export default BpkPageIndicator;
diff --git a/packages/bpk-component-page-indicator/src/BpkPageIndicator-test.js b/packages/bpk-component-page-indicator/src/BpkPageIndicator-test.tsx
similarity index 91%
rename from packages/bpk-component-page-indicator/src/BpkPageIndicator-test.js
rename to packages/bpk-component-page-indicator/src/BpkPageIndicator-test.tsx
index c5bb266a1e..226642b6b1 100644
--- a/packages/bpk-component-page-indicator/src/BpkPageIndicator-test.js
+++ b/packages/bpk-component-page-indicator/src/BpkPageIndicator-test.tsx
@@ -15,16 +15,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/* @flow strict */
 
 import { render, screen } from '@testing-library/react';
 import '@testing-library/jest-dom';
 
 import BpkPageIndicator from './BpkPageIndicator';
 
-let props;
+import type { Props } from './BpkPageIndicator';
 
 describe('BpkPageIndicator', () => {
+  let props: Props;
+
   beforeEach(() => {
     props = {
       currentIndex: 0,
@@ -43,9 +44,7 @@ describe('BpkPageIndicator', () => {
   });
 
   it('should support custom class names', () => {
-    render(
-      <BpkPageIndicator {...props} className="custom-classname" />,
-    );
+    render(<BpkPageIndicator {...props} className="custom-classname" />);
 
     expect(document.querySelector('.custom-classname')).toBeTruthy();
   });
diff --git a/packages/bpk-component-page-indicator/src/BpkPageIndicator.js b/packages/bpk-component-page-indicator/src/BpkPageIndicator.js
deleted file mode 100644
index c862299009..0000000000
--- a/packages/bpk-component-page-indicator/src/BpkPageIndicator.js
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * 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.
- */
-/* @flow strict */
-
-import PropTypes from 'prop-types';
-
-import { cssModules } from '../../bpk-react-utils';
-
-import NavButton, { DIRECTIONS } from './NavButton';
-
-import STYLES from './BpkPageIndicator.module.scss';
-
-const getClassName = cssModules(STYLES);
-
-const DISPLAYED_TOTAL = 5;
-const START_SCROLL_INDEX = Math.floor(DISPLAYED_TOTAL / 2);
-
-export const VARIANT = {
-  default: 'default',
-  overImage: 'overImage',
-};
-
-export type Props = {
-  className: ?string,
-  showNav: ?boolean,
-  currentIndex: number,
-  totalIndicators: number,
-  onClick: ?() => void,
-  indicatorLabel: string,
-  prevNavLabel: string,
-  nextNavLabel: string,
-  variant: ?$Keys<typeof VARIANT>,
-};
-
-const BpkPageIndicator = ({
-  className,
-  currentIndex,
-  indicatorLabel,
-  nextNavLabel,
-  onClick,
-  prevNavLabel,
-  showNav,
-  totalIndicators,
-  variant,
-}: Props) => {
-  /**
-   * This validation is used to avoid an a11y issue when onClick isn't available.
-   * In this case, we can set aria-hidden = true to let screen reader skip reading page indicator dots.
-   * and render the dot as div rather than button to align with aria-hidden = true.
-  */
-  const isInteractive = !!onClick;
-
-  return (
-    // $FlowFixMe[cannot-spread-inexact] - inexact rest. See 'decisions/flowfixme.md'.
-    <div
-      className={className}
-      aria-hidden={isInteractive ? 'false': 'true'}
-      data-testid="indicator-container"
-    >
-      <div
-        className={getClassName(
-          'bpk-page-indicator',
-          showNav && 'bpk-page-indicator__showNav',
-        )}
-      >
-        {showNav && (
-          <NavButton
-            currentIndex={currentIndex}
-            onClick={onClick}
-            disabled={currentIndex === 0}
-            direction={DIRECTIONS.PREV}
-            ariaLabel={prevNavLabel}
-          />
-        )}
-        <div className={getClassName('bpk-page-indicator__container')}>
-          <div
-            className={getClassName('bpk-page-indicator__indicators-container')}
-            style={
-              currentIndex > START_SCROLL_INDEX
-                ? {
-                  '--scroll-index':
-                    totalIndicators > DISPLAYED_TOTAL
-                      ? Math.min(
-                        currentIndex - START_SCROLL_INDEX,
-                        totalIndicators - DISPLAYED_TOTAL,
-                      )
-                      : 0,
-                }
-                : undefined
-            }
-          >
-            {[...Array(totalIndicators)].map((val, index) => isInteractive ? (
-              <button
-                type="button"
-                onClick={(e) => {
-                  onClick(e, index, DIRECTIONS.INDICATORS);
-                }}
-                className={getClassName(
-                  'bpk-page-indicator__indicator',
-                  `bpk-page-indicator__indicator--${variant}`,
-                  index === currentIndex &&
-                  `bpk-page-indicator__indicator--active-${variant}`,
-                )}
-                aria-label={`${indicatorLabel} ${index + 1}`}
-                aria-current={currentIndex === index ? 'true' : 'false'}
-                // eslint-disable-next-line react/no-array-index-key
-                key={`indicator-${index}`}
-              />
-            ) : (
-              <div
-                className={getClassName(
-                  'bpk-page-indicator__indicator',
-                  `bpk-page-indicator__indicator--${variant}`,
-                  index === currentIndex &&
-                  `bpk-page-indicator__indicator--active-${variant}`,
-                )}
-                // eslint-disable-next-line react/no-array-index-key
-                key={`indicator-${index}`}
-              />
-            ))}
-          </div>
-        </div>
-        {showNav && (
-          <NavButton
-            currentIndex={currentIndex}
-            onClick={onClick}
-            disabled={currentIndex === totalIndicators - 1}
-            ariaLabel={nextNavLabel}
-            direction={DIRECTIONS.NEXT}
-          />
-        )}
-      </div>
-    </div>
-  )
-};
-
-BpkPageIndicator.propTypes = {
-  indicatorLabel: PropTypes.string,
-  prevNavLabel: PropTypes.string,
-  nextNavLabel: PropTypes.string,
-  currentIndex: PropTypes.number.isRequired,
-  totalIndicators: PropTypes.number.isRequired,
-  variant: PropTypes.oneOf(Object.keys(VARIANT)),
-  onClick: PropTypes.func,
-  className: PropTypes.string,
-  showNav: PropTypes.bool,
-};
-
-BpkPageIndicator.defaultProps = {
-  onClick: null,
-  className: null,
-  showNav: false,
-  variant: VARIANT.default,
-};
-
-export default BpkPageIndicator;
diff --git a/packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx b/packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx
new file mode 100644
index 0000000000..40afe4af1f
--- /dev/null
+++ b/packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx
@@ -0,0 +1,161 @@
+/*
+ * 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 type { CSSProperties, MouseEvent } from 'react';
+
+import { cssModules } from '../../bpk-react-utils';
+
+import NavButton, { DIRECTIONS } from './NavButton';
+
+import STYLES from './BpkPageIndicator.module.scss';
+
+const getClassName = cssModules(STYLES);
+
+const DISPLAYED_TOTAL = 5;
+const START_SCROLL_INDEX = Math.floor(DISPLAYED_TOTAL / 2);
+
+export const VARIANT = {
+  default: 'default',
+  overImage: 'overImage',
+} as const;
+
+type Variant = (typeof VARIANT)[keyof typeof VARIANT];
+type Direction = (typeof DIRECTIONS)[keyof typeof DIRECTIONS];
+
+export type Props = {
+  indicatorLabel?: string;
+  prevNavLabel?: string;
+  nextNavLabel?: string;
+  currentIndex: number;
+  totalIndicators: number;
+  variant?: Variant;
+  onClick?: (
+    event: MouseEvent<HTMLButtonElement>,
+    newIndex: number,
+    direction: Direction,
+  ) => void;
+  className?: string;
+  showNav?: boolean;
+};
+
+const BpkPageIndicator = ({
+  className = undefined,
+  currentIndex,
+  indicatorLabel,
+  nextNavLabel,
+  onClick = () => {},
+  prevNavLabel,
+  showNav = false,
+  totalIndicators,
+  variant = VARIANT.default,
+}: Props) => {
+  /**
+   * This validation is used to avoid an a11y issue when onClick isn't available.
+   * In this case, we can set aria-hidden = true to let screen reader skip reading page indicator dots.
+   * and render the dot as div rather than button to align with aria-hidden = true.
+   */
+  const isInteractive = !!onClick;
+
+  type CustomCSSProperties = CSSProperties & {
+    '--scroll-index'?: number;
+  };
+
+  const customStyle: CustomCSSProperties = {
+    '--scroll-index':
+      totalIndicators > DISPLAYED_TOTAL
+        ? Math.min(
+            currentIndex - START_SCROLL_INDEX,
+            totalIndicators - DISPLAYED_TOTAL,
+          )
+        : 0,
+  };
+
+  return (
+    <div
+      className={className}
+      aria-hidden={isInteractive ? 'false' : 'true'}
+      data-testid="indicator-container"
+    >
+      <div
+        className={getClassName(
+          'bpk-page-indicator',
+          showNav && 'bpk-page-indicator__showNav',
+        )}
+      >
+        {showNav && (
+          <NavButton
+            currentIndex={currentIndex}
+            onClick={onClick}
+            disabled={currentIndex === 0}
+            direction={DIRECTIONS.PREV}
+            ariaLabel={prevNavLabel}
+          />
+        )}
+        <div className={getClassName('bpk-page-indicator__container')}>
+          <div
+            className={getClassName('bpk-page-indicator__indicators-container')}
+            style={currentIndex > START_SCROLL_INDEX ? customStyle : undefined}
+          >
+            {[...Array(totalIndicators)].map((val, index) =>
+              isInteractive ? (
+                <button
+                  type="button"
+                  onClick={(e) => {
+                    onClick(e, index, DIRECTIONS.INDICATORS);
+                  }}
+                  className={getClassName(
+                    'bpk-page-indicator__indicator',
+                    `bpk-page-indicator__indicator--${variant}`,
+                    index === currentIndex &&
+                      `bpk-page-indicator__indicator--active-${variant}`,
+                  )}
+                  aria-label={`${indicatorLabel} ${index + 1}`}
+                  aria-current={currentIndex === index ? 'true' : 'false'}
+                  // eslint-disable-next-line react/no-array-index-key
+                  key={`indicator-${index}`}
+                />
+              ) : (
+                <div
+                  className={getClassName(
+                    'bpk-page-indicator__indicator',
+                    `bpk-page-indicator__indicator--${variant}`,
+                    index === currentIndex &&
+                      `bpk-page-indicator__indicator--active-${variant}`,
+                  )}
+                  // eslint-disable-next-line react/no-array-index-key
+                  key={`indicator-${index}`}
+                />
+              ),
+            )}
+          </div>
+        </div>
+        {showNav && (
+          <NavButton
+            currentIndex={currentIndex}
+            onClick={onClick}
+            disabled={currentIndex === totalIndicators - 1}
+            ariaLabel={nextNavLabel}
+            direction={DIRECTIONS.NEXT}
+          />
+        )}
+      </div>
+    </div>
+  );
+};
+
+export default BpkPageIndicator;
diff --git a/packages/bpk-component-page-indicator/src/NavButton.js b/packages/bpk-component-page-indicator/src/NavButton.js
deleted file mode 100644
index fa2502fa37..0000000000
--- a/packages/bpk-component-page-indicator/src/NavButton.js
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.
- */
-/* @flow strict */
-
-import PropTypes from 'prop-types';
-
-import {BUTTON_TYPES, BpkButtonV2} from '../../bpk-component-button';
-import { withButtonAlignment, withRtlSupport } from '../../bpk-component-icon';
-import LeftArrowIcon from '../../bpk-component-icon/lg/chevron-left';
-import RightArrowIcon from '../../bpk-component-icon/lg/chevron-right';
-
-export const DIRECTIONS = {
-  PREV: 'PREV',
-  INDICATORS: 'INDICATORS',
-  NEXT: 'NEXT',
-};
-
-type Props = {
-  direction: $Keys<typeof DIRECTIONS>,
-  disabled?: boolean,
-  currentIndex: number,
-  onClick: ?() => void,
-  ariaLabel: string,
-};
-
-const AlignedLeftArrowIcon = withButtonAlignment(withRtlSupport(LeftArrowIcon));
-const AlignedRightArrowIcon = withButtonAlignment(
-  withRtlSupport(RightArrowIcon),
-);
-
-const NavButton = (props: Props) => {
-  const { ariaLabel, currentIndex, direction, disabled, onClick } = props;
-  return (
-    <BpkButtonV2
-      iconOnly
-      type={BUTTON_TYPES.link}
-      onClick={(e) => {
-        if (direction === DIRECTIONS.PREV) {
-          onClick(e, currentIndex - 1, direction);
-        } else {
-          onClick(e, currentIndex + 1, direction);
-        }
-      }}
-      aria-label={ariaLabel}
-      disabled={disabled}
-    >
-      {direction === DIRECTIONS.PREV ? (
-        <AlignedLeftArrowIcon />
-      ) : (
-        <AlignedRightArrowIcon />
-      )}
-    </BpkButtonV2>
-  );
-};
-
-NavButton.propTypes = {
-  direction: PropTypes.oneOf(Object.keys(DIRECTIONS)).isRequired,
-  disabled: PropTypes.bool,
-  ariaLabel: PropTypes.string.isRequired,
-  currentIndex: PropTypes.number.isRequired,
-  onClick: PropTypes.func,
-};
-
-NavButton.defaultProps = {
-  disabled: false,
-  onClick: null,
-};
-
-export default NavButton;
diff --git a/packages/bpk-component-page-indicator/src/NavButton.tsx b/packages/bpk-component-page-indicator/src/NavButton.tsx
new file mode 100644
index 0000000000..cd4885b970
--- /dev/null
+++ b/packages/bpk-component-page-indicator/src/NavButton.tsx
@@ -0,0 +1,77 @@
+/*
+ * 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 { BUTTON_TYPES, BpkButtonV2 } from '../../bpk-component-button';
+import { withButtonAlignment, withRtlSupport } from '../../bpk-component-icon';
+import LeftArrowIcon from '../../bpk-component-icon/lg/chevron-left';
+import RightArrowIcon from '../../bpk-component-icon/lg/chevron-right';
+
+export const DIRECTIONS = {
+  PREV: 'PREV',
+  INDICATORS: 'INDICATORS',
+  NEXT: 'NEXT',
+} as const;
+
+type Direction = (typeof DIRECTIONS)[keyof typeof DIRECTIONS];
+
+type Props = {
+  ariaLabel: string | undefined;
+  currentIndex: number;
+  direction: Direction;
+  disabled?: boolean;
+  onClick?: (
+    event: React.MouseEvent<HTMLButtonElement>,
+    newIndex: number,
+    direction: Direction,
+  ) => void;
+};
+
+const AlignedLeftArrowIcon = withButtonAlignment(withRtlSupport(LeftArrowIcon));
+const AlignedRightArrowIcon = withButtonAlignment(
+  withRtlSupport(RightArrowIcon),
+);
+
+const NavButton = ({
+  ariaLabel,
+  currentIndex,
+  direction,
+  disabled = false,
+  onClick = () => {},
+}: Props) => (
+  <BpkButtonV2
+    iconOnly
+    type={BUTTON_TYPES.link}
+    onClick={(e) => {
+      if (direction === DIRECTIONS.PREV) {
+        onClick(e, currentIndex - 1, direction);
+      } else {
+        onClick(e, currentIndex + 1, direction);
+      }
+    }}
+    aria-label={ariaLabel}
+    disabled={disabled}
+  >
+    {direction === DIRECTIONS.PREV ? (
+      <AlignedLeftArrowIcon />
+    ) : (
+      <AlignedRightArrowIcon />
+    )}
+  </BpkButtonV2>
+);
+
+export default NavButton;
diff --git a/packages/bpk-component-page-indicator/src/accessibility-test.js b/packages/bpk-component-page-indicator/src/accessibility-test.tsx
similarity index 98%
rename from packages/bpk-component-page-indicator/src/accessibility-test.js
rename to packages/bpk-component-page-indicator/src/accessibility-test.tsx
index fbfcb85d88..50d95264aa 100644
--- a/packages/bpk-component-page-indicator/src/accessibility-test.js
+++ b/packages/bpk-component-page-indicator/src/accessibility-test.tsx
@@ -15,7 +15,6 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-/* @flow strict */
 
 import { render } from '@testing-library/react';
 import { axe } from 'jest-axe';


Reviews:
user: login: senzg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T03:06:55Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR adds TypeScript support for the BpkPageIndicator component and updates related files to remove Flow types and PropTypes while improving type safety.  
- Migrated components from Flow to TypeScript by replacing PropTypes and defaultProps with proper interfaces and default values.  
- Updated related tests, examples, and the carousel integration to align with the new type definitions.

### Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.

<details>
<summary>Show a summary per file</summary>

| File | Description |
| ---- | ----------- |
| packages/bpk-component-page-indicator/src/NavButton.tsx | Updated type definitions and removed PropTypes to use TypeScript's type system. |
| packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx | Replaced PropTypes and Flow types with TypeScript interfaces and default values. |
| packages/bpk-component-page-indicator/src/BpkPageIndicator-test.tsx | Improved test props typing for better type safety. |
| packages/bpk-component-page-indicator/index.ts | Adjusted type imports and exports for consistency. |
| packages/bpk-component-carousel/src/BpkCarousel.tsx | Removed the ts-expect-error suppression; ensure compatibility with updated types. |
| examples/bpk-component-page-indicator/stories.tsx | Updated Storybook stories using the CSF object notation. |
| examples/bpk-component-page-indicator/examples.tsx | Added explicit type annotations to example container component props. |
</details>



<details>
<summary>Comments suppressed due to low confidence (1)</summary>

**packages/bpk-component-carousel/src/BpkCarousel.tsx:20**
* The removal of the ts-expect-error suppression comment implies that the type definitions for BpkPageIndicator should now be correct. Please verify that no TypeScript errors are introduced due to this change.
```
// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T03:10:45Z
user: login: gc-skyscanner
body: we also need to remove the ` /* @flow strict */` in `packages/bpk-component-page-indicator/src/accessibility-test.tsx`

state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T08:58:29Z
user: login: senzg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T09:24:59Z
user: login: senzg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T09:32:55Z
user: login: senzg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T09:36:13Z
user: login: senzg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T10:05:30Z
user: login: senzg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T10:09:55Z
user: login: senzg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T10:22:27Z
user: login: gc-skyscanner
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T06:55:26Z
user: login: gc-skyscanner
body: LGTM
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-07T08:08:45Z

Review comments:
diff_hunk: @@ -36,7 +36,13 @@ export const ThreePages = ThreePagesExample;
 export const OverImage = OverImageExample;
 export const WithNav = WithNavExample;
 export const VisualTest = VisualTestExample;
-export const VisualTestWithZoom = VisualTest.bind({});
-VisualTestWithZoom.args = {
-  zoomEnabled: true
-};
+// export const VisualTestWithZoom = VisualTest.bind({});
path: examples/bpk-component-page-indicator/stories.tsx
user: login: senzg
body: This is a mistake forgetting to remove the commented code. I will fix it soon
created_at: 2025-04-03T03:06:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+declare module 'jest-axe' {
path: @types/jest-axe.d.ts
user: login: gc-skyscanner
body: It seems we don't need this. we already have` @types/jest-axe` in the code https://github.com/Skyscanner/backpack/blob/main/package.json#L141
created_at: 2025-04-03T07:53:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -6,6 +6,7 @@
       "dom.iterable",
       "esnext"
     ],
+    "typeRoots": ["./node_modules/@types", "./types"],
path: tsconfig.json
user: login: gc-skyscanner
body: https://www.typescriptlang.org/tsconfig/#typeRoots
I think we don't need this config at the moment, because `node_modules/@types` and `@types` are included by default
created_at: 2025-04-03T07:58:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -22,9 +22,18 @@ import '@testing-library/jest-dom';
 
 import BpkPageIndicator from './BpkPageIndicator';
 
-let props;
-
 describe('BpkPageIndicator', () => {
+  let props: {
path: packages/bpk-component-page-indicator/src/BpkPageIndicator-test.tsx
user: login: gc-skyscanner
body: I think it would be better if we reuse the type defined in  `packages/bpk-component-carousel/src/BpkCarousel.tsx`
created_at: 2025-04-03T08:04:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -22,9 +22,18 @@ import '@testing-library/jest-dom';
 
 import BpkPageIndicator from './BpkPageIndicator';
 
-let props;
path: packages/bpk-component-page-indicator/src/BpkPageIndicator-test.tsx
user: login: gc-skyscanner
body: Also, I think we might need to remove  `/* @flow strict */` in this file
https://github.com/Skyscanner/backpack/blob/8e43963066ab53bb3869efe9f151e1a8955f9032/packages/bpk-component-page-indicator/src/BpkPageIndicator-test.tsx#L18
created_at: 2025-04-03T08:05:17Z
author_association: CONTRIBUTOR
diff_hunk: @@ -18,11 +18,13 @@
 /* @flow strict */
path: packages/bpk-component-page-indicator/index.ts
user: login: gc-skyscanner
body: We might need to remove this, since this file has been migrated to ts
created_at: 2025-04-03T08:05:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -32,7 +32,8 @@ const image =
   'https://content.skyscnr.com/m/50d9dff3186775ad/original/Condor-Homepage-Hero-Option-3.png';
 const imageWidth = 400;
 const imageHeight = 90;
-const PageIndicatorContainer = (props) => {
+type Variant = typeof VARIANT[keyof typeof VARIANT];
+const PageIndicatorContainer = (props: { totalIndicators: number; showNav?: boolean; variant?: Variant; className?: string}) => {
path: examples/bpk-component-page-indicator/examples.tsx
user: login: gc-skyscanner
body: ```suggestion
type PageIndicatorContainerProps = Omit<BpkPageIndicatorProps, 'currentIndex'>;
const PageIndicatorContainer = (props: PageIndicatorContainerProps) => {
```

created_at: 2025-04-03T08:23:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -18,7 +18,6 @@
 
 import { useRef, useState } from 'react';
 
-// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
path: packages/bpk-component-carousel/src/BpkCarousel.tsx
user: login: gc-skyscanner
body: 👍 
created_at: 2025-04-03T08:23:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -17,8 +17,6 @@
  */
 /* @flow strict */
path: packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx
user: login: gc-skyscanner
body: Remove this please 😄 
created_at: 2025-04-03T08:24:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -17,8 +17,6 @@
  */
 /* @flow strict */
 
path: packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx
user: login: gc-skyscanner
body: We also need to remove  this 👇 https://github.com/Skyscanner/backpack/blob/8e43963066ab53bb3869efe9f151e1a8955f9032/packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx#L74
created_at: 2025-04-03T08:27:40Z
author_association: CONTRIBUTOR
diff_hunk: @@ -33,30 +31,37 @@ const START_SCROLL_INDEX = Math.floor(DISPLAYED_TOTAL / 2);
 export const VARIANT = {
   default: 'default',
   overImage: 'overImage',
-};
+} as const;
 
-export type Props = {
-  className: ?string,
-  showNav: ?boolean,
+type Variant = typeof VARIANT[keyof typeof VARIANT];
+type Direction = typeof DIRECTIONS[keyof typeof DIRECTIONS];
+
+export interface Props {
+  indicatorLabel?: string,
+  prevNavLabel?: string,
+  nextNavLabel?: string,
   currentIndex: number,
   totalIndicators: number,
-  onClick: ?() => void,
-  indicatorLabel: string,
-  prevNavLabel: string,
-  nextNavLabel: string,
-  variant: ?$Keys<typeof VARIANT>,
-};
+  variant?: Variant,
+  onClick?: (
+    event: React.MouseEvent<HTMLButtonElement>,
+    newIndex: number,
+    direction: Direction,
+  ) => void,
+  className?: string,
+  showNav?: boolean,
+}
 
-const BpkPageIndicator = ({
-  className,
+const BpkPageIndicator: React.FC<Props> = ({
path: packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx
user: login: gc-skyscanner
body: ```suggestion
const BpkPageIndicator = ({
```
created_at: 2025-04-03T08:29:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -33,30 +31,37 @@ const START_SCROLL_INDEX = Math.floor(DISPLAYED_TOTAL / 2);
 export const VARIANT = {
   default: 'default',
   overImage: 'overImage',
-};
+} as const;
 
-export type Props = {
-  className: ?string,
-  showNav: ?boolean,
+type Variant = typeof VARIANT[keyof typeof VARIANT];
+type Direction = typeof DIRECTIONS[keyof typeof DIRECTIONS];
+
+export interface Props {
+  indicatorLabel?: string,
+  prevNavLabel?: string,
+  nextNavLabel?: string,
   currentIndex: number,
   totalIndicators: number,
-  onClick: ?() => void,
-  indicatorLabel: string,
-  prevNavLabel: string,
-  nextNavLabel: string,
-  variant: ?$Keys<typeof VARIANT>,
-};
+  variant?: Variant,
+  onClick?: (
+    event: React.MouseEvent<HTMLButtonElement>,
path: packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx
user: login: gc-skyscanner
body: ```suggestion
     import type { MouseEvent } from 'react';
...
    event: MouseEvent<HTMLButtonElement>,
```
created_at: 2025-04-03T08:29:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -93,14 +98,14 @@ const BpkPageIndicator = ({
             style={
               currentIndex > START_SCROLL_INDEX
                 ? {
-                  '--scroll-index':
-                    totalIndicators > DISPLAYED_TOTAL
-                      ? Math.min(
-                        currentIndex - START_SCROLL_INDEX,
-                        totalIndicators - DISPLAYED_TOTAL,
-                      )
-                      : 0,
-                }
+                    '--scroll-index': 
+                      totalIndicators > DISPLAYED_TOTAL
+                        ? Math.min(
+                          currentIndex - START_SCROLL_INDEX,
+                          totalIndicators - DISPLAYED_TOTAL,
+                        )
+                        : 0,
+                  } as React.CSSProperties
path: packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx
user: login: gc-skyscanner
body: As I remember in banana, we are not recommending to use type assertion, therefore, i would prefer

```
import type { CSSProperties } from 'react';
...
type CustomCSSProperties = CSSProperties & {
  '--scroll-index'?: number;
}
  const customStyle: CustomCSSProperties = {
    '--scroll-index':
      totalIndicators > DISPLAYED_TOTAL
        ? Math.min(
          currentIndex - START_SCROLL_INDEX,
          totalIndicators - DISPLAYED_TOTAL,
        )
        : 0,
  }

      <div
        className={getClassName('bpk-page-indicator__indicators-container')}
        style={
          currentIndex > START_SCROLL_INDEX
            ? customStyle
            : undefined
        }
      >
...


```
created_at: 2025-04-03T08:48:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -17,8 +17,6 @@
  */
 /* @flow strict */
path: packages/bpk-component-page-indicator/src/NavButton.tsx
user: login: gc-skyscanner
body: We need to remove this
created_at: 2025-04-03T08:49:59Z
author_association: CONTRIBUTOR
diff_hunk: @@ -28,24 +26,34 @@ export const DIRECTIONS = {
   PREV: 'PREV',
   INDICATORS: 'INDICATORS',
   NEXT: 'NEXT',
-};
+} as const;
 
-type Props = {
-  direction: $Keys<typeof DIRECTIONS>,
-  disabled?: boolean,
+type Direction = typeof DIRECTIONS[keyof typeof DIRECTIONS];
+
+interface Props {
+  ariaLabel: string | undefined,
   currentIndex: number,
-  onClick: ?() => void,
-  ariaLabel: string,
+  direction: Direction,
+  disabled?: boolean,
+  onClick?: (
+    event: React.MouseEvent<HTMLButtonElement>,
+    newIndex: number,
+    direction: Direction,
+  ) => void,
 };
 
 const AlignedLeftArrowIcon = withButtonAlignment(withRtlSupport(LeftArrowIcon));
 const AlignedRightArrowIcon = withButtonAlignment(
   withRtlSupport(RightArrowIcon),
 );
 
-const NavButton = (props: Props) => {
-  const { ariaLabel, currentIndex, direction, disabled, onClick } = props;
-  return (
+const NavButton: React.FC<Props> = ({
path: packages/bpk-component-page-indicator/src/NavButton.tsx
user: login: gc-skyscanner
body: ```suggestion
const NavButton = ({
```
created_at: 2025-04-03T08:53:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -28,24 +26,34 @@ export const DIRECTIONS = {
   PREV: 'PREV',
   INDICATORS: 'INDICATORS',
   NEXT: 'NEXT',
-};
+} as const;
 
-type Props = {
-  direction: $Keys<typeof DIRECTIONS>,
-  disabled?: boolean,
+type Direction = typeof DIRECTIONS[keyof typeof DIRECTIONS];
+
+interface Props {
path: packages/bpk-component-page-indicator/src/NavButton.tsx
user: login: gc-skyscanner
body: Why we change it from type to interface here?
created_at: 2025-04-03T08:57:24Z
author_association: CONTRIBUTOR
diff_hunk: @@ -33,30 +31,37 @@ const START_SCROLL_INDEX = Math.floor(DISPLAYED_TOTAL / 2);
 export const VARIANT = {
   default: 'default',
   overImage: 'overImage',
-};
+} as const;
 
-export type Props = {
-  className: ?string,
-  showNav: ?boolean,
+type Variant = typeof VARIANT[keyof typeof VARIANT];
+type Direction = typeof DIRECTIONS[keyof typeof DIRECTIONS];
+
+export interface Props {
path: packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx
user: login: gc-skyscanner
body: Why we change it to interface here?
created_at: 2025-04-03T08:57:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+declare module 'jest-axe' {
path: @types/jest-axe.d.ts
user: login: senzg
body: Interesting, without it, there were type-check errors for every import { axe } from 'jest-axe'; in TSX; while they are gone now even without it. I will delete it see if it passes the check
created_at: 2025-04-03T09:24:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -22,9 +22,18 @@ import '@testing-library/jest-dom';
 
 import BpkPageIndicator from './BpkPageIndicator';
 
-let props;
path: packages/bpk-component-page-indicator/src/BpkPageIndicator-test.tsx
user: login: senzg
body: Oh yes, didn't notice them. Removed!
created_at: 2025-04-03T09:32:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -17,8 +17,6 @@
  */
 /* @flow strict */
 
path: packages/bpk-component-page-indicator/src/BpkPageIndicator.tsx
user: login: senzg
body: Thank you! Didn't know about it
created_at: 2025-04-03T09:36:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -28,24 +26,34 @@ export const DIRECTIONS = {
   PREV: 'PREV',
   INDICATORS: 'INDICATORS',
   NEXT: 'NEXT',
-};
+} as const;
 
-type Props = {
-  direction: $Keys<typeof DIRECTIONS>,
-  disabled?: boolean,
+type Direction = typeof DIRECTIONS[keyof typeof DIRECTIONS];
+
+interface Props {
path: packages/bpk-component-page-indicator/src/NavButton.tsx
user: login: senzg
body: Yes you are right! 'type' adheres more to the style we do in this codebase, didn't notice it. Changed
created_at: 2025-04-03T10:05:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -28,24 +26,34 @@ export const DIRECTIONS = {
   PREV: 'PREV',
   INDICATORS: 'INDICATORS',
   NEXT: 'NEXT',
-};
+} as const;
 
-type Props = {
-  direction: $Keys<typeof DIRECTIONS>,
-  disabled?: boolean,
+type Direction = typeof DIRECTIONS[keyof typeof DIRECTIONS];
+
+interface Props {
+  ariaLabel: string | undefined,
   currentIndex: number,
-  onClick: ?() => void,
-  ariaLabel: string,
+  direction: Direction,
+  disabled?: boolean,
+  onClick?: (
+    event: React.MouseEvent<HTMLButtonElement>,
+    newIndex: number,
+    direction: Direction,
+  ) => void,
 };
 
 const AlignedLeftArrowIcon = withButtonAlignment(withRtlSupport(LeftArrowIcon));
 const AlignedRightArrowIcon = withButtonAlignment(
   withRtlSupport(RightArrowIcon),
 );
 
-const NavButton = (props: Props) => {
-  const { ariaLabel, currentIndex, direction, disabled, onClick } = props;
-  return (
+const NavButton: React.FC<Props> = ({
path: packages/bpk-component-page-indicator/src/NavButton.tsx
user: login: senzg
body: May I ask why should we remove this declaration?
created_at: 2025-04-03T10:09:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -6,6 +6,7 @@
       "dom.iterable",
       "esnext"
     ],
+    "typeRoots": ["./node_modules/@types", "./types"],
path: tsconfig.json
user: login: senzg
body: Removed. No error shows
created_at: 2025-04-03T10:22:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -28,24 +26,34 @@ export const DIRECTIONS = {
   PREV: 'PREV',
   INDICATORS: 'INDICATORS',
   NEXT: 'NEXT',
-};
+} as const;
 
-type Props = {
-  direction: $Keys<typeof DIRECTIONS>,
-  disabled?: boolean,
+type Direction = typeof DIRECTIONS[keyof typeof DIRECTIONS];
+
+interface Props {
+  ariaLabel: string | undefined,
   currentIndex: number,
-  onClick: ?() => void,
-  ariaLabel: string,
+  direction: Direction,
+  disabled?: boolean,
+  onClick?: (
+    event: React.MouseEvent<HTMLButtonElement>,
+    newIndex: number,
+    direction: Direction,
+  ) => void,
 };
 
 const AlignedLeftArrowIcon = withButtonAlignment(withRtlSupport(LeftArrowIcon));
 const AlignedRightArrowIcon = withButtonAlignment(
   withRtlSupport(RightArrowIcon),
 );
 
-const NavButton = (props: Props) => {
-  const { ariaLabel, currentIndex, direction, disabled, onClick } = props;
-  return (
+const NavButton: React.FC<Props> = ({
path: packages/bpk-component-page-indicator/src/NavButton.tsx
user: login: gc-skyscanner
body: I saw we didn't use `children` inside the component, as I remember, the function component will implicit the `children` by default,  It'll be a little redundant. What do you think?

created_at: 2025-04-07T06:55:26Z
author_association: CONTRIBUTOR

PR comments:
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-02T07:41:16Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-02T07:43:25Z
body: 
<!--
  0 failure: 
  2 warning:  Package source fi..., Package source fi...
  
  1 markdown notices
  DangerID: danger-id-Danger;
-->


<table>
  <thead>
    <tr>
      <th width="50"></th>
      <th width="100%" data-danger-table="true">Warnings</th>
    </tr>
  </thead>
  <tbody><tr>
      <td>:warning:</td>
      <td>

  Package source files (e.g. `packages/package-name/src/Component.js`) were updated, but snapshots weren't. Have you checked that the tests still pass?
  </td>
    </tr>
  
<tr>
      <td>:warning:</td>
      <td>

  Package source files (e.g. `packages/package-name/src/Component.tsx`) were updated, but type files weren't. Have you checked that no types have changed?
  </td>
    </tr>
  </tbody>
</table>



  ## Browser support

  If this is a visual change, make sure you've tested it in multiple browsers.
  
<p align="right">
  Generated by :no_entry_sign: <a href="https://danger.systems/js">dangerJS</a> against 6ed2b758cdf21e0d3cbdc5ab147cfea7bac3597e
</p>

author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-02T08:22:58Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-02T08:31:13Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-02T08:37:45Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-02T08:49:57Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-02T09:29:30Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-02T09:45:13Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-02T09:57:12Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-03T05:49:53Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: gc-skyscanner
created_at: 2025-04-03T08:59:57Z
body: I noticed the Percy failed here, I don't think the ts migration would cause the visual changes, could you help to check with it?
author_association: CONTRIBUTOR
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-03T09:27:37Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-03T09:30:25Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-03T09:37:25Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-03T09:42:55Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-03T10:11:02Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-07T06:03:20Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-07T06:27:31Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-07T07:15:05Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-07T07:51:52Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE
user: login: skyscanner-backpack-bot[bot]
created_at: 2025-04-07T08:01:24Z
body: Visit https://backpack.github.io/storybook-prs/3783 to see this build running in a browser.
author_association: NONE