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

fix: Modalの挙動と外観を修正 #389

Merged
merged 8 commits into from
Oct 20, 2023
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
20 changes: 16 additions & 4 deletions packages/react/src/components/Modal/ModalPlumbing.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
import { ModalTitle } from '.'
import styled from 'styled-components'
import { BottomSheet, ModalContext, ModalTitle } from '.'
import styled, { css } from 'styled-components'
import { theme } from '../../styled'
import { useContext } from 'react'
import { maxWidth } from '@charcoal-ui/utils'

export function ModalHeader() {
const modalCtx = useContext(ModalContext)
return (
<ModalHeaderRoot>
<ModalHeaderRoot $bottomSheet={modalCtx.bottomSheet}>
<StyledModalTitle />
</ModalHeaderRoot>
)
}

const ModalHeaderRoot = styled.div`
const ModalHeaderRoot = styled.div<{
$bottomSheet: BottomSheet
}>`
height: 64px;
display: grid;
align-content: center;
justify-content: center;
@media ${({ theme }) => maxWidth(theme.breakpoint.screen1)} {
${(p) =>
p.$bottomSheet !== false &&
css`
height: 48px;
`}
}
`

const StyledModalTitle = styled(ModalTitle)`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Story } from '../../../_lib/compat'
import Modal, { BottomSheet, ModalProps } from '..'
import { OverlayProvider } from '@react-aria/overlays'
import { useOverlayTriggerState } from 'react-stately'
import Button from '../../Button'
import { ModalBody, ModalButtons, ModalHeader } from '../ModalPlumbing'
import styled, { css } from 'styled-components'
import { maxWidth } from '@charcoal-ui/utils'

export const InternalScrollStory: Story<ModalProps> = (args: ModalProps) => {
const state = useOverlayTriggerState({})
return (
<OverlayProvider>
<Button onClick={() => state.open()}>Open Modal</Button>

<Modal {...args} isOpen={state.isOpen} onClose={() => state.close()}>
<ModalHeader />
<ModalBody>
<ModalBodyOverflowDiv $offset={56} $bottomSheet={args.bottomSheet}>
<div
style={{
height: 1000,
background: `linear-gradient(#e66465, #9198e5)`,
}}
></div>
</ModalBodyOverflowDiv>
<TopBorderButtons>
<Button fullWidth onClick={() => state.close()}>
Close
</Button>
</TopBorderButtons>
</ModalBody>
</Modal>
</OverlayProvider>
)
}

// underlay padding-top: 40px (desktop)
// underlay padding-bottom: 40px (desktop)
// modal header: 64px (desktop)
// modal header: 48px (mobile-bottom-sheet)
// modal padding-bottom: 40px
// button and space: 56px
const MAX_HEIGHT_OFFSET = 64 + 40 + 40 + 40
const MAX_HEIGHT_OFFSET_MOBILE = MAX_HEIGHT_OFFSET - 40 * 2 - 16
const ModalBodyOverflowDiv = styled.div<{
$offset: number
$bottomSheet?: BottomSheet
}>`
overflow: auto;
max-height: calc(
100vh - ${MAX_HEIGHT_OFFSET}px - ${({ $offset }) => $offset}px
);
${({ $bottomSheet, $offset }) =>
($bottomSheet === true || $bottomSheet === 'full') &&
css`
@media ${({ theme }) => maxWidth(theme.breakpoint.screen1)} {
max-height: calc(100vh - ${MAX_HEIGHT_OFFSET_MOBILE}px - ${$offset}px);
}
`}
`

const TopBorderButtons = styled(ModalButtons)`
position: relative;
&::before {
content: '';
pointer-events: none;
border-top: 1px solid ${({ theme }) => theme.border.default.color};
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
`
79 changes: 41 additions & 38 deletions packages/react/src/components/Modal/index.story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,51 +43,52 @@ const DefaultStory = (args: ModalProps) => {
// hidden from screen readers when a modal opens.
<OverlayProvider>
<Button onClick={() => state.open()}>Open Modal</Button>

<Modal
<M
{...args}
isDismissable
isOpen={state.isOpen}
onClose={() => state.close()}
isDismissable
>
<ModalHeader />
<ModalBody>
<ModalVStack>
<StyledModalText>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quod
placeat tenetur, necessitatibus laudantium cumque exercitationem
provident. Quaerat iure enim, eveniet dolores earum odio quo
possimus fugiat aspernatur, numquam, commodi repellat.
</StyledModalText>
<ModalAlign>
<TextField
showLabel
label="Name"
placeholder="Nagisa"
></TextField>
</ModalAlign>
<ModalAlign>
<TextField
showLabel
label="Country"
placeholder="Tokyo"
></TextField>
</ModalAlign>
</ModalVStack>
<ModalButtons>
<Button variant="Primary" onClick={() => state.close()} fullWidth>
Apply
</Button>
<Button onClick={() => state.close()} fullWidth>
Cancel
</Button>
</ModalButtons>
</ModalBody>
</Modal>
/>
</OverlayProvider>
)
}

const M = (props: ModalProps) => {
return (
<Modal {...props}>
<ModalHeader />
<ModalBody>
<ModalVStack>
<StyledModalText>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quod
placeat tenetur, necessitatibus laudantium cumque exercitationem
provident. Quaerat iure enim, eveniet dolores earum odio quo
possimus fugiat aspernatur, numquam, commodi repellat.
</StyledModalText>
<ModalAlign>
<TextField showLabel label="Name" placeholder="Nagisa"></TextField>
</ModalAlign>
<ModalAlign>
<TextField
showLabel
label="Country"
placeholder="Tokyo"
></TextField>
</ModalAlign>
</ModalVStack>
<ModalButtons>
<Button variant="Primary" onClick={() => props.onClose()} fullWidth>
Apply
</Button>
<Button onClick={() => props.onClose()} fullWidth>
Cancel
</Button>
</ModalButtons>
</ModalBody>
</Modal>
)
}

const ModalVStack = styled.div`
display: grid;
gap: 24px;
Expand Down Expand Up @@ -192,3 +193,5 @@ const BottomSheetStory = (args: ModalProps) => {
}

export const BottomSheet: Story<ModalProps> = BottomSheetStory.bind({})

export { InternalScrollStory as InternalScroll } from './__stories__/InternalScrollStory'
Loading
Loading