コンポーネント

ダイアログ

メインウィンドウまたは別のダイアログウィンドウ上にオーバーレイ表示されるウィンドウで、その下にあるコンテンツは操作できなくなります。

import React from 'react';
import * as Dialog from '@radix-ui/react-dialog';
import { Cross2Icon } from '@radix-ui/react-icons';
import './styles.css';
const DialogDemo = () => (
<Dialog.Root>
<Dialog.Trigger asChild>
<button className="Button violet">Edit profile</button>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="DialogOverlay" />
<Dialog.Content className="DialogContent">
<Dialog.Title className="DialogTitle">Edit profile</Dialog.Title>
<Dialog.Description className="DialogDescription">
Make changes to your profile here. Click save when you're done.
</Dialog.Description>
<fieldset className="Fieldset">
<label className="Label" htmlFor="name">
Name
</label>
<input className="Input" id="name" defaultValue="Pedro Duarte" />
</fieldset>
<fieldset className="Fieldset">
<label className="Label" htmlFor="username">
Username
</label>
<input className="Input" id="username" defaultValue="@peduarte" />
</fieldset>
<div style={{ display: 'flex', marginTop: 25, justifyContent: 'flex-end' }}>
<Dialog.Close asChild>
<button className="Button green">Save changes</button>
</Dialog.Close>
</div>
<Dialog.Close asChild>
<button className="IconButton" aria-label="Close">
<Cross2Icon />
</button>
</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
export default DialogDemo;

特徴

    モーダルモードと非モーダルモードをサポートします。

    モーダルの場合、フォーカスは自動的にトラップされます。

    制御型または非制御型にできます。

    スクリーンリーダーによるアナウンスをTitle および Description コンポーネントで管理します。

    Escキーでコンポーネントを自動的に閉じます。

インストール

コマンドラインからコンポーネントをインストールします。

npm install @radix-ui/react-dialog

構造

すべてのパーツをインポートして組み合わせます。

import * as Dialog from '@radix-ui/react-dialog';
export default () => (
<Dialog.Root>
<Dialog.Trigger />
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>
<Dialog.Title />
<Dialog.Description />
<Dialog.Close />
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);

API リファレンス

Root

ダイアログのすべてのパーツを含みます。

Propタイプデフォルト
defaultOpen
boolean
デフォルト値なし
open
boolean
デフォルト値なし
onOpenChange
function
デフォルト値なし
modal
boolean
true

Trigger

ダイアログを開くボタン。

Propタイプデフォルト
asChild
boolean
false
データ属性
[data-state]"open" |"closed"

Portal

使用すると、オーバーレイとコンテンツパーツがbodyにポータルされます。

Propタイプデフォルト
forceMount
boolean
デフォルト値なし
container
HTMLElement
document.body

Overlay

ダイアログが開いているときに、ビューの操作できない部分を覆うレイヤー。

Propタイプデフォルト
asChild
boolean
false
forceMount
boolean
デフォルト値なし
データ属性
[data-state]"open" |"closed"

Content

開いているダイアログに表示されるコンテンツを含みます。

Propタイプデフォルト
asChild
boolean
false
forceMount
boolean
デフォルト値なし
onOpenAutoFocus
function
デフォルト値なし
onCloseAutoFocus
function
デフォルト値なし
onEscapeKeyDown
function
デフォルト値なし
onPointerDownOutside
function
デフォルト値なし
onInteractOutside
function
デフォルト値なし
データ属性
[data-state]"open" |"closed"

Close

ダイアログを閉じるボタン。

Propタイプデフォルト
asChild
boolean
false

Title

ダイアログが開いたときにアナウンスされるアクセシブルなタイトル。

タイトルを隠したい場合は、視覚的に隠すユーティリティで次のようにラップします:<VisuallyHidden asChild>

Propタイプデフォルト
asChild
boolean
false

Description

ダイアログが開いたときにアナウンスされる、オプションのアクセシブルな説明。

説明を隠したい場合は、視覚的に隠すユーティリティで次のようにラップします:<VisuallyHidden asChild>。説明を完全に削除したい場合は、この部分を削除し、aria-describedby={undefined}Dialog.Content に渡します。

Propタイプデフォルト
asChild
boolean
false

非同期フォーム送信後に閉じる

制御されたプロパティを使用して、非同期操作が完了した後、プログラムでダイアログを閉じます。

import React from 'react';
import * as Dialog from '@radix-ui/react-dialog';
const wait = () => new Promise((resolve) => setTimeout(resolve, 1000));
export default () => {
const [open, setOpen] = React.useState(false);
return (
<Dialog.Root open={open} onOpenChange={setOpen}>
<Dialog.Trigger>Open</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>
<form onSubmit={(event) => { wait().then(() => setOpen(false)); event.preventDefault(); }} >
{/** some inputs */}
<button type="submit">Submit</button>
</form>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
};

スクロール可能なオーバーレイ

コンテンツをオーバーレイ内に移動して、オーバーフロー付きのダイアログをレンダリングします。

// index.jsx
import * as Dialog from '@radix-ui/react-dialog';
import './styles.css';
export default () => {
return (
<Dialog.Root>
<Dialog.Trigger />
<Dialog.Portal>
<Dialog.Overlay className="DialogOverlay">
<Dialog.Content className="DialogContent">...</Dialog.Content>
</Dialog.Overlay>
</Dialog.Portal>
</Dialog.Root>
);
};
/* styles.css */
.DialogOverlay {
background: rgba(0 0 0 / 0.5);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: grid;
place-items: center;
overflow-y: auto;
}
.DialogContent {
min-width: 300px;
background: white;
padding: 30px;
border-radius: 4px;
}

カスタムポータルコンテナ

ダイアログがポータルされる要素をカスタマイズします。

import React from 'react';
import * as Dialog from '@radix-ui/react-dialog';
export default () => {
const [container, setContainer] = React.useState(null);
return (
<div>
<Dialog.Root>
<Dialog.Trigger />
<Dialog.Portal container={container}>
<Dialog.Overlay />
<Dialog.Content>...</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
<div ref={setContainer} />
</div>
);
};

アクセシビリティ

Dialog WAI-ARIA デザインパターン に準拠しています。

キーボード操作

キーDescription
Space
ダイアログを開閉します。
Enter
ダイアログを開閉します。
Tab
フォーカスを次のフォーカス可能な要素に移動します。
Shift + Tab
フォーカスを前のフォーカス可能な要素に移動します。
Esc
ダイアログを閉じ、フォーカスをDialog.Trigger に移動します。

カスタム API

プリミティブな部分を独自のコンポーネントに抽象化することで、独自の API を作成できます。

オーバーレイとクローズボタンを抽象化する

この例では、Dialog.OverlayDialog.Close の部分を抽象化します。

使用法

import { Dialog, DialogTrigger, DialogContent } from './your-dialog';
export default () => (
<Dialog>
<DialogTrigger>Dialog trigger</DialogTrigger>
<DialogContent>Dialog Content</DialogContent>
</Dialog>
);

実装

// your-dialog.jsx
import React from 'react';
import * as DialogPrimitive from '@radix-ui/react-dialog';
import { Cross1Icon } from '@radix-ui/react-icons';
export const DialogContent = React.forwardRef(
({ children, ...props }, forwardedRef) => (
<DialogPrimitive.Portal>
<DialogPrimitive.Overlay />
<DialogPrimitive.Content {...props} ref={forwardedRef}>
{children}
<DialogPrimitive.Close aria-label="Close">
<Cross1Icon />
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPrimitive.Portal>
)
);
export const Dialog = DialogPrimitive.Root;
export const DialogTrigger = DialogPrimitive.Trigger;