Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: Dialog の位置指定を消し、スタイリングを見直し #4848

Merged
merged 5 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,61 +1,40 @@
import React, { FC, PropsWithChildren, ReactNode, useCallback } from 'react'
import React, { type FC, type PropsWithChildren, type ReactNode, useCallback } from 'react'

import { Button } from '../../Button'
import { Heading, HeadingTagTypes } from '../../Heading'
import { Cluster, Stack } from '../../Layout'
import { ResponseMessage } from '../../ResponseMessage'
import { Section } from '../../SectioningContent'
import { Text } from '../../Text'
import { useOffsetHeight } from '../dialogHelper'
import { type ContentBodyProps, useDialoginnerStyle } from '../useDialogInnerStyle'
import { DialogBody, type Props as DialogBodyProps } from '../DialogBody'
import { DialogHeader, type Props as DialogHeaderProps } from '../DialogHeader'
import { dialogContentInner } from '../dialogInnerStyle'

import type { DecoratorsType, ResponseMessageType } from '../../../types'

export type BaseProps = PropsWithChildren<{
/**
* ダイアログのタイトル
*/
title: ReactNode
/**
* ダイアログのサブタイトル
*/
subtitle?: ReactNode
/**
* @deprecated SectioningContent(Article, Aside, Nav, Section)でDialog全体をラップして、ダイアログタイトルのHeadingレベルを設定してください
*/
titleTag?: HeadingTagTypes
/**
* アクションボタンのラベル
*/
actionText: ReactNode
/**
* アクションボタンのスタイル
*/
actionTheme?: 'primary' | 'secondary' | 'danger'
/**
* アクションボタンをクリックした時に発火するコールバック関数
* @param closeDialog - ダイアログを閉じる関数
*/
onClickAction: (closeDialog: () => void) => void
/**
* アクションボタンを無効にするかどうか
*/
actionDisabled?: boolean
/**
* 閉じるボタンを無効にするかどうか
*/
closeDisabled?: boolean
/** ダイアログフッターの左端操作領域 */
subActionArea?: ReactNode
/** コンポーネント内の文言を変更するための関数を設定 */
decorators?: DecoratorsType<'closeButtonLabel'>
}> &
ContentBodyProps
export type BaseProps = PropsWithChildren<
DialogHeaderProps &
DialogBodyProps & {
/** アクションボタンのラベル */
actionText: ReactNode
/** アクションボタンのスタイル */
actionTheme?: 'primary' | 'secondary' | 'danger'
/**
* アクションボタンをクリックした時に発火するコールバック関数
* @param closeDialog - ダイアログを閉じる関数
*/
onClickAction: (closeDialog: () => void) => void
/** アクションボタンを無効にするかどうか */
actionDisabled?: boolean
/** 閉じるボタンを無効にするかどうか */
closeDisabled?: boolean
/** ダイアログフッターの左端操作領域 */
subActionArea?: ReactNode
/** コンポーネント内の文言を変更するための関数を設定 */
decorators?: DecoratorsType<'closeButtonLabel'>
}
>

export type ActionDialogContentInnerProps = BaseProps & {
onClickClose: () => void
responseMessage?: ResponseMessageType
titleId: string
}

