Skip to content

Commit ecef296

Browse files
authored
[QUAR-497] [BpkInsetBanner] Add CTA button & popover (#3732)
[QUAR-497] [BpkInsetBanner] Add CTA button & popover (#3732) * [QUAR-497] Update BpkInsetBanner to include CTA btn * Update BpkInsetBanner.module.scss * [QUAR-497] update stories and readme * [QUAR-497] adjust styling * [QUAR-487] update CTA field names * [QUAR-497] update inset banner test * Update accessibility-test.tsx * Update README.md * Update BpkInsetBanner.tsx
1 parent 68f8f95 commit ecef296

File tree

7 files changed

+157
-6
lines changed

7 files changed

+157
-6
lines changed

examples/bpk-component-inset-banner/examples.tsx

+21
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,31 @@ const WithBodyTextAndLinkExampleDark = () => (
8585
/>
8686
);
8787

88+
const WithCtaTextAndPopoverExampleLight = () => (
89+
<BpkInsetBanner
90+
title="Lorem ipsum"
91+
subheadline="Lorem ipsum dolor sit amet"
92+
logo="https://content.skyscnr.com/m/49503c4388cb05ab/original/Skyland_Black_172x96.png"
93+
callToAction={{
94+
text: 'Sponsored',
95+
popoverMessage: 'This is a popover message',
96+
closeBtnIcon: true,
97+
labelTitle: true,
98+
popverLabel: 'Info',
99+
buttonCloseLabel: 'Close',
100+
buttonA11yLabel: 'More info',
101+
}}
102+
backgroundColor="#FFE300"
103+
variant={VARIANT.onLight}
104+
accessibilityLabel="Sponsored by Skyscanner"
105+
/>
106+
);
107+
88108
export {
89109
DefaultExampleTitleOnly,
90110
DefaultExampleTitleAndSubheadline,
91111
WithLogoAndCtaTextExampleLight,
92112
WithBodyTextExampleLight,
93113
WithBodyTextAndLinkExampleDark,
114+
WithCtaTextAndPopoverExampleLight,
94115
};

examples/bpk-component-inset-banner/stories.ts

+2
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import {
2424
WithLogoAndCtaTextExampleLight,
2525
WithBodyTextExampleLight,
2626
WithBodyTextAndLinkExampleDark,
27+
WithCtaTextAndPopoverExampleLight,
2728
} from './examples';
2829

2930
export default {
@@ -38,3 +39,4 @@ export const WithBodyTextLight = WithBodyTextExampleLight;
3839
export const WithBodyTextAndLinkDark = WithBodyTextAndLinkExampleDark;
3940
export const VisualTestDark = WithBodyTextAndLinkExampleDark;
4041
export const VisualTestLight = WithLogoAndCtaTextExampleLight;
42+
export const WithCtaTextAndPopoverLight = WithCtaTextAndPopoverExampleLight;

packages/bpk-component-inset-banner/README.md

+8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ export default () => (
2222
}}
2323
callToAction={{
2424
text: 'Sponsored',
25+
popoverMessage: 'This is a popover message',
26+
popoverPlacement: 'top',
27+
buttonCloseLabel: 'Close',
28+
buttonA11yLabel: 'More info',
29+
popverLabel: 'More info',
30+
popoverId: 'popover',
31+
labelTitle: true,
32+
closeBtnIcon: false,
2533
}}
2634
logo="logo.png"
2735
subheadline="My subheadline"

packages/bpk-component-inset-banner/src/BpkInsetBanner-test.tsx

+23-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* limitations under the License.
1717
*/
1818

19-
import { render } from '@testing-library/react';
19+
import { render, screen, fireEvent } from '@testing-library/react';
2020

2121
import '@testing-library/jest-dom';
2222

@@ -52,6 +52,28 @@ describe('BpkInsetBanner', () => {
5252
expect(getByText('Sponsored')).toBeInTheDocument();
5353
});
5454

55+
it('should render call to action popover text if provided', () => {
56+
render(
57+
<BpkInsetBanner
58+
title="Lorem ipsum"
59+
subheadline="Lorem ipsum dolor sit amet"
60+
logo="https://content.skyscnr.com/m/7950ed6f30581485/Medium-Skyscanner-Vertical-White.png"
61+
backgroundColor="#F55D42"
62+
callToAction={{
63+
text: 'Sponsored',
64+
popoverMessage: 'Popover message',
65+
}}
66+
variant={VARIANT.onDark}
67+
/>,
68+
);
69+
70+
const ctaButton = screen.getByTestId('adInfoBtn');
71+
72+
fireEvent.click(ctaButton);
73+
74+
expect(screen.getByText('Popover message')).toBeInTheDocument();
75+
});
76+
5577
it('should render body if provided', () => {
5678
const { getByRole } = render(
5779
<BpkInsetBanner

packages/bpk-component-inset-banner/src/BpkInsetBanner.module.scss

+25
Original file line numberDiff line numberDiff line change
@@ -60,9 +60,34 @@
6060
flex-direction: column;
6161
}
6262

63+
&--cta-text {
64+
display: flex;
65+
align-items: center;
66+
}
67+
68+
&--cta-button {
69+
all: unset;
70+
71+
&:focus-visible {
72+
@include utils.bpk-focus-indicator;
73+
}
74+
}
75+
6376
&--cta-container {
6477
display: flex;
6578
align-items: center;
79+
cursor: pointer;
80+
}
81+
82+
&--cta-content {
83+
display: flex;
84+
align-items: center;
85+
}
86+
87+
&--cta-info-icon {
88+
display: flex;
89+
align-items: center;
90+
margin-inline-start: tokens.bpk-spacing-md();
6691
}
6792
}
6893

packages/bpk-component-inset-banner/src/BpkInsetBanner.tsx

+72-5
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@
1717
*/
1818
import { surfaceHighlightDay } from '@skyscanner/bpk-foundations-web/tokens/base.es6';
1919

20+
import InfoIcon from '../../bpk-component-icon/sm/information-circle';
21+
import BpkPopover from '../../bpk-component-popover/src/BpkPopover';
2022
import BpkText, { TEXT_STYLES } from '../../bpk-component-text/src/BpkText';
2123
import { cssModules } from '../../bpk-react-utils';
2224

25+
import type { Placement } from '@floating-ui/react';
26+
2327
import STYLES from './BpkInsetBanner.module.scss';
2428

2529
const getClassName = cssModules(STYLES);
@@ -37,9 +41,16 @@ export type Props = {
3741
link?: string;
3842
linkText?: string;
3943
};
40-
// [TO-DO] In future iteration we will add a button to CTA section with popover functionality
4144
callToAction?: {
4245
text?: string;
46+
popoverMessage?: string;
47+
popoverPlacement?: Placement;
48+
buttonCloseLabel?: string;
49+
buttonA11yLabel?: string;
50+
popverLabel?: string;
51+
popoverId?: string;
52+
labelTitle?: boolean;
53+
closeBtnIcon?: boolean;
4354
};
4455
logo?: string;
4556
subheadline?: string;
@@ -86,13 +97,69 @@ const BpkInsetBanner = ({
8697
<BpkText textStyle={TEXT_STYLES.caption}>{subheadline}</BpkText>
8798
</div>
8899
</div>
89-
<div className={getClassName('bpk-inset-banner--cta-container')}>
90-
{callToAction?.text && (
100+
{callToAction && callToAction.popoverMessage && (
101+
<div
102+
role="presentation"
103+
className={getClassName('bpk-inset-banner--cta-container')}
104+
onClick={(e) => {
105+
// Do not propagate the click on the trigger OR popover content up the DOM tree.
106+
e.stopPropagation();
107+
e.preventDefault();
108+
}}
109+
>
110+
<BpkPopover
111+
id={callToAction?.popoverId || ''}
112+
label={callToAction?.popverLabel || ''}
113+
placement={callToAction?.popoverPlacement || 'bottom'}
114+
onClose={(e: {
115+
stopPropagation: () => void;
116+
preventDefault: () => void;
117+
}) => {
118+
e.stopPropagation();
119+
e.preventDefault();
120+
}}
121+
closeButtonText={callToAction?.buttonCloseLabel}
122+
closeButtonIcon={callToAction?.closeBtnIcon}
123+
labelAsTitle={callToAction?.labelTitle}
124+
target={
125+
<button
126+
aria-label={callToAction?.buttonA11yLabel}
127+
className={getClassName('bpk-inset-banner--cta-button')}
128+
data-testid="adInfoBtn"
129+
aria-hidden="false"
130+
type="button"
131+
>
132+
<div
133+
className={getClassName('bpk-inset-banner--cta-content')}
134+
>
135+
{callToAction?.text && (
136+
<BpkText textStyle={TEXT_STYLES.caption}>
137+
{callToAction.text}
138+
</BpkText>
139+
)}
140+
141+
<div
142+
className={getClassName(
143+
'bpk-inset-banner--cta-info-icon',
144+
)}
145+
>
146+
<InfoIcon />
147+
</div>
148+
</div>
149+
</button>
150+
}
151+
>
152+
<BpkText tagName="p">{callToAction?.popoverMessage}</BpkText>
153+
</BpkPopover>
154+
</div>
155+
)}
156+
{callToAction && !callToAction.popoverMessage && callToAction.text && (
157+
<div className={getClassName('bpk-inset-banner--cta-text')}>
91158
<BpkText textStyle={TEXT_STYLES.caption}>
92159
{callToAction.text}
93160
</BpkText>
94-
)}
95-
</div>
161+
</div>
162+
)}
96163
</div>
97164
{body && (
98165
<div className={getClassName('bpk-inset-banner-body-container')}>

packages/bpk-component-inset-banner/src/accessibility-test.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ describe('BpkInsetBanner accessibility tests', () => {
3131
backgroundColor="#F55D42"
3232
callToAction={{
3333
text: 'Sponsored',
34+
popoverMessage: 'This is a popover message',
35+
closeBtnIcon: true,
36+
labelTitle: true,
37+
popverLabel: 'Info',
38+
buttonCloseLabel: 'Close',
39+
buttonA11yLabel: 'More info',
3440
}}
3541
body={{
3642
text: 'You can change your destination, date of travel, or both, with no change fee. Valid for all new bookings made up to 31 May for travel between now and 31 December 2020.',

0 commit comments

Comments
 (0)