Skip to content

Commit

Permalink
Merge pull request #104 from 8845musign/feat/add-hero-prop-to-modals
Browse files Browse the repository at this point in the history
Add Hero Prop to Modals
  • Loading branch information
takanorip committed Jun 17, 2024
2 parents e34cad5 + 677dc7a commit 3e9438a
Show file tree
Hide file tree
Showing 17 changed files with 474 additions and 158 deletions.
9 changes: 4 additions & 5 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ const config: StorybookConfig = {
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@chromatic-com/storybook'
'@chromatic-com/storybook',
],
framework: '@storybook/react-vite',

docs: {},

typescript: {
reactDocgen: 'react-docgen-typescript'
}
reactDocgen: 'react-docgen-typescript',
},
staticDirs: ['./public'],
};
export default config;
10 changes: 10 additions & 0 deletions .storybook/public/images/placeholder.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
34 changes: 21 additions & 13 deletions src/components/ActionHalfModal/ActionHalfModal.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,15 @@
padding: 0 var(--size-spacing-md);
}

.modalBody {
.dialog {
position: fixed;
bottom: 0;
left: 50%;
display: flex;
flex-direction: column;
gap: var(--size-spacing-lg);
width: 100%;
max-width: 600px;
max-height: calc(100% - 24px);
padding: var(--size-spacing-lg) 0;
margin: 0 auto;
background: #fff;
border-radius: 12px;
Expand All @@ -41,22 +39,27 @@
transform: translate3d(-50%, 0, 0);
}

.modalBody.bodyScroll {
.dialog.bodyScroll {
overflow-y: auto;
}

.modalBody.headerLess {
padding-top: var(--size-spacing-xl);
.dialog.fullscreen {
height: calc(100% - 24px);
}

.modalBody.fullscreen {
height: calc(100% - 24px);
.mainContent {
display: flex;
flex-direction: column;
gap: var(--size-spacing-lg);
padding: var(--size-spacing-lg) var(--size-spacing-md);
}

.modalBody.fullscreen.contents {
height: 100%;
min-height: 400px;
overflow: hidden;
.mainContent.headerLess {
padding-top: var(--size-spacing-xl);
}

.mainContent.fullscreen {
flex-grow: 1;
}

.header {
Expand All @@ -70,10 +73,15 @@
outline: none;
}

.body.fullscreen {
height: 100%;
min-height: 400px;
overflow: hidden;
}

.buttonContainer {
display: grid;
gap: var(--size-spacing-md);
padding: 0 var(--size-spacing-md);
}

.overlayEnter {
Expand Down
71 changes: 71 additions & 0 deletions src/components/ActionHalfModal/ActionHalfModal.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,74 @@ export const CustomHeader: Story = {
header: undefined,
},
};

export const WithHero: Story = {
render: (args) => {
const [open, setOpen] = useState(false);
const onClose = useCallback(() => {
setOpen(false);
}, []);

return (
<>
<button type="button" onClick={() => setOpen(true)}>
Open Modal
</button>
<ActionHalfModal
hero={
<img
src="/images/placeholder.svg"
alt="Illustration: Modal"
style={{ width: '100%', height: 'auto', verticalAlign: 'bottom' }}
width={560}
height={315}
/>
}
primaryActionLabel="Action"
onPrimaryAction={onClose}
{...args}
open={open}
onClose={onClose}
>
<p>Content</p>
</ActionHalfModal>
</>
);
},
args: {
...defaultArgs,
},
};

export const WithHeroAndFullScreen: Story = {
render: (args) => {
const [open, setOpen] = useState(false);
const onClose = useCallback(() => {
setOpen(false);
}, []);

return (
<>
<button type="button" onClick={() => setOpen(true)}>
Open Modal
</button>
<ActionHalfModal primaryActionLabel="Action" onPrimaryAction={onClose} {...args} open={open} onClose={onClose}>
<p>Content</p>
</ActionHalfModal>
</>
);
},
args: {
...defaultArgs,
fullscreen: true,
hero: (
<img
src="/images/placeholder.svg"
alt="Illustration: Modal"
style={{ width: '100%', height: 'auto', verticalAlign: 'bottom' }}
width={560}
height={315}
/>
),
},
};
80 changes: 49 additions & 31 deletions src/components/ActionHalfModal/ActionHalfModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { Dialog, Transition } from '@headlessui/react';
import { clsx } from 'clsx';
import { FC, Fragment, PropsWithChildren, useCallback, useRef } from 'react';
import { FC, Fragment, PropsWithChildren, ReactNode, useCallback, useRef } from 'react';
import styles from './ActionHalfModal.module.css';
import { VisuallyHidden } from '../../sharedComponents/VisuallyHidden/VisuallyHidden';
import { CustomDataAttributeProps } from '../../types/attributes';
Expand Down Expand Up @@ -68,6 +68,10 @@ type BaseProps = {
* ネイティブのaria-labelledby属性。独自の見出しを実装する場合にダイアログとの紐づけに使用。ページで固有のIDを指定
*/
ariaLabelledby?: string;
/**
* ヒーローエリア(見出しの更に上)に配置するコンテンツ
*/
hero?: ReactNode;
};

type PrimaryActionProps = {
Expand Down Expand Up @@ -111,6 +115,7 @@ export const ActionHalfModal: FC<PropsWithChildren<Props>> = ({
fullscreen = false,
bodyScroll = true,
ariaLabelledby,
hero,
...props
}) => {
const opacityClassName = opacityToClassName(overlayOpacity);
Expand Down Expand Up @@ -159,39 +164,52 @@ export const ActionHalfModal: FC<PropsWithChildren<Props>> = ({
leaveTo={styles.panelLeaveTo}
>
<div
className={clsx(
styles.modalBody,
!header && styles.headerLess,
fullscreen && styles.fullscreen,
bodyScroll && styles.bodyScroll,
)}
className={clsx(styles.dialog, {
[styles.fullscreen]: fullscreen,
[styles.bodyScroll]: bodyScroll,
})}
>
{header != null ? (
<Dialog.Title tabIndex={-1} ref={initialFocusRef} className={styles.header}>
{header}
</Dialog.Title>
) : (
<VisuallyHidden tabIndex={-1} ref={initialFocusRef}>
{header === undefined ? (
<VisuallyHidden as="p" tabIndex={-1} ref={initialFocusRef}>
ダイアログ
</VisuallyHidden>
)}
<div className={styles.contents}>{children}</div>
<div className={styles.buttonContainer}>
{onPrimaryAction && primaryActionLabel && (
<Button block onClick={onPrimaryAction} aria-label={primaryActionLabel} variant={primaryActionColor}>
{primaryActionLabel}
</Button>
)}
{onSecondaryAction && secondaryActionLabel && (
<Button block variant="secondary" onClick={onSecondaryAction} aria-label={secondaryActionLabel}>
{secondaryActionLabel}
</Button>
)}
{showClose && (
<Button variant="text" onClick={onClose} aria-label={closeLabel}>
{closeLabel}
</Button>
)}
) : null}
{hero !== undefined ? <div className={styles.hero}>{hero}</div> : null}
<div
className={clsx(styles.mainContent, {
[styles.headerLess]: header === undefined && hero === undefined,
[styles.fullscreen]: fullscreen,
})}
>
{header !== undefined ? (
<Dialog.Title tabIndex={-1} ref={initialFocusRef} className={styles.header}>
{header}
</Dialog.Title>
) : null}
<div
className={clsx(styles.body, {
[styles.fullscreen]: fullscreen,
})}
>
{children}
</div>
<div className={styles.buttonContainer}>
{onPrimaryAction && primaryActionLabel && (
<Button block onClick={onPrimaryAction} aria-label={primaryActionLabel} variant={primaryActionColor}>
{primaryActionLabel}
</Button>
)}
{onSecondaryAction && secondaryActionLabel && (
<Button block variant="secondary" onClick={onSecondaryAction} aria-label={secondaryActionLabel}>
{secondaryActionLabel}
</Button>
)}
{showClose && (
<Button variant="text" onClick={onClose} aria-label={closeLabel}>
{closeLabel}
</Button>
)}
</div>
</div>
</div>
</Transition.Child>
Expand Down
32 changes: 21 additions & 11 deletions src/components/ActionModal/ActionModal.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,34 +21,38 @@
background: rgb(0 0 0 / 80%);
}

.modalBody {
.dialog {
position: relative;
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: var(--size-spacing-lg);
width: calc(100% - 32px);
max-width: 600px;
max-height: calc(100% - 48px);
padding: var(--size-spacing-lg) var(--size-spacing-md) var(--size-spacing-md);
margin: 0 auto;
overflow-y: auto;
background: #fff;
border-radius: var(--radius-lg);
}

.modalBody.headerLess {
padding-top: var(--size-spacing-xl);
.dialog.fixedHeight {
height: calc(100% - 48px);
}

.modalBody.fixedHeight {
height: calc(100% - 48px);
.mainContent {
box-sizing: border-box;
display: flex;
flex-direction: column;
gap: var(--size-spacing-lg);
padding: var(--size-spacing-lg) var(--size-spacing-md) var(--size-spacing-md);
}

.modalBody.fixedHeight .contents {
height: 100%;
min-height: 400px;
overflow: hidden;
.mainContent.fixedHeight {
flex-grow: 1;
}

.mainContent.headerLess {
padding-top: var(--size-spacing-xl);
}

.header {
Expand All @@ -62,6 +66,12 @@
outline: none;
}

.body.fixedHeight {
flex-grow: 1;
min-height: 400px;
overflow: hidden;
}

.buttonContainer {
display: grid;
gap: var(--size-spacing-md);
Expand Down
Loading

0 comments on commit 3e9438a

Please sign in to comment.