Modalはブラウザのトップレイヤー(dialog要素)に表示されるため、document.bodyへポータルした要素はModalの背面に隠れます。Modalは自身のdialog要素をPortalのルートとしてコンテキストで提供しており、usePortalRootで取得してポータル先にすれば、Modalの中でも浮遊UIが正しく前面に表示されます。Modal内のuseToastは自動的にこの仕組みで表示されるので、対応が必要なのは自前でポータルを使う場合だけです。
aria-describedby?stringaria-label?stringaria-labelledby?stringchildren?ReactNodedefaultOpen?booleanisOpen?booleanonClose?() => voidref?Ref<HTMLDialogElement>side?ModalSide'center'| Prop | Type | Default |
|---|---|---|
aria-describedby? | string | - |
aria-label? | string | - |
aria-labelledby? | string | - |
children? | ReactNode | - |
defaultOpen? | boolean | - |
isOpen? | boolean | - |
onClose? | () => void | - |
ref? | Ref<HTMLDialogElement> | - |
side? |
ModalSide |
'center' |
import { Modal } from '@k8ordo/ui';const [isOpen, setIsOpen] = useState(false);
<Button onClick={() => setIsOpen(true)}>
Open Modal
</Button>
<Modal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
side="center"
>
<Dialog.Root>
<Dialog.Header
onClose={() => setIsOpen(false)}
title="Confirmation"
/>
<Dialog.Content>
<p>Are you sure you want to proceed?</p>
</Dialog.Content>
</Dialog.Root>
</Modal><Button onClick={() => setCenterOpen(true)}>Center</Button>
<Button onClick={() => setBottomOpen(true)}>Bottom</Button>
<Button onClick={() => setRightOpen(true)}>Right</Button>
<Modal isOpen={centerOpen} onClose={() => setCenterOpen(false)} side="center">
<Dialog.Root>
<Dialog.Header onClose={() => setCenterOpen(false)} title="Center Modal" />
<Dialog.Content>Centered on screen</Dialog.Content>
</Dialog.Root>
</Modal>
<Modal isOpen={bottomOpen} onClose={() => setBottomOpen(false)} side="bottom">
<Dialog.Root>
<Dialog.Header onClose={() => setBottomOpen(false)} title="Bottom Modal" />
<Dialog.Content>Slides up from bottom</Dialog.Content>
</Dialog.Root>
</Modal>
<Modal isOpen={rightOpen} onClose={() => setRightOpen(false)} side="right">
<Dialog.Root>
<Dialog.Header onClose={() => setRightOpen(false)} title="Right Modal" />
<Dialog.Content>Slides in from right</Dialog.Content>
</Dialog.Root>
</Modal><Modal defaultOpen side="center">
<Dialog.Root>
<Dialog.Header
onClose={() => {}}
title="Default Open Modal"
/>
<Dialog.Content>
<p>This modal is open by default.</p>
</Dialog.Content>
</Dialog.Root>
</Modal>import { usePortalRoot } from '@k8ordo/ui';
import { createPortal } from 'react-dom';
function FloatingLayer({ children }) {
// Inside a Modal this is the top-layer <dialog>; outside it is undefined.
const portalRoot = usePortalRoot();
return createPortal(children, portalRoot?.current ?? document.body);
}