const CLOSE_BUTTON_LABEL = 'キャンセル'
Expand All @@ -80,33 +59,21 @@ export const ActionDialogContentInner: FC<ActionDialogContentInnerProps> = ({
const handleClickAction = useCallback(() => {
onClickAction(onClickClose)
}, [onClickAction, onClickClose])
const { offsetHeight, titleRef, bottomRef } = useOffsetHeight()

const isRequestProcessing = responseMessage && responseMessage.status === 'processing'

const { titleAreaStyle, bodyStyleProps, actionAreaStyle, buttonAreaStyle, messageStyle } =
useDialoginnerStyle(offsetHeight, contentBgColor, contentPadding)
const { wrapper, actionArea, buttonArea, message } = dialogContentInner()

return (
<Section>
{/* eslint-disable-next-line smarthr/a11y-heading-in-sectioning-content */}
<Heading tag={titleTag}>
<Stack gap={0.25} as="span" ref={titleRef} className={titleAreaStyle}>
{subtitle && (
<Text size="S" leading="TIGHT" color="TEXT_GREY" className="smarthr-ui-Dialog-subtitle">
{subtitle}
</Text>
)}
<Text id={titleId} size="L" leading="TIGHT" className="smarthr-ui-Dialog-title">
{title}
</Text>
</Stack>
</Heading>
<div {...bodyStyleProps}>{children}</div>
<Stack gap={0.5} ref={bottomRef} className={actionAreaStyle}>
// eslint-disable-next-line smarthr/best-practice-for-layouts, smarthr/a11y-heading-in-sectioning-content
<Stack gap={0} as="section" className={wrapper()}>
<DialogHeader title={title} subtitle={subtitle} titleTag={titleTag} titleId={titleId} />
<DialogBody contentPadding={contentPadding} contentBgColor={contentBgColor}>
{children}
</DialogBody>
<Stack gap={0.5} className={actionArea()}>
<Cluster justify="space-between">
{subActionArea}
<Cluster gap={{ row: 0.5, column: 1 }} className={buttonAreaStyle}>
<Cluster gap={{ row: 0.5, column: 1 }} className={buttonArea()}>
<Button
onClick={onClickClose}
disabled={closeDisabled || isRequestProcessing}
Expand All @@ -126,13 +93,13 @@ export const ActionDialogContentInner: FC<ActionDialogContentInnerProps> = ({
</Cluster>
</Cluster>
{(responseMessage?.status === 'success' || responseMessage?.status === 'error') && (
<div className={messageStyle}>
<div className={message()}>
<ResponseMessage type={responseMessage.status} role="alert">
{responseMessage.text}
</ResponseMessage>
</div>
)}
</Stack>
</Section>
</Stack>
)
}
30 changes: 0 additions & 30 deletions packages/smarthr-ui/src/components/Dialog/Dialog.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -459,30 +459,6 @@ export const WidthAndPosition: StoryFn = () => (
</DialogContent>
</DialogWrapper>
</li>
<li>
<DialogWrapper>
<DialogTrigger>
<Button aria-haspopup="dialog" aria-controls="dialog-position-1">
top-left
</Button>
</DialogTrigger>
<DialogContent top={50} left={200} id="dialog-position-1">
<p>This Dialog is set to `top: 50px, left: 200px`.</p>
</DialogContent>
</DialogWrapper>
</li>
<li>
<DialogWrapper>
<DialogTrigger>
<Button aria-haspopup="dialog" aria-controls="dialog-position-2">
bottom-right
</Button>
</DialogTrigger>
<DialogContent right={50} bottom={100} id="dialog-position-2">
<p>This Dialog is set to `right: 50px, bottom: 100px`.</p>
</DialogContent>
</DialogWrapper>
</li>
</TriggerList>
)
WidthAndPosition.parameters = {
Expand Down Expand Up @@ -551,12 +527,6 @@ export const RegDialogOpenedDialogWidth: StoryFn = () => (
</Dialog>
)

export const RegDialogOpenedDialogPosition: StoryFn = () => (
<Dialog isOpen top={20} right={40} bottom={60} left={80}>
<p>{dummyText}</p>
</Dialog>
)

export const RegOpenedForm: StoryFn = () => (
<FormDialog
isOpen={true}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
import { useMemo } from 'react'
import { type VariantProps, tv } from 'tailwind-variants'
import React, { type PropsWithChildren } from 'react'
import { VariantProps, tv } from 'tailwind-variants'

import { type Gap } from '../../types'
import type { Gap } from '../../types'

export type Props = PropsWithChildren<
Pick<VariantProps<typeof dialogBody>, 'contentBgColor'> & {
contentPadding?: Gap | { block?: Gap; inline?: Gap }
className?: string | undefined
}
>

const dialogContentInner = tv({
slots: {
titleArea: ['smarthr-ui-Dialog-titleArea', 'shr-border-b-shorthand shr-px-1.5 shr-py-1'],
actionArea: ['smarthr-ui-Dialog-actionArea', 'shr-border-t-shorthand shr-px-1.5 shr-py-1'],
buttonArea: ['smarthr-ui-Dialog-buttonArea', 'shr-ms-auto'],
message: 'shr-text-right',
},
})
const dialogBody = tv({
base: ['smarthr-ui-Dialog-body', 'shr-overflow-auto'],
base: ['smarthr-ui-Dialog-body', 'shr-overflow-auto shr-flex-auto'],
variants: {
contentPaddingBlock: {
paddingBlock: {
0: 'shr-py-0',
0.25: 'shr-py-0.25',
0.5: 'shr-py-0.5',
Expand All @@ -38,7 +37,7 @@ const dialogBody = tv({
XXL: 'shr-py-3.5',
X3L: 'shr-py-4',
} as { [key in Gap]: string },
contentPaddingInline: {
paddingInline: {
0: 'shr-px-0',
0.25: 'shr-px-0.25',
0.5: 'shr-px-0.5',
Expand Down Expand Up @@ -80,34 +79,15 @@ const dialogBody = tv({
},
})

export type ContentBodyProps = Pick<VariantProps<typeof dialogBody>, 'contentBgColor'> & {
contentPadding?: Gap | { block?: Gap; inline?: Gap }
}

export const useDialoginnerStyle = (
offsetHeight: number,
bgColor: ContentBodyProps['contentBgColor'],
padding: ContentBodyProps['contentPadding'] = 1.5,
) =>
useMemo(() => {
const { titleArea, actionArea, buttonArea, message } = dialogContentInner()
const paddingBlock = padding instanceof Object ? padding.block : padding
const paddingInline = padding instanceof Object ? padding.inline : padding
export const DialogBody: React.FC<Props> = ({
contentBgColor,
contentPadding = 1.5,
className,
...rest
}) => {
const paddingBlock = contentPadding instanceof Object ? contentPadding.block : contentPadding
const paddingInline = contentPadding instanceof Object ? contentPadding.inline : contentPadding

return {
titleAreaStyle: titleArea(),
bodyStyleProps: {
className: dialogBody({
contentBgColor: bgColor,
contentPaddingBlock: paddingBlock,
contentPaddingInline: paddingInline,
}),
style: {
maxHeight: `calc(100svh - ${offsetHeight}px)`,
},
},
actionAreaStyle: actionArea(),
buttonAreaStyle: buttonArea(),
messageStyle: message(),
}
}, [bgColor, offsetHeight, padding])
const style = dialogBody({ contentBgColor, paddingBlock, paddingInline, className })
return <div {...rest} className={style} />
}
Loading