Skip to content

Commit d29437c

Browse files
Merge pull request #3601 from openedx/ags/release-22-23-sync
Sync release-22.x into release-23.x
2 parents 444d7cc + 7bcd64d commit d29437c

12 files changed

+372
-265
lines changed

src/Alert/index.scss

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,15 @@
1515
border: var(--pgn-size-alert-border-width) solid var(--pgn-alert-border-color, transparent);
1616
color: inherit;
1717
background-color: var(--pgn-alert-bg, transparent);
18+
align-items: center;
1819

1920
@include border-radius(var(--pgn-size-alert-border-radius));
2021
@include pgn-box-shadow(1, "down");
2122

23+
&:has(.alert-heading:not(:only-child)) {
24+
align-items: start;
25+
}
26+
2227
.alert-message-content > :last-child {
2328
margin-bottom: 0;
2429
}

src/ProductTour/Checkpoint.jsx

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@ import { createPopper } from '@popperjs/core';
55
import { FormattedMessage } from 'react-intl';
66

77
import breakpoints from '../utils/breakpoints';
8-
98
import CheckpointActionRow from './CheckpointActionRow';
109
import CheckpointBody from './CheckpointBody';
11-
import CheckpointBreadcrumbs from './CheckpointBreadcrumbs';
12-
import CheckpointTitle from './CheckpointTitle';
10+
import CheckpointHeader from './CheckpointHeader';
1311
import messages from './messages';
1412

