Skip to content

Commit

Permalink
feat: add pagination component and logic (#3992)
Browse files Browse the repository at this point in the history
* feat: add pagination component and logic

* feat: add functionality to close feature tour on clicking overlay

* refactor: move ProgressIndicator into components

* fix: fix failing stories due to implementation of pagination component

* fix: refactor code as per comments

Co-authored-by: Siddarth Nandanahosur Suresh <[email protected]>
  • Loading branch information
siddarth2824 and Siddarth Nandanahosur Suresh authored Jun 14, 2022
1 parent bf6a233 commit 6ee7026
Show file tree
Hide file tree
Showing 6 changed files with 109 additions and 43 deletions.
88 changes: 57 additions & 31 deletions frontend/src/features/admin-form/create/featureTour/FeatureTour.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useState } from 'react'
import Joyride, { CallBackProps, EVENTS, STATUS } from 'react-joyride'
import Joyride, { ACTIONS, CallBackProps, EVENTS, STATUS } from 'react-joyride'
import { useToken } from '@chakra-ui/react'

import { FEATURE_STEPS } from './constants'
import { FeatureTourContext } from './FeatureTourContext'
import { FeatureTourTooltip } from './FeatureTourTooltip'

interface FeatureTourProps {
Expand All @@ -12,43 +13,68 @@ interface FeatureTourProps {
export const FeatureTour = ({ onClose }: FeatureTourProps): JSX.Element => {
const [stepIndex, setStepIndex] = useState<number>(0)
const arrowColor: string = useToken('colors', ['primary.100'])
const [isPaginationClicked, setIsPaginationClicked] = useState<boolean>(false)

const handleJoyrideCallback = ({ index, status, type }: CallBackProps) => {
if (type === EVENTS.STEP_AFTER || type === EVENTS.TARGET_NOT_FOUND) {
setStepIndex(index + 1)
}
const handleJoyrideCallback = ({
action,
index,
status,
type,
}: CallBackProps) => {
if (!isPaginationClicked) {
if (type === EVENTS.STEP_AFTER || type === EVENTS.TARGET_NOT_FOUND) {
setStepIndex(index + 1)
}

if (status === STATUS.FINISHED || status === STATUS.SKIPPED) {
onClose()
if (
status === STATUS.FINISHED ||
status === STATUS.SKIPPED ||
action === ACTIONS.CLOSE
) {
onClose()
}
} else {
setIsPaginationClicked(false)
}
}

const handlePaginationCallback = (indicatorIdx: number) => {
setIsPaginationClicked(true)
setStepIndex(indicatorIdx)
}

return (
<Joyride
steps={FEATURE_STEPS}
callback={handleJoyrideCallback}
stepIndex={stepIndex}
run
hideBackButton
floaterProps={{
placement: 'right-start',
styles: {
arrow: {
length: 8,
spread: 16,
<FeatureTourContext.Provider
value={{
paginationCallback: handlePaginationCallback,
}}
>
<Joyride
steps={FEATURE_STEPS}
callback={handleJoyrideCallback}
stepIndex={stepIndex}
run
hideBackButton
floaterProps={{
placement: 'right-start',
styles: {
arrow: {
length: 8,
spread: 16,
},
floaterWithAnimation: {
transition: 'opacity 0.3s ease 0s, transform 0s ease 0s',
},
},
floaterWithAnimation: {
transition: 'opacity 0.3s ease 0s, transform 0s ease 0s',
}}
styles={{
options: {
arrowColor: arrowColor,
},
},
}}
styles={{
options: {
arrowColor: arrowColor,
},
}}
spotlightPadding={3}
tooltipComponent={FeatureTourTooltip}
/>
}}
spotlightPadding={3}
tooltipComponent={FeatureTourTooltip}
/>
</FeatureTourContext.Provider>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { createContext, useContext } from 'react'

type FeatureTourContextProps = {
paginationCallback: (indicatorIdx: number) => void
}

export const FeatureTourContext = createContext<
FeatureTourContextProps | undefined
>(undefined)

export const useFeatureTourContext = () => {
const context = useContext(FeatureTourContext)

if (context === undefined) {
throw new Error(
`useFeatureTourContext must be used within a FeatureTourContextProvider`,
)
}

return context
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { fullScreenDecorator } from '~utils/storybook'
import { ButtonProps } from '~components/Button'

import { FEATURE_STEPS } from './constants'
import { FeatureTourContext } from './FeatureTourContext'
import {
FeatureTourStep,
FeatureTourTooltip,
Expand All @@ -21,7 +22,7 @@ export default {
} as Meta

const Template: Story<FeatureTourTooltipProps> = (args) => {
const [featureStep, setFeatureStep] = useState<number>(args.stepIndex ?? 0)
const [featureStep, setFeatureStep] = useState<number>(args.index ?? 0)

const handleNextClick = () => {
featureStep === FEATURE_STEPS.length - 1
Expand All @@ -43,21 +44,29 @@ const Template: Story<FeatureTourTooltipProps> = (args) => {
const mockPrimaryProps: ButtonProps = {
onClick: handleNextClick,
}
const paginationCallback = (indicatorIdx: number) => {
setFeatureStep(indicatorIdx)
}

return (
<FeatureTourTooltip
{...args}
step={featureTourTooltipContent}
primaryProps={mockPrimaryProps}
isLastStep={isLastStep}
/>
<FeatureTourContext.Provider
value={{ paginationCallback: paginationCallback }}
>
<FeatureTourTooltip
{...args}
step={featureTourTooltipContent}
primaryProps={mockPrimaryProps}
isLastStep={isLastStep}
index={featureStep}
/>
</FeatureTourContext.Provider>
)
}

export const BasicUsage = Template.bind({})

export const LastFeatureStep = Template.bind({})
LastFeatureStep.args = {
stepIndex: FEATURE_STEPS.length - 1,
index: FEATURE_STEPS.length - 1,
isLastStep: true,
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ import { Box, BoxProps, CloseButton, Flex, Icon, Text } from '@chakra-ui/react'

import Badge from '~components/Badge'
import Button, { ButtonProps } from '~components/Button'
import { ProgressIndicator } from '~components/ProgressIndicator/ProgressIndicator'

import { FEATURE_STEPS } from './constants'
import { useFeatureTourContext } from './FeatureTourContext'

export interface FeatureTourStep {
content: React.ReactNode
Expand All @@ -15,7 +19,7 @@ export interface FeatureTourTooltipProps {
primaryProps: ButtonProps
skipProps: ButtonProps
isLastStep: boolean
stepIndex?: number
index: number
}

export const FeatureTourTooltip = ({
Expand All @@ -24,7 +28,9 @@ export const FeatureTourTooltip = ({
primaryProps,
skipProps,
isLastStep,
index,
}: FeatureTourTooltipProps): JSX.Element => {
const { paginationCallback } = useFeatureTourContext()
return (
<Box
padding="1.5rem"
Expand Down Expand Up @@ -66,8 +72,11 @@ export const FeatureTourTooltip = ({
alignItems="center"
justifyContent="space-between"
>
{/* Todo: Create pagination component */}
<Text>Pagination Component</Text>
<ProgressIndicator
numIndicators={FEATURE_STEPS.length}
currActiveIdx={index}
onClick={paginationCallback}
/>
{isLastStep ? (
<Button {...skipProps}>Done</Button>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import {
import { useIsMobile } from '~hooks/useIsMobile'
import Button from '~components/Button'

import { ProgressIndicator } from '../../components/ProgressIndicator/ProgressIndicator'

import { LastFeatureContent } from './components/LastFeatureContent'
import { NewFeatureContent } from './components/NewFeatureContent'
import { ProgressIndicator } from './components/ProgressIndicator'
import { NEW_FEATURES, OTHER_UPDATES } from './Announcements'

interface RolloutAnnouncementModalProps {
Expand Down

0 comments on commit 6ee7026

Please sign in to comment.