Skip to content

Commit

Permalink
[LUNA-1092] [BpkSwapButton] Contribute to Backpack (#3181)
Browse files Browse the repository at this point in the history
* init commit for BpkSwapButton contribution

* import/export fixes to run correctly in Storybook

* Add visual test for Percy

* update snapshots

* add ReadMe

* Edit  ReadMe

* remove duplicate ally test

* fix boilerplate .d.ts file

* remove unecessary label

* update scss to remove some FSC controls styling to be applied in banana directly

* remove more unnecessary container styling

* rebuild css file

* remove unnecessary rtl styling

* update stories styling

* update styling

---------

Co-authored-by: Jenna <[email protected]>
  • Loading branch information
Jennahowieson and Jenna authored Jan 23, 2024
1 parent 1f9c303 commit b75eb7a
Show file tree
Hide file tree
Showing 12 changed files with 417 additions and 0 deletions.
30 changes: 30 additions & 0 deletions examples/bpk-component-swap-button/examples.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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 BpkSwapButton from '../../packages/bpk-component-swap-button';
import { action } from '../bpk-storybook-utils';

const DefaultExample = () => (

<div style={{ marginTop:'25px', marginLeft:'25px' }}>
<BpkSwapButton ariaLabel='Swap Button' ariaLiveTextProp='Swapped' onClick={action('Button clicked')}/>
</div>
);

export default DefaultExample ;
30 changes: 30 additions & 0 deletions examples/bpk-component-swap-button/stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* 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 BpkSwapButton from '../../packages/bpk-component-swap-button/src/BpkSwapButton';

import DefaultExample from './examples'

export default {
title: 'bpk-component-swap-button',
component: BpkSwapButton,
};

export const Default = DefaultExample;

export const VisualTest = DefaultExample;
21 changes: 21 additions & 0 deletions packages/bpk-component-swap-button/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# bpk-component-swap-button

> Backpack Swap Button component.
## Installation

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

## Usage

```ts
import BpkSwapButton from '@skyscanner/backpack-web/bpk-swap-button';

export default () =>
<BpkSwapButton
ariaLabel="Swap Button"
ariaLiveTextProps="Swapped"
onClick={() => {console.log('swap');
}}
/>;
```
24 changes: 24 additions & 0 deletions packages/bpk-component-swap-button/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 BpkSwapButton, {
type Props as BpkSwapButtonProps,
} from './src/BpkSwapButton.tsx';

export type { BpkSwapButtonProps };
export default BpkSwapButton;
24 changes: 24 additions & 0 deletions packages/bpk-component-swap-button/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 BpkSwapButton, {
type Props as BpkSwapButtonProps,
} from './src/BpkSwapButton';

export type { BpkSwapButtonProps };
export default BpkSwapButton;
44 changes: 44 additions & 0 deletions packages/bpk-component-swap-button/src/BpkSwapButton-test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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 { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import BpkSwapButton from './BpkSwapButton';

const props = {
onClick: jest.fn(),
ariaLabel: 'Swap Button',
ariaLiveTextProp: 'Swapped'
};

describe('BpkSwapButton', () => {
it('should render correctly', () => {
const { asFragment } = render(<BpkSwapButton {...props }/>);
expect(asFragment()).toMatchSnapshot();
});

it('calls onClick prop when clicked', async () => {
const mockOnClick = jest.fn();
render(<BpkSwapButton {...props} onClick={mockOnClick}/>);

await userEvent.click(screen.getByRole('button'));

expect(mockOnClick).toHaveBeenCalled();
});
});
29 changes: 29 additions & 0 deletions packages/bpk-component-swap-button/src/BpkSwapButton.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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.
*/

export type Props = {
ariaLabel: string;
ariaLiveTextProps: string;
onClick: () => void;
};
declare const BpkSwapButton: ({
ariaLabel,
ariaLiveTextProps,
onClick,
} : Props) => JSX.Element;
export default BpkSwapButton;
18 changes: 18 additions & 0 deletions packages/bpk-component-swap-button/src/BpkSwapButton.module.css
Original file line number Diff line number Diff line change
@@ -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)}}@layer bpk-component{.bpk-swap-button{width:2.5rem;height:2.5rem;transform:translateY(-50%) rotate(90deg)}@media (max-width: 48rem){.bpk-swap-button{transform:rotate(0deg)}}.bpk-swap-button :focus-visible{box-shadow:0 0 0 0.125rem #fff,0 0 0 0.25rem #0062e3}.bpk-swap-button__button{display:flex;width:100%;height:100%;justify-content:center;align-items:center;transition:transform 400ms;border:3px solid #05203c;border-radius:50%;background-color:#fff}@media (max-width: 48rem){.bpk-swap-button__button{border:2px solid #05203c}}.bpk-no-touch-support .bpk-swap-button__button:hover:not(:active):not(:disabled){background-color:#e0e3e5}:global(.bpk-no-touch-support) .bpk-swap-button__button:hover:not(:active):not(:disabled){background-color:#e0e3e5}.bpk-swap-button__icon{max-width:1rem;max-height:1rem}}
62 changes: 62 additions & 0 deletions packages/bpk-component-swap-button/src/BpkSwapButton.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 '../../bpk-mixins/index.scss';

@layer bpk-component {
.bpk-swap-button {
width: bpk-spacing-xxl();
height: bpk-spacing-xxl();
transform: translateY(-50%) rotate(90deg);

@include bpk-breakpoint-small-tablet {
transform: rotate(0deg);
}

:focus-visible {
box-shadow:
0 0 0 (bpk-spacing-sm() / 2) $bpk-surface-elevated-day,
0 0 0 bpk-spacing-sm() $bpk-text-link-day;
}

&__button {
display: flex;
width: 100%;
height: 100%;
justify-content: center;
align-items: center;
transition: transform $bpk-duration-base;
border: $bpk-border-size-xl solid $bpk-core-primary-day;
border-radius: 50%;
background-color: $bpk-surface-default-day;

@include bpk-breakpoint-small-tablet {
border: $bpk-border-size-lg solid $bpk-core-primary-day;
}

@include bpk-hover {
background-color: $bpk-surface-highlight-day;
}
}

&__icon {
max-width: bpk-spacing-base();
max-height: bpk-spacing-base();
}
}
}
73 changes: 73 additions & 0 deletions packages/bpk-component-swap-button/src/BpkSwapButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* 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 { useState } from 'react';

import { cssModules } from '../../bpk-react-utils';
import BpkAriaLive from '../../bpk-component-aria-live'
// @ts-expect-error Untyped import. See `decisions/imports-ts-suppressions.md`.
import SwapVertical from '../../bpk-component-icon/sm/swap--vertical';

import STYLES from './BpkSwapButton.module.scss';

const getClassName = cssModules(STYLES);

export type Props = {
onClick: () => void,
ariaLabel: string,
ariaLiveTextProp: string,
}
const BpkSwapButton = ( props: Props ) => {
const { ariaLabel, ariaLiveTextProp, onClick } = props;

const [rotationDegree, setRotationDegree] = useState(0);
const [ariaLiveText, setAriaLiveText] = useState('');

const handleRotation = () => {
if (rotationDegree === 0) {
setRotationDegree(-180);
} else {
setRotationDegree(0);
}
setAriaLiveText(ariaLiveTextProp);
// without set timeout, the aria-live text would not change and screenreader would read out 'swapped' for the first time only.
setTimeout(() => {
setAriaLiveText('');
}, 250);
};

return (
<div className={getClassName('bpk-swap-button')}>
<button
type="button"
className={getClassName('bpk-swap-button__button')}
style={{ transform: `rotate(${rotationDegree}deg)` }}
aria-label={ariaLabel}
onClick={() => {
onClick();
handleRotation();
}}
>
<SwapVertical className={getClassName('bpk-swap-button__icon')} />
</button>
<BpkAriaLive>{ariaLiveText}</BpkAriaLive>
</div>
);
};
export default BpkSwapButton;

Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`BpkSwapButton should render correctly 1`] = `
<DocumentFragment>
<div
class="bpk-swap-button"
>
<button
aria-label="Swap Button"
class="bpk-swap-button__button"
style="transform: rotate(0deg);"
type="button"
>
<svg
aria-hidden="true"
class="bpk-swap-button__icon"
style="width: 1rem; height: 1rem;"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M.44 8.56a1.5 1.5 0 010-2.12l4.5-4.5a1.5 1.5 0 012.12 0l4.5 4.5a1.5 1.5 0 01-2.12 2.12L7.5 6.622V19.5a1.5 1.5 0 01-3 0V6.621l-1.94 1.94a1.5 1.5 0 01-2.12 0zm12 6.88a1.5 1.5 0 000 2.12l4.5 4.5a1.5 1.5 0 002.12 0l4.5-4.5a1.5 1.5 0 00-2.12-2.12l-1.94 1.939V4.5a1.5 1.5 0 00-3 0v12.879l-1.94-1.94a1.5 1.5 0 00-2.12 0z"
/>
</svg>
</button>
<div
aria-live="polite"
class="bpk-aria-live bpk-aria-live--invisible"
/>
</div>
</DocumentFragment>
`;
Loading

0 comments on commit b75eb7a

Please sign in to comment.