Skip to content

Commit be41d94

Browse files
animations guided tour: Add ending page and better mobile support
Also updated imports locations so hot reloads work properly
1 parent 336064b commit be41d94

6 files changed

Lines changed: 189 additions & 52 deletions

File tree

packages/react-core/src/demos/Animations/Animations.md

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,13 @@ import l_gallery_GridTemplateColumns_min from '@patternfly/react-tokens/dist/esm
2525
import {applicationsData} from './examples/ResourceTableData.jsx';
2626
import SkeletonTable from "@patternfly/react-component-groups/dist/dynamic/SkeletonTable";
2727
import t_global_text_color_subtle from '@patternfly/react-tokens/dist/esm/t_global_text_color_subtle';
28-
import { AnimationsOverview } from '@patternfly/react-core/dist/js/demos/Animations/AnimationsOverview';
29-
import { AnimationsNotificationsDrawer } from '@patternfly/react-core/dist/js/demos/Animations/AnimationsNotificationsDrawer';
30-
import { AnimationsHeaderToolbar } from '@patternfly/react-core/dist/js/demos/Animations/AnimationsHeaderToolbar';
31-
import { AnimationsTourModal } from '@patternfly/react-core/dist/js/demos/Animations/AnimationsTourModal';
32-
import { AnimationsCreateDatabaseForm } from '@patternfly/react-core/dist/js/demos/Animations/AnimationsCreateDatabaseForm';
33-
import { GuidedTourProvider, useGuidedTour } from '@patternfly/react-core/dist/js/demos/Animations/GuidedTourContext';
28+
import { AnimationsOverview } from '@patternfly/react-core/dist/esm/demos/Animations/AnimationsOverview';
29+
import { AnimationsNotificationsDrawer } from '@patternfly/react-core/dist/esm/demos/Animations/AnimationsNotificationsDrawer';
30+
import { AnimationsHeaderToolbar } from '@patternfly/react-core/dist/esm/demos/Animations/AnimationsHeaderToolbar';
31+
import { AnimationsStartTourModal } from '@patternfly/react-core/dist/esm/demos/Animations/AnimationsStartTourModal';
32+
import { AnimationsEndTourModal } from '@patternfly/react-core/dist/esm/demos/Animations/AnimationsEndTourModal';
33+
import { AnimationsCreateDatabaseForm } from '@patternfly/react-core/dist/esm/demos/Animations/AnimationsCreateDatabaseForm';
34+
import { GuidedTourProvider, useGuidedTour } from '@patternfly/react-core/dist/esm/demos/Animations/GuidedTourContext';
3435

3536
## Demos
3637

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { FunctionComponent } from 'react';
2+
import { Button, Content, Modal, ModalBody, ModalFooter, ModalHeader, ModalVariant } from '../../index';
3+
import { useGuidedTour } from './GuidedTourContext';
4+
5+
export const AnimationsEndTourModal: FunctionComponent = () => {
6+
const { onStart, onFinish } = useGuidedTour();
7+
8+
return (
9+
<Modal
10+
variant={ModalVariant.small}
11+
isOpen
12+
onClose={onFinish}
13+
aria-labelledby="guided-tour-title"
14+
aria-describedby="guided-tour-description"
15+
>
16+
<ModalHeader title="This concludes the tour" labelId="guided-tour-title" />
17+
<ModalBody id="guided-tour-description">
18+
<Content component="p">Come back again to see the progress we've been making!</Content>
19+
</ModalBody>
20+
<ModalFooter>
21+
<Button key="end" variant="primary" onClick={onFinish}>
22+
End tour
23+
</Button>
24+
<Button key="restart" variant="link" onClick={onStart}>
25+
Restart tour
26+
</Button>
27+
</ModalFooter>
28+
</Modal>
29+
);
30+
};

