Skip to content

Commit

Permalink
refactor: focus-scopeの利用方法を変更
Browse files Browse the repository at this point in the history
  • Loading branch information
toshusai committed Oct 23, 2023
1 parent f47c18d commit 7801b0d
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 84 deletions.
16 changes: 16 additions & 0 deletions packages/react/src/_lib/useForwardedRef.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import * as React from 'react';

export function useForwardedRef<T>(ref: React.ForwardedRef<T>) {
const innerRef = React.useRef<T>(null);

React.useEffect(() => {
if (!ref) return;
if (typeof ref === 'function') {
ref(innerRef.current);
} else {
ref.current = innerRef.current;
}
});

return innerRef;
}
81 changes: 81 additions & 0 deletions packages/react/src/components/Modal/Dialog/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { forwardRef } from 'react'
import * as React from 'react'
import styled, { css } from 'styled-components'
import { useDialog } from '@react-aria/dialog'
import { columnSystem, COLUMN_UNIT, GUTTER_UNIT } from '@charcoal-ui/foundation'
import { unreachable } from '../../../_lib'
import { maxWidth } from '@charcoal-ui/utils'
import { animated } from 'react-spring'
import { useForwardedRef } from '../../../_lib/useForwardedRef'
import { Size, BottomSheet } from '..'

export const Dialog = forwardRef<
HTMLDivElement,
React.ComponentProps<typeof AnimatedStyledDialogDiv>
>(function Dialog(props, forwardRef) {
const ref = useForwardedRef(forwardRef)
const { dialogProps } = useDialog(
{
role: 'dialog',
},
ref
)

return (
<AnimatedStyledDialogDiv
{...props}
role={dialogProps.role}
tabIndex={dialogProps.tabIndex}
aria-labelledby={dialogProps['aria-labelledby']}
onBlur={dialogProps.onBlur}
ref={ref}
/>
)
})

const AnimatedStyledDialogDiv = animated(styled.div<{
size: Size
bottomSheet: BottomSheet
}>`
margin: auto;
position: relative;
height: fit-content;
width: ${(p) => {
switch (p.size) {
case 'S': {
return columnSystem(3, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
}
case 'M': {
return columnSystem(4, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
}
case 'L': {
return columnSystem(6, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
}
default: {
return unreachable(p.size)
}
}
}}px;
background-color: ${({ theme }) => theme.color.background1};
border-radius: 24px;
@media ${({ theme }) => maxWidth(theme.breakpoint.screen1)} {
max-width: 440px;
width: calc(100% - 48px);
${(p) =>
p.bottomSheet !== false &&
css`
width: 100%;
border-radius: 0;
margin: auto 0 0 0;
${p.bottomSheet === 'full' &&
css`
min-height: 100%;
`}
`}
}
:focus {
outline: none;
}
`)
106 changes: 22 additions & 84 deletions packages/react/src/components/Modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,17 @@ import {
} from '@react-aria/overlays'
import styled, { css, useTheme } from 'styled-components'
import { theme } from '../../styled'
import { useDialog } from '@react-aria/dialog'
import { AriaDialogProps } from '@react-types/dialog'
import { columnSystem, COLUMN_UNIT, GUTTER_UNIT } from '@charcoal-ui/foundation'
import { unreachable } from '../../_lib'
import { maxWidth } from '@charcoal-ui/utils'
import { useMedia } from '@charcoal-ui/styled'
import { animated, useTransition, easings } from 'react-spring'
import Button, { ButtonProps } from '../Button'
import IconButton from '../IconButton'
import { useObjectRef } from '@react-aria/utils'
import { FocusScope } from '@react-aria/focus'
import { Dialog } from './Dialog'

export type BottomSheet = boolean | 'full'
type Size = 'S' | 'M' | 'L'
export type Size = 'S' | 'M' | 'L'

export type ModalProps = AriaModalOverlayProps &
AriaDialogProps & {
Expand Down Expand Up @@ -142,37 +139,33 @@ const Modal = forwardRef<HTMLDivElement, ModalProps>(function ModalInner(
style={transitionEnabled ? { backgroundColor, overflow } : {}}
$bottomSheet={bottomSheet}
>
<ModalDialog
<Dialog
ref={ref}
{...modalProps}
style={transitionEnabled ? { transform } : {}}
size={size}
bottomSheet={bottomSheet}
className={className}
>
<FocusScope autoFocus restoreFocus contain>
<Dialog>
<ModalContext.Provider
value={{
titleProps: {},
title,
close: onClose,
showDismiss,
bottomSheet,
}}
>
{children}
{isDismissable === true && (
<ModalCrossButton
size="S"
icon="24/Close"
onClick={onClose}
/>
)}
</ModalContext.Provider>
</Dialog>
</FocusScope>
</ModalDialog>
<ModalContext.Provider
value={{
titleProps: {},
title,
close: onClose,
showDismiss,
bottomSheet,
}}
>
{children}
{isDismissable === true && (
<ModalCrossButton
size="S"
icon="24/Close"
onClick={onClose}
/>
)}
</ModalContext.Provider>
</Dialog>
</ModalBackground>
</Overlay>
)
Expand All @@ -182,17 +175,6 @@ const Modal = forwardRef<HTMLDivElement, ModalProps>(function ModalInner(

export default memo(Modal)

function Dialog({ children }: { children: React.ReactNode }) {
const r = React.useRef(null)
const { dialogProps } = useDialog(
{
role: 'dialog',
},
r
)
return <div {...dialogProps}>{children}</div>
}

export const ModalContext = React.createContext<{
/**
* @deprecated
Expand Down Expand Up @@ -237,50 +219,6 @@ const ModalBackground = animated(styled.div<{
}
`)

const ModalDialog = animated(styled.div<{
size: Size
bottomSheet: BottomSheet
}>`
margin: auto;
position: relative;
height: fit-content;
width: ${(p) => {
switch (p.size) {
case 'S': {
return columnSystem(3, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
}
case 'M': {
return columnSystem(4, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
}
case 'L': {
return columnSystem(6, COLUMN_UNIT, GUTTER_UNIT) + GUTTER_UNIT * 2
}
default: {
return unreachable(p.size)
}
}
}}px;
background-color: ${({ theme }) => theme.color.background1};
border-radius: 24px;
@media ${({ theme }) => maxWidth(theme.breakpoint.screen1)} {
max-width: 440px;
width: calc(100% - 48px);
${(p) =>
p.bottomSheet !== false &&
css`
width: 100%;
border-radius: 0;
margin: auto 0 0 0;
${p.bottomSheet === 'full' &&
css`
min-height: 100%;
`}
`}
}
`)

const ModalCrossButton = styled(IconButton)`
position: absolute;
top: 8px;
Expand Down

0 comments on commit 7801b0d

Please sign in to comment.