Skip to content

Commit

Permalink
feat: Stepを飛ばせるようにidで管理する
Browse files Browse the repository at this point in the history
  • Loading branch information
schktjm committed Dec 19, 2024
1 parent 394b884 commit f04ee15
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 165 deletions.
116 changes: 69 additions & 47 deletions packages/smarthr-ui/src/components/Dialog/StepFormDialog.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Input } from '../Input'
import { Cluster } from '../Layout'
import { RadioButton } from '../RadioButton'

import { StepFormDialog } from './StepFormDialog'
import { StepFormDialog, StepFormDialogItem } from './StepFormDialog'

import { ActionDialog, ActionDialogContent, DialogTrigger } from '.'

Expand Down Expand Up @@ -42,6 +42,14 @@ export const Default: StoryFn = () => {
const [responseMessage, setResponseMessage] =
useState<ComponentProps<typeof ActionDialog>['responseMessage']>()
const onChange = (e: React.ChangeEvent<HTMLInputElement>) => setValue(e.currentTarget.name)
const stepOrder = [
{ id: 'a', stepNumber: 1 },
{
id: 'b',
stepNumber: 2,
},
{ id: 'c', stepNumber: 3 },
]

return (
<Cluster>
Expand All @@ -59,69 +67,83 @@ export const Default: StoryFn = () => {
title="FormDialog"
subtitle="副題"
submitLabel="保存"
decorators={{ closeButtonLabel: () => '閉じる', nextButtonLabel: () => 'Next' }}
onSubmit={(closeDialog) => {
action('executed')()
firstStep={stepOrder[0]}
onSubmit={(closeDialog, e, currentStep) => {
action('onSubmit')()
setResponseMessage(undefined)
closeDialog()
const currentStepIndex = stepOrder.findIndex((step) => step.id === currentStep.id)
if (currentStepIndex >= 2) {
closeDialog()
}
if (currentStepIndex === 0) {
const grape = e.currentTarget.elements.namedItem('Grape') as HTMLInputElement
if (grape.checked) {
return stepOrder[2]
}
}
return stepOrder.at(currentStepIndex + 1)
}}
onClickClose={() => {
action('closed')()
setOpenedDialog(null)
setResponseMessage(undefined)
}}
onClickNext={() => {
action('next')()
}}
onClickBack={() => {
action('back')()
}}
stepLength={3}
responseMessage={responseMessage}
id="dialog-form"
data-test="form-dialog-content"
width="40em"
>
<Fieldset title="fruits" innerMargin={0.5}>
<RadioListCluster forwardedAs="ul">
<li>
<RadioButton name="Apple" checked={value === 'Apple'} onChange={onChange}>
Apple
</RadioButton>
</li>
<li>
<RadioButton name="Orange" checked={value === 'Orange'} onChange={onChange}>
Orange
</RadioButton>
</li>
<li>
<RadioButton name="Grape" checked={value === 'Grape'} onChange={onChange}>
Grape
</RadioButton>
</li>
</RadioListCluster>
</Fieldset>
<FormControl title="Sample">
<Input type="text" name="text" />
</FormControl>
<Fieldset title="fruits" innerMargin={0.5}>
<ul>
<li>
<CheckBox name="1">CheckBox</CheckBox>
</li>
<StepFormDialogItem {...stepOrder[0]}>
<Fieldset title="fruits" innerMargin={0.5}>
<RadioListCluster forwardedAs="ul">
<li>
<RadioButton name="Apple" checked={value === 'Apple'} onChange={onChange}>
Apple
</RadioButton>
</li>
<li>
<RadioButton name="Orange" checked={value === 'Orange'} onChange={onChange}>
Orange
</RadioButton>
</li>
<li>
<RadioButton name="Grape" checked={value === 'Grape'} onChange={onChange}>
これを選ぶとステップ2を飛ばして3に進みます
</RadioButton>
</li>
</RadioListCluster>
</Fieldset>
</StepFormDialogItem>
<StepFormDialogItem {...stepOrder[1]}>
<FormControl id="b" title="Sample">
<Input type="text" name="text" />
</FormControl>
</StepFormDialogItem>
<StepFormDialogItem {...stepOrder[2]}>
<Fieldset title="fruits" innerMargin={0.5}>
<ul>
<li>
<CheckBox name="1">CheckBox</CheckBox>
</li>

<li>
<CheckBox name="error" error>
CheckBox / error
</CheckBox>
</li>
<li>
<CheckBox name="error" error>
CheckBox / error
</CheckBox>
</li>

<li>
<CheckBox name="disabled" disabled>
CheckBox / disabled
</CheckBox>
</li>
</ul>
</Fieldset>
<li>
<CheckBox name="disabled" disabled>
CheckBox / disabled
</CheckBox>
</li>
</ul>
</Fieldset>
</StepFormDialogItem>
</StepFormDialog>
</Cluster>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
import React, { ComponentProps, FormEvent, useCallback, useId } from 'react'
import React, { ComponentProps, FormEvent, useCallback, useId, useRef } from 'react'

import { DialogContentInner } from '../DialogContentInner'
import { DialogProps } from '../types'
import { FocusTrapRef } from '../FocusTrap'
import { DialogProps /** コンテンツなにもないDialogの基本props */ } from '../types'
import { useDialogPortal } from '../useDialogPortal'

import {
StepFormDialogContentInner,
StepFormDialogContentInnerProps,
} from './StepFormDialogContentInner'
import { useStepDialog } from './useStep'
import { StepFormDialogProvider, type StepItem } from './StepFormDialogProvider'

type Props = Omit<StepFormDialogContentInnerProps, 'titleId' | 'activeStep'> & DialogProps

type Props = Omit<StepFormDialogContentInnerProps, 'titleId' | 'activeStep' | 'stepLength'> &
DialogProps
type ElementProps = Omit<ComponentProps<'div'>, keyof Props>

export const StepFormDialog: React.FC<Props & ElementProps> = ({
children,
title,
subtitle,
stepLength,
titleTag,
contentBgColor,
contentPadding,
actionTheme,
submitLabel,
firstStep,
onSubmit,
onClickClose,
onClickBack,
onClickNext,
onPressEscape = onClickClose,
responseMessage,
actionDisabled = false,
Expand All @@ -39,80 +41,67 @@ export const StepFormDialog: React.FC<Props & ElementProps> = ({
}) => {
const { createPortal } = useDialogPortal(portalParent, id)
const titleId = useId()
const {
activeStep,
childrenSteps,
onSubmit: onSubmitStep,
onBackSteps,
onNextSteps,
focusTrapRef,
} = useStepDialog(children)
const focusTrapRef = useRef<FocusTrapRef>(null)

const handleClickClose = useCallback(() => {
if (!props.isOpen) {
return
}
focusTrapRef.current?.focus()
onClickClose()
}, [onClickClose, props.isOpen])

const handleSubmitAction = useCallback(
(close: () => void, e: FormEvent<HTMLFormElement>) => {
(close: () => void, e: FormEvent<HTMLFormElement>, currentStep: StepItem) => {
if (!props.isOpen) {
return
return undefined
}

onSubmitStep()
onSubmit(close, e)
focusTrapRef.current?.focus()
return onSubmit(close, e, currentStep)
},
[onSubmit, onSubmitStep, props.isOpen],
[onSubmit, props.isOpen],
)

const handleBackSteps = useCallback(() => {
if (!props.isOpen) {
return
}
focusTrapRef.current?.focus()
onClickBack?.()
onBackSteps()
}, [props.isOpen, onBackSteps, onClickBack])

const handleNextSteps = useCallback(() => {
if (!props.isOpen) {
return
}
onClickNext?.()
onNextSteps()
}, [props.isOpen, onNextSteps, onClickNext])
}, [props.isOpen, onClickBack])

return createPortal(
<DialogContentInner
{...props}
ariaLabelledby={titleId}
className={className}
onPressEscape={onPressEscape}
focusTrapRef={focusTrapRef}
>
{/* eslint-disable-next-line smarthr/a11y-delegate-element-has-role-presentation */}
<StepFormDialogContentInner
title={title}
titleId={titleId}
subtitle={subtitle}
titleTag={titleTag}
contentBgColor={contentBgColor}
contentPadding={contentPadding}
activeStep={activeStep}
stepLength={childrenSteps.length}
actionTheme={actionTheme}
actionDisabled={actionDisabled}
closeDisabled={closeDisabled}
submitLabel={submitLabel}
onClickClose={handleClickClose}
onSubmit={handleSubmitAction}
onClickBack={handleBackSteps}
onClickNext={handleNextSteps}
responseMessage={responseMessage}
decorators={decorators}
<StepFormDialogProvider firstStep={firstStep}>
<DialogContentInner
{...props}
ariaLabelledby={titleId}
className={className}
onPressEscape={onPressEscape}
focusTrapRef={focusTrapRef}
>
{childrenSteps[activeStep]}
</StepFormDialogContentInner>
</DialogContentInner>,
{/* eslint-disable-next-line smarthr/a11y-delegate-element-has-role-presentation */}
<StepFormDialogContentInner
title={title}
titleId={titleId}
subtitle={subtitle}
titleTag={titleTag}
contentBgColor={contentBgColor}
contentPadding={contentPadding}
firstStep={firstStep}
stepLength={stepLength}
actionTheme={actionTheme}
actionDisabled={actionDisabled}
closeDisabled={closeDisabled}
submitLabel={submitLabel}
onClickClose={handleClickClose}
onSubmit={handleSubmitAction}
onClickBack={handleBackSteps}
responseMessage={responseMessage}
decorators={decorators}
>
{children}
</StepFormDialogContentInner>
</DialogContentInner>
</StepFormDialogProvider>,
)
}
Loading

0 comments on commit f04ee15

Please sign in to comment.