• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

zooniverse / front-end-monorepo / 16290720450

15 Jul 2025 10:24AM UTC coverage: 77.968% (+0.04%) from 77.933%
16290720450

Pull #6961

github

web-flow
Merge 79a39356f into 8eaeac2ec
Pull Request #6961: Fix issue with mobile scrolling for tutorial popup on safari.

11256 of 16829 branches covered (66.88%)

Branch coverage included in aggregate %.

4 of 4 new or added lines in 2 files covered. (100.0%)

1 existing line in 1 file now uncovered.

17452 of 19991 relevant lines covered (87.3%)

403.01 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

85.71
/packages/lib-classifier/src/components/Classifier/components/SlideTutorial/SlideTutorial.js
1
import { useState } from 'react';
1✔
2
import PropTypes from 'prop-types'
1✔
3
import styled from 'styled-components'
1✔
4
import { Box, Button, Paragraph } from 'grommet'
2✔
5
import { Markdownz, Media } from '@zooniverse/react-components'
6
import { useTranslation } from '@translations/i18n'
1✔
7

8
import StepNavigation from '@shared/StepNavigation'
57!
9

10
const StyledBox = styled(Box)`
1✔
11
  max-height: 80vh;
12
`
13

14
const StyledMarkdownWrapper = styled(Box)`
1✔
15
  > h1, h2 {
16
    font-size: 26px;
17
    line-height: 31px;
18
  }
19

20
  > p {
21
    margin-top: 10px;
22
    margin-bottom: 10px;
23
  }
24
`
25

26
/**
27
A workflow slide tutorial which can be embedded directly into the classifier or shown in a popup.
28

29
```
30
<SlideTutorial
31
  activeStep={0}
32
  height='100%'
33
  steps={[...steps]}
34
  stepwithMedium={index => steps[index]}
35
  width='40vw'
36
/>
37
```
38
*/
39
function SlideTutorial({
40
  activeStep = 0,
17✔
41
  className = '',
17!
42
  projectDisplayName = '',
17✔
43
  onClick = () => true,
17✔
44
  height,
17✔
45
  pad = 'medium',
17✔
46
  steps = [],
17✔
47
  stepWithMedium,
17✔
48
  strings = {},
17✔
49
  width
17✔
50
}) {
19✔
51
  const [stepIndex, setStepIndex] = useState(activeStep)
17✔
52
  const { t } = useTranslation('components')
17✔
53
  const { medium, step } = stepWithMedium(stepIndex)
17✔
54
  const isThereMedia = medium?.src
17✔
55
  const isLastStep = stepIndex === steps.length - 1
17✔
56

57
  if (!step) {
17!
UNCOV
58
    return (
×
59
      <Box height='100%' justify='between' pad={pad}>
60
        <Paragraph>{t('SlideTutorial.error')}</Paragraph>
61
      </Box>
62
    )
63
  }
64

65
  return (
17✔
66
    <StyledBox
67
      className={className}
68
      height={height}
69
      justify='between'
70
      pad={pad}
71
      width={width}
72
    >
73
      <StyledMarkdownWrapper
74
        aria-live='polite'
75
        autoFocus
76
        height='100%'
77
        overflow={{ horizontal: 'hidden', vertical: 'auto' }}
78
      >
79
        {isThereMedia &&
21✔
80
          <Media
81
            alt={t('SlideTutorial.alt', { activeStep: stepIndex })}
82
            fit='contain'
83
            height={200}
84
            src={medium.src}
85
          />}
86
        <Markdownz>{strings[`steps.${stepIndex}.content`]}</Markdownz>
87
      </StyledMarkdownWrapper>
88
      <StepNavigation
89
        name='TutorialStepNavigation'
90
        onChange={setStepIndex}
91
        stepIndex={stepIndex}
92
        steps={steps}
93
      />
94
      {isLastStep &&
19✔
95
        <Button
96
          label={t('SlideTutorial.getStarted')}
97
          onClick={onClick}
98
          margin={{ top: 'medium' }}
99
          primary
100
        />}
101
    </StyledBox>
102
  )
103
}
104

105
const tutorialStep = PropTypes.shape({
1✔
106
  content: PropTypes.string,
107
  medium: PropTypes.string
108
})
109

110
SlideTutorial.propTypes = {
1✔
111
  /** Array index of the current tutorial step. */
112
  activeStep: PropTypes.number,
113
  /** Optional CSS classes */
114
  className: PropTypes.string,
115
  /** Tutorial height (CSS units). */
116
  height: PropTypes.string,
117
  /** The project name */
118
  projectDisplayName: PropTypes.string,
119
  /** Callback for the Get Started button. */
120
  onClick: PropTypes.func,
121
  /**
122
    Array of tutorial steps.
123
    A step is a string of markdown content and an optional reference to a media file (image/audio/video.)
124
  */
125
  steps: PropTypes.arrayOf(tutorialStep),
126
  /** A function which should return the step and media file for a given step index. */
127
  stepWithMedium: PropTypes.func.isRequired,
128
  /** Translated strings for the tutorial content */
129
  strings: PropTypes.object,
130
  /** Tutorial width (CSS units). */
131
  width: PropTypes.string,
132
}
1✔
133

134
export default SlideTutorial
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc