-
Notifications
You must be signed in to change notification settings - Fork 30
/
SlideTutorial.js
131 lines (121 loc) · 3.25 KB
/
SlideTutorial.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import { useState } from 'react';
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { Box, Button, Heading, Paragraph } from 'grommet'
import { Markdownz, Media } from '@zooniverse/react-components'
import { useTranslation } from '@translations/i18n'
import StepNavigation from '@shared/StepNavigation'
const StyledMarkdownWrapper = styled(Box)`
> h1, h2 {
font-size: 26px;
line-height: 31px;
}
> p {
margin-top: 10px;
margin-bottom: 10px;
}
`
/**
A workflow slide tutorial which can be embedded directly into the classifier or shown in a popup.
```
<SlideTutorial
activeStep={0}
height='100%'
steps={[...steps]}
stepwithMedium={index => steps[index]}
width='40vw'
/>
```
*/
function SlideTutorial({
activeStep = 0,
className = '',
projectDisplayName = '',
onClick = () => true,
height,
pad = 'medium',
steps = [],
stepWithMedium,
strings = {},
width
}) {
const [stepIndex, setStepIndex] = useState(activeStep)
const { t } = useTranslation('components')
const { medium, step } = stepWithMedium(stepIndex)
const isThereMedia = medium?.src
const isFirstStep = stepIndex === 0
const isLastStep = stepIndex === steps.length - 1
if (!step) {
return (
<Box height='100%' justify='between' pad={pad}>
<Paragraph>{t('SlideTutorial.error')}</Paragraph>
</Box>
)
}
return (
<Box
className={className}
height={height}
justify='between'
pad={pad}
width={width}
>
<StyledMarkdownWrapper
aria-live='polite'
autoFocus
height='100%'
overflow={{ horizontal: 'hidden', vertical: 'auto' }}
>
{isThereMedia &&
<Media
alt={t('SlideTutorial.alt', { activeStep: stepIndex })}
fit='contain'
height={200}
src={medium.src}
/>}
<Markdownz>{strings[`steps.${stepIndex}.content`]}</Markdownz>
</StyledMarkdownWrapper>
<StepNavigation
name='TutorialStepNavigation'
onChange={setStepIndex}
stepIndex={stepIndex}
steps={steps}
/>
{isLastStep &&
<Button
label={t('SlideTutorial.getStarted')}
onClick={onClick}
margin={{ top: 'medium' }}
primary
/>}
</Box>
)
}
const tutorialStep = PropTypes.shape({
content: PropTypes.string,
medium: PropTypes.string
})
SlideTutorial.propTypes = {
/** Array index of the current tutorial step. */
activeStep: PropTypes.number,
/** Optional CSS classes */
className: PropTypes.string,
/** Tutorial height (CSS units). */
height: PropTypes.string,
/** The project name */
projectDisplayName: PropTypes.string,
/** Callback for the Get Started button. */
onClick: PropTypes.func,
/**
Array of tutorial steps.
A step is a string of markdown content and an optional reference to a media file (image/audio/video.)
*/
steps: PropTypes.arrayOf(tutorialStep),
/** A function which should return the step and media file for a given step index. */
stepWithMedium: PropTypes.func.isRequired,
/** Translated strings for the tutorial content */
strings: PropTypes.object,
/** Tutorial width (CSS units). */
width: PropTypes.string,
}
export default SlideTutorial