1513
const Checkpoint = React.forwardRef(({
1614
body,
15+
dismissAltText,
1716
index,
17+
onBack,
18+
onDismiss,
1819
placement,
1920
target,
2021
title,
@@ -87,7 +88,6 @@ const Checkpoint = React.forwardRef(({
8788
}, [target, checkpointVisible, placement]);
8889

8990
const isLastCheckpoint = index + 1 === totalCheckpoints;
90-
const isOnlyCheckpoint = totalCheckpoints === 1;
9191

9292
return (
9393
<div
@@ -104,14 +104,17 @@ const Checkpoint = React.forwardRef(({
104104
values={{ step: index + 1 }}
105105
/>
106106
</span>
107-
{(title || !isOnlyCheckpoint) && (
108-
<div className="pgn__checkpoint-header">
109-
<CheckpointTitle>{title}</CheckpointTitle>
110-
<CheckpointBreadcrumbs currentIndex={index} totalCheckpoints={totalCheckpoints} />
111-
</div>
112-
)}
107+
<CheckpointHeader
108+
dismissAltText={dismissAltText}
109+
index={index}
110+
onDismiss={onDismiss}
111+
title={title}
112+
totalCheckpoints={totalCheckpoints}
113+
/>
113114
<CheckpointBody>{body}</CheckpointBody>
114115
<CheckpointActionRow
116+
onBack={onBack}
117+
onDismiss={onDismiss}
115118
isLastCheckpoint={isLastCheckpoint}
116119
index={index}
117120
{...props}
@@ -129,28 +132,33 @@ const Checkpoint = React.forwardRef(({
129132

130133
Checkpoint.defaultProps = {
131134
advanceButtonText: null,
135+
backButtonText: null,
132136
body: null,
133-
dismissButtonText: null,
137+
dismissAltText: null,
134138
endButtonText: null,
135139
placement: 'top',
136140
title: null,
137-
showDismissButton: undefined,
138141
};
139142

140143
Checkpoint.propTypes = {
141144
/** The text displayed on the button used to advance the tour for the given Checkpoint. */
142145
advanceButtonText: PropTypes.node,
146+
/** The text displayed on the button used go back in the tour for the given Checkpoint. */
147+
backButtonText: PropTypes.string,
143148
/** The text displayed in the body of the Checkpoint */
144149
body: PropTypes.node,
145-
/** The text displayed on the button used to dismiss the tour for the given Checkpoint. */
146-
dismissButtonText: PropTypes.node,
150+
/** The text used in the alt for the icon used to dismiss the tour for the given Checkpoint */
151+
dismissAltText: PropTypes.string,
147152
/** The text displayed on the button used to end the tour for the given Checkpoint. */
148153
endButtonText: PropTypes.node,
149154
/** The current index of the given Checkpoint */
150155
index: PropTypes.number.isRequired,
151156
/** A function that runs when triggering the `onClick` event of the advance
152157
* button for the given Checkpoint. */
153158
onAdvance: PropTypes.func.isRequired,
159+
/** A function that runs when triggering the `onBack` event of the back
160+
* button for the given Checkpoint. */
161+
onBack: PropTypes.func.isRequired,
154162
/** A function that runs when triggering the `onClick` event of the dismiss
155163
* button for the given Checkpoint. */
156164
onDismiss: PropTypes.func.isRequired,
@@ -168,8 +176,6 @@ Checkpoint.propTypes = {
168176
title: PropTypes.node,
169177
/** The total number of Checkpoints in a tour */
170178
totalCheckpoints: PropTypes.number.isRequired,
171-
/** Enforces visibility of the dismiss button under all circumstances */
172-
showDismissButton: PropTypes.bool,
173179
};
174180

175181
export default Checkpoint;

src/ProductTour/Checkpoint.scss

Lines changed: 8 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
var(--pgn-size-product-tour-checkpoint-width-border)
88
solid var(--pgn-color-product-tour-checkpoint-border);
99
border-radius: var(--pgn-size-border-radius-base);
10-
padding: var(--pgn-spacing-spacer-4);
10+
padding: var(--pgn-spacing-spacer-3-5);
1111
box-shadow: 0 .25rem .5rem var(--pgn-color-product-tour-checkpoint-box-shadow);
1212
z-index: var(--pgn-elevation-product-tour-checkpoint-zindex);
1313
max-width: var(--pgn-size-product-tour-checkpoint-width-max);
@@ -44,39 +44,6 @@
4444
margin-inline-end: var(--pgn-spacing-spacer-2);
4545
}
4646

47-
.pgn__checkpoint-breadcrumb {
48-
height: 6px;
49-
width: 6px;
50-
border-radius: 50%;
51-
52-
&.pgn__checkpoint-breadcrumb_active {
53-
background: var(--pgn-color-product-tour-checkpoint-breadcrumb);
54-
}
55-
56-
&.pgn__checkpoint-breadcrumb_inactive {
57-
border: 1px solid var(--pgn-color-product-tour-checkpoint-breadcrumb);
58-
background: transparent;
59-
}
60-
61-
&:not(:first-child) {
62-
margin-left: map.get($spacers, 1\.5);
63-
}
64-
65-
[dir="rtl"] & {
66-
margin-left: map.get($spacers, 1\.5);
67-
margin-right: 0;
68-
69-
&:last-child {
70-
margin-left: 0;
71-
}
72-
}
73-
}
74-
75-
.pgn__checkpoint-breadcrumb-container {
76-
display: flex;
77-
align-items: center;
78-
}
79-
8047
.pgn__checkpoint-body {
8148
color: var(--pgn-color-product-tour-checkpoint-body);
8249
margin-bottom: map.get($spacers, 3\.5);
@@ -86,13 +53,18 @@
8653
.pgn__checkpoint-header {
8754
display: flex;
8855
justify-content: space-between;
89-
margin-bottom: map.get($spacers, 2\.5);
56+
margin-bottom: map.get($spacers, 2);
57+
align-items: center;
9058
}
9159

9260
#pgn__checkpoint-title {
9361
font-size: var(--pgn-typography-font-size-h3-base);
9462
margin-inline-end: map.get($spacers, 2\.5);
95-
margin-bottom: 0;
63+
margin-bottom: map.get($spacers, 2);;
64+
}
65+
66+
.pgn__checkpoint-page-index {
67+
font-size: $small-font-size;
9668
}
9769
}
9870

src/ProductTour/Checkpoint.test.jsx

Lines changed: 20 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ const popperMock = jest.spyOn(popper, 'createPopper');
1111

1212
describe('Checkpoint', () => {
1313
const handleAdvance = jest.fn();
14+
const handleBack = jest.fn();
1415
const handleDismiss = jest.fn();
1516
const handleEnd = jest.fn();
1617

@@ -29,11 +30,12 @@ describe('Checkpoint', () => {
2930
<div id="target-element">...</div>
3031
<Checkpoint
3132
advanceButtonText="Next"
33+
backButtonText="Back"
3234
body="Lorem ipsum checkpoint body"
33-
dismissButtonText="Dismiss"
3435
endButtonText="End"
3536
index={1}
3637
onAdvance={handleAdvance}
38+
onBack={handleBack}
3739
onDismiss={handleDismiss}
3840
onEnd={handleEnd}
3941
target="#target-element"
@@ -44,31 +46,22 @@ describe('Checkpoint', () => {
4446
);
4547
});
4648

47-
it('renders correct active breadcrumb', () => {
48-
expect(screen.getByText('Checkpoint title')).toBeInTheDocument();
49-
const breadcrumbs = screen.getAllByTestId('pgn__checkpoint-breadcrumb_', { exact: false });
50-
expect(breadcrumbs.length).toEqual(5);
51-
expect(breadcrumbs[0].classList).toContain('pgn__checkpoint-breadcrumb_inactive');
52-
expect(breadcrumbs[1].classList).toContain('pgn__checkpoint-breadcrumb_active');
53-
expect(breadcrumbs[2].classList).toContain('pgn__checkpoint-breadcrumb_inactive');
54-
expect(breadcrumbs[3].classList).toContain('pgn__checkpoint-breadcrumb_inactive');
55-
expect(breadcrumbs[4].classList).toContain('pgn__checkpoint-breadcrumb_inactive');
56-
});
57-
58-
it('only renders advance and dismiss buttons (i.e. does not render end button)', () => {
59-
expect(screen.getByRole('button', { name: 'Dismiss' })).toBeInTheDocument();
49+
it('only renders advance and back buttons (i.e. does not render end button)', () => {
50+
expect(screen.getByRole('button', { name: 'Back' })).toBeInTheDocument();
6051
expect(screen.getByRole('button', { name: 'Next' })).toBeInTheDocument();
6152
});
6253

63-
it('dismiss button onClick calls handleDismiss', async () => {
64-
const dismissButton = screen.getByRole('button', { name: 'Dismiss' });
65-
await userEvent.click(dismissButton);
66-
expect(handleDismiss).toHaveBeenCalledTimes(1);
54+
it('back button onClick calls handleBack', async () => {
55+
const user = userEvent.setup();
56+
const backButton = screen.getByRole('button', { name: 'Back' });
57+
await user.click(backButton);
58+
expect(handleBack).toHaveBeenCalledTimes(1);
6759
});
6860

6961
it('advance button onClick calls handleAdvance', async () => {
62+
const user = userEvent.setup();
7063
const advanceButton = screen.getByRole('button', { name: 'Next' });
71-
await userEvent.click(advanceButton);
64+
await user.click(advanceButton);
7265
expect(handleAdvance).toHaveBeenCalledTimes(1);
7366
});
7467
});
@@ -80,8 +73,9 @@ describe('Checkpoint', () => {
8073
<div id="#last-element" />
8174
<Checkpoint
8275
advanceButtonText="Next"
76+
backButtonText="Back"
8377
body="Lorem ipsum checkpoint body"
84-
dismissButtonText="Dismiss"
78+
dismissAltText="Escape"
8579
endButtonText="End"
8680
index={4}
8781
onAdvance={handleAdvance}
@@ -95,10 +89,15 @@ describe('Checkpoint', () => {
9589
);
9690
});
9791

98-
it('only renders end button (i.e. neither advance nor dismiss buttons)', () => {
92+
it('only renders end button (i.e. neither advance nor back buttons)', () => {
9993
expect(screen.getByText('End', { selector: 'button' })).toBeInTheDocument();
10094
});
10195

96+
it('uses customized alt text on the close icon', () => {
97+
const closeButton = screen.getByTestId('dismiss-tour');
98+
expect(closeButton).toHaveAttribute('aria-label', 'Escape');
99+
});
100+
102101
it('end button onClick calls handleEnd', async () => {
103102
const user = userEvent.setup({ pointerEventsCheck: PointerEventsCheckLevel.Never });
104103
const endButton = screen.getByText('End', { selector: 'button' });
@@ -115,7 +114,6 @@ describe('Checkpoint', () => {
115114
<Checkpoint
116115
advanceButtonText="Next"
117116
body="Lorem ipsum checkpoint body"
118-
dismissButtonText="Dismiss"
119117
endButtonText="End"
120118
index={0}
121119
onAdvance={handleAdvance}
@@ -132,36 +130,5 @@ describe('Checkpoint', () => {
132130
it('only renders end button (i.e. neither advance nor dismiss buttons)', () => {
133131
expect(screen.getByText('End', { selector: 'button' })).toBeInTheDocument();
134132
});
135-
136-
it('does not render breadcrumbs', () => {
137-
const breadcrumbs = screen.queryAllByTestId('pgn__checkpoint-breadcrumb_', { exact: false });
138-
expect(breadcrumbs.length).toEqual(0);
139-
});
140-
});
141-
142-
describe('only one Checkpoint in Tour and showDismissButton set to true', () => {
143-
it('it renders dismiss button and end button', () => {
144-
render(
145-
<IntlProvider locale="en" messages={{}}>
146-
<div id="#target-element" />
147-
<Checkpoint
148-
advanceButtonText="Next"
149-
body="Lorem ipsum checkpoint body"
150-
dismissButtonText="Dismiss"
151-
endButtonText="End"
152-
index={0}
153-
onAdvance={handleAdvance}
154-
onDismiss={handleDismiss}
155-
onEnd={handleEnd}
156-
target="#target-element"
157-
title="Checkpoint title"
158-
totalCheckpoints={1}
159-
showDismissButton
160-
/>
161-
</IntlProvider>,
162-
);
163-
expect(screen.getByText('Dismiss', { selector: 'button' })).toBeInTheDocument();
164-
expect(screen.getByText('End', { selector: 'button' })).toBeInTheDocument();
165-
});
166133
});
167134
});

0 commit comments

Comments
 (0)