packages/react-core/src/demos/Animations/AnimationsHeaderToolbar.tsx

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,13 +80,7 @@ export const AnimationsHeaderToolbar: FunctionComponent<Props> = ({
8080
/>
8181
)}
8282
</ToolbarItem>
83-
<ToolbarGroup
84-
variant="action-group-plain"
85-
visibility={{
86-
default: 'hidden',
87-
lg: 'visible'
88-
}} /** the settings and help icon buttons are only visible on desktop sizes and replaced by a kebab dropdown for other sizes */
89-
>
83+
<ToolbarGroup variant="action-group-plain">
9084
<ToolbarItem>
9185
{renderTourStepElement(
9286
'settingsButton',

packages/react-core/src/demos/Animations/AnimationsTourModal.tsx renamed to packages/react-core/src/demos/Animations/AnimationsStartTourModal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ interface Props {
55
onClose: (startTour?: boolean) => void;
66
}
77

8-
export const AnimationsTourModal: FunctionComponent<Props> = ({ onClose }) => (
8+
export const AnimationsStartTourModal: FunctionComponent<Props> = ({ onClose }) => (
99
<Modal
1010
variant={ModalVariant.small}
1111
isOpen

packages/react-core/src/demos/Animations/GuidedTourContext.tsx

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { createContext, useContext, useCallback, useEffect, useState } from 'react';
2-
import { Button, ButtonVariant, Flex, FlexItem, Popover } from '../..';
1+
import { createContext, useContext, useCallback, useEffect, useState, useRef } from 'react';
2+
import { Button, ButtonVariant, debounce, Flex, FlexItem, getResizeObserver, Popover } from '../..';
33
import TimesIcon from '@patternfly/react-icons/dist/esm/icons/times-icon';
44
import { GuidedTourStep } from './types';
55

@@ -9,6 +9,7 @@ interface GuidedTourContextType {
99
onPrevStep: () => void;
1010
onFinish: () => void;
1111
tourStep: GuidedTourStep | undefined;
12+
isFinished: boolean;
1213
setCustomStepContent: (customContent: React.ReactNode) => void;
1314
renderTourStepElement: (forStepId: string, child: React.ReactElement) => React.ReactElement;
1415
}
@@ -20,7 +21,8 @@ const GuidedTourContext = createContext<GuidedTourContextType>({
2021
onFinish: () => {},
2122
setCustomStepContent: () => {},
2223
renderTourStepElement: () => null,
23-
tourStep: undefined
24+
tourStep: undefined,
25+
isFinished: false
2426
});
2527

2628
export const GuidedTourProvider: React.FC<{ steps: GuidedTourStep[]; children: React.ReactNode }> = ({
@@ -29,6 +31,10 @@ export const GuidedTourProvider: React.FC<{ steps: GuidedTourStep[]; children: R
2931
}) => {
3032
const [currentStep, setCurrentStep] = useState<number | undefined>();
3133
const [customStepContent, setCustomStepContent] = useState<React.ReactNode | undefined>();
34+
const [windowWidth, setWindowWidth] = useState<number>();
35+
const unObserver = useRef(null);
36+
37+
const isMobile = windowWidth < 500;
3238

3339
useEffect(() => {
3440
setCurrentStep(undefined);
@@ -48,12 +54,12 @@ export const GuidedTourProvider: React.FC<{ steps: GuidedTourStep[]; children: R
4854
const onNextStep = useCallback(() => {
4955
setCustomStepContent(undefined);
5056
setCurrentStep((prev) => {
51-
if (prev === undefined || prev === steps.length) {
57+
if (prev === undefined) {
5258
return prev;
5359
}
5460
return prev + 1;
5561
});
56-
}, [steps]);
62+
}, []);
5763

5864
const onPrevStep = useCallback(() => {
5965
setCustomStepContent(undefined);
@@ -66,6 +72,7 @@ export const GuidedTourProvider: React.FC<{ steps: GuidedTourStep[]; children: R
6672
}, []);
6773

6874
const tourStep = currentStep !== undefined ? steps[currentStep] : undefined;
75+
const isFinished = currentStep !== undefined ? currentStep >= steps.length : false;
6976

7077
const renderTourStepElement = useCallback(
7178
(forStepId: string, child: React.ReactElement) => {
@@ -76,7 +83,7 @@ export const GuidedTourProvider: React.FC<{ steps: GuidedTourStep[]; children: R
7683
<Popover
7784
isVisible
7885
showClose
79-
maxWidth="28rem"
86+
maxWidth={isMobile ? undefined : '28rem'}
8087
hideOnOutsideClick={false}
8188
position={tourStep.position}
8289
headerContent={
@@ -113,11 +120,8 @@ export const GuidedTourProvider: React.FC<{ steps: GuidedTourStep[]; children: R
113120
</Button>
114121
</FlexItem>
115122
<FlexItem>
116-
<Button
117-
variant={ButtonVariant.primary}
118-
onClick={() => (currentStep < steps.length ? onNextStep() : onFinish())}
119-
>
120-
{currentStep < steps.length - 1 ? 'Next' : 'Finish'}
123+
<Button variant={ButtonVariant.primary} onClick={onNextStep}>
124+
Next
121125
</Button>
122126
</FlexItem>
123127
</Flex>
@@ -129,13 +133,53 @@ export const GuidedTourProvider: React.FC<{ steps: GuidedTourStep[]; children: R
129133
</Popover>
130134
);
131135
},
132-
[tourStep, currentStep, steps, onNextStep, onPrevStep, onFinish, customStepContent]
136+
[tourStep, currentStep, steps, onNextStep, onPrevStep, onFinish, customStepContent, isMobile]
137+
);
138+
139+
const measureRef = (ref: HTMLDivElement) => {
140+
// Remove any previous observer
141+
if (unObserver.current) {
142+
unObserver.current();
143+
}
144+
145+
if (!ref) {
146+
return;
147+
}
148+
149+
const handleResize = () => setWindowWidth(ref.clientWidth);
150+
151+
// Set size on initialization
152+
handleResize();
153+
154+
const debounceResize = debounce(handleResize, 100);
155+
156+
// Update graph size on resize events
157+
unObserver.current = getResizeObserver(ref, debounceResize);
158+
};
159+
160+
useEffect(
161+
() => () => {
162+
if (unObserver.current) {
163+
unObserver.current();
164+
}
165+
},
166+
[]
133167
);
134168

135169
return (
136170
<GuidedTourContext.Provider
137-
value={{ onStart, onNextStep, onPrevStep, onFinish, setCustomStepContent, renderTourStepElement, tourStep }}
171+
value={{
172+
onStart,
173+
onNextStep,
174+
onPrevStep,
175+
onFinish,
176+
setCustomStepContent,
177+
renderTourStepElement,
178+
tourStep,
179+
isFinished
180+
}}
138181
>
182+
<div ref={measureRef} style={{ width: '100%' }} />
139183
{children}
140184
</GuidedTourContext.Provider>
141185
);

0 commit comments

Comments
 (0)