Skip to content

Commit

Permalink
feat(CoachmarkOverlayElements): Add next/back callbacks and currentSt…
Browse files Browse the repository at this point in the history
…ep properties (#6548)

* feat: add on click back and next callbacks

* feat: add current step

* fix: bug with current step

* fix: bug with back button not showing (progress of carrousel not done)

* test: add tests for onnext
  • Loading branch information
gcattan authored Dec 12, 2024
1 parent 20f5787 commit 36bd4f9
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,18 @@ const children = `hello, world (${uuidv4()})`;
const dataTestId = uuidv4();
const className = `class-${uuidv4()}`;

const childrenContent = (
const childrenContent = [
<CoachmarkOverlayElement
key="element1"
title="Hello World"
description="this is a description test"
/>
);
/>,
<CoachmarkOverlayElement
key="element2"
title="Hello World"
description="this is a another description test"
/>,
];

const renderCoachmarkWithOverlayElements = (
{ ...rest } = {},
Expand Down Expand Up @@ -165,4 +171,22 @@ describe(componentName, () => {

expect(screen.getByRole('img')).toBeInTheDocument();
});

it('calls onNext', async () => {
const user = userEvent.setup();
const onNext = jest.fn();
renderCoachmarkWithOverlayElements({
'data-testid': dataTestId,
onNext,
});
const beaconOrButton = screen.getByRole('button', {
name: 'Show information',
});
await act(() => user.click(beaconOrButton));
const nextButton = screen.getByRole('button', {
name: 'Next',
});
await act(() => user.click(nextButton));
await expect(onNext).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,18 @@ export interface CoachmarkOverlayElementsProps {
* The label for the Close button.
*/
closeButtonLabel?: string;
/**
* Callback called when clicking on the Next button.
*/
onNext?: () => void;
/**
* Callback called when clicking on the Previous button.
*/
onBack?: () => void;
/**
* Current step of the coachmarks.
*/
currentStep?: number;
}

// NOTE: the component SCSS is not imported here: it is rolled up separately.
Expand All @@ -96,6 +108,9 @@ const defaults = {
nextButtonText: 'Next',
previousButtonLabel: 'Back',
closeButtonLabel: 'Got it',
onNext: undefined,
onBack: undefined,
currentStep: 0,
};
/**
* Composable container to allow for the displaying of CoachmarkOverlayElement
Expand All @@ -112,9 +127,12 @@ export let CoachmarkOverlayElements = React.forwardRef<
isVisible = defaults.isVisible,
media,
renderMedia,
currentStep = defaults.currentStep,
nextButtonText = defaults.nextButtonText,
previousButtonLabel = defaults.previousButtonLabel,
closeButtonLabel = defaults.closeButtonLabel,
onNext = defaults.onNext,
onBack = defaults.onBack,
// Collect any other property values passed in.
...rest
},
Expand All @@ -123,7 +141,7 @@ export let CoachmarkOverlayElements = React.forwardRef<
const buttonFocusRef = useRef<ButtonProps<any> | undefined>(undefined);
const scrollRef = useRef<CarouselProps | undefined>(undefined);
const [scrollPosition, setScrollPosition] = useState(0);
const [currentProgStep, _setCurrentProgStep] = useState(0);
const [currentProgStep, _setCurrentProgStep] = useState(currentStep);
const coachmark = useCoachmark();
const hasMedia = media || renderMedia;

Expand All @@ -145,6 +163,16 @@ export let CoachmarkOverlayElements = React.forwardRef<
[currentProgStep, renderMedia]
);

useEffect(() => {
// When current step is set by props
// scroll to the appropriate view on the carrousel
const targetStep = clamp(currentStep, progStepFloor, progStepCeil);

scrollRef?.current?.scrollToView?.(targetStep);
// Avoid circular call to this hook
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentStep]);

useEffect(() => {
// On mount, one of the two primary buttons ("next" or "close")
// will be rendered and must have focus. (a11y)
Expand Down Expand Up @@ -222,7 +250,6 @@ export let CoachmarkOverlayElements = React.forwardRef<
) : (
<>
<Carousel
disableArrowScroll
ref={scrollRef as RefObject<HTMLDivElement>}
onScroll={(scrollPercent) => {
setScrollPosition(scrollPercent);
Expand All @@ -248,6 +275,7 @@ export let CoachmarkOverlayElements = React.forwardRef<
);
scrollRef?.current?.scrollToView?.(targetStep);
setCurrentProgStep(targetStep);
onBack?.();
}}
>
{previousButtonLabel}
Expand All @@ -268,6 +296,7 @@ export let CoachmarkOverlayElements = React.forwardRef<
);
scrollRef?.current?.scrollToView?.(targetStep);
setCurrentProgStep(targetStep);
onNext?.();
}}
>
{nextButtonText}
Expand Down Expand Up @@ -320,6 +349,10 @@ CoachmarkOverlayElements.propTypes = {
* The label for the Close button.
*/
closeButtonLabel: PropTypes.string,
/**
* Current step of the coachmarks
*/
currentStep: PropTypes.number,
/**
* The visibility of CoachmarkOverlayElements is
* managed in the parent component.
Expand All @@ -344,6 +377,14 @@ CoachmarkOverlayElements.propTypes = {
* The label for the Next button.
*/
nextButtonText: PropTypes.string,
/**
* Optional callback called when clicking on the Previous button.
*/
onBack: PropTypes.func,
/**
* Optional callback called when clicking on the Next button.
*/
onNext: PropTypes.func,
/**
* The label for the Previous button.
*/
Expand Down

0 comments on commit 36bd4f9

Please sign in to comment.