Skip to content

Instantly share code, notes, and snippets.

@kachar
Last active February 19, 2021 08:59
Show Gist options
  • Save kachar/9694fb8f30066032ff776e01005cdc6d to your computer and use it in GitHub Desktop.
Save kachar/9694fb8f30066032ff776e01005cdc6d to your computer and use it in GitHub Desktop.

Usage

<WizardProvider steps={4}>
  <Container maxWidth="sm">
    <Paper className={classes.paper}>
      <WizardSlotForm />
    </Paper>
  </Container>
</WizardProvider>
const WizardSlotForm = () => {
  const { activeStep, next } = useFormWizard()
  
  return (
    <Button
      fullWidth
      color="primary"
      variant="contained"
      onClick={next}>
      ({activeStep}) Continue
    </Button>
  )
}
import React, { useState, createContext, useContext, ReactNode, PropsWithChildren } from 'react'
import { Grow } from '@material-ui/core'
import BackButton from 'components/common/BackButton'
type WizardProps = {
steps: number
}
type WizardContext = {
steps: number
activeStep: number
lastStep: boolean
reset: () => void
prev: () => void
next: () => void
}
type WizardStepProps = {
index: number
}
export const WizardStep = ({ index, children }: PropsWithChildren<WizardStepProps>) => {
const { activeStep } = useFormWizard()
const active = activeStep === index
if (!active) {
return null
}
return (
<Grow in={active} timeout={250}>
<div>{children}</div>
</Grow>
)
}
export const WizardStepBack = () => {
const { prev, activeStep, lastStep } = useFormWizard()
// We can't go back if we're at the initial screen
if (activeStep === 0) {
return null
}
// Last step is normally a success message
if (lastStep) {
return null
}
return <BackButton onClick={() => prev()} />
}
const DefaultContext = ({ steps }: WizardProps): WizardContext => {
const [activeStep, setActiveStep] = useState(0)
const lastStep = activeStep >= steps
return {
steps,
activeStep,
lastStep,
prev: () => {
if (activeStep - 1 >= 0) {
setActiveStep(activeStep - 1)
}
},
next: () => {
if (!lastStep) {
setActiveStep(activeStep + 1)
}
},
reset: () => {
setActiveStep(0)
},
}
}
const WizardContext = createContext<WizardContext>(null as any)
export function WizardProvider({ steps, children }: WizardProps & { children?: ReactNode }) {
const { Provider } = WizardContext
return <Provider value={DefaultContext({ steps })}>{children}</Provider>
}
export function useFormWizard() {
return useContext(WizardContext)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment