modal について
modalは、@lobehub/uiで命令的なモーダルを実装するためのガイドで、主にbase-ui APIを扱います。アプリ開発者向けに、セットアップ、コンテンツ、確認ダイアログ、国際化、コールバックの動作を説明します。
主な機能
- 01base-uiのcreateModalとconfirmModalの使用
- 02グローバルなModalHostのマウント
- 03モーダルの内容と呼び出し方法
- 04終了コールバックの動作
- 05国際化と主なオプション
活用シーン
- 01アプリへの命令的モーダルの追加
- 02モーダル終了後のクリーンアップ設定
- 03確認ダイアログの作成
- 04base-uiへの利用方法の移行
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ lobehub/ lobehub --skill modalインストール後、Claude Code で/modalを入力して読み込まれたか確認します。
詳細
Modal 命令型 API ガイド
推奨:@lobehub/ui/base-ui
新しいコードでは、base-ui のモーダルスタック(ヘッドレスプリミティブ、antd の Modal ではありません)を使用してください。
@lobehub/ui/base-uiのcreateModal、confirmModal、ModalHost- モーダルの コンテンツ 内で使用する
@lobehub/ui/base-uiのuseModalContext
本文スロットには content を渡してください(または children。ランタイムでは content ?? children が使用されます)。
グローバル ModalHost(必須)
base-ui の createModal は、ルートパッケージとは別のホストを通じてレンダリングされます。アプリでは @lobehub/ui/base-ui の ModalHost をルート付近(例:ほかのグローバルホストの隣)に一度マウントする必要があります。マウントしない場合、createModal の呼び出しは表示されません。
プロジェクトが @lobehub/ui の ModalHost だけをマウントしている場合は、命令型モーダルの移行がすべて完了するまで、@lobehub/ui/base-ui の遅延読み込みされる ModalHost をもう一つ追加してください。
命令型を推奨する理由
| モード | 特徴 | 推奨 |
|---|---|---|
| 宣言型 | open の状態 + <Modal /> | ❌ |
| 命令型 | createModal() を呼び出し、ローカル状態は不要 | ✅ |
ファイル構成
features/
└── MyFeatureModal/
├── index.tsx # export createXxxModal
└── MyFeatureContent.tsx # modal body
1. コンテンツ(MyFeatureContent.tsx)
'use client';
import { useModalContext } from '@lobehub/ui/base-ui';
import { useTranslation } from 'react-i18next';
export const MyFeatureContent = () => {
const { t } = useTranslation('namespace');
const { close } = useModalContext();
return <div>{/* ... */}</div>;
};
2. createModal(index.tsx)
'use client';
import { createModal } from '@lobehub/ui/base-ui';
import { t } from 'i18next';
import { MyFeatureContent } from './MyFeatureContent';
export const createMyFeatureModal = () =>
createModal({
content: <MyFeatureContent />,
footer: null,
maskClosable: true,
styles: {
content: { overflow: 'hidden', padding: 0 },
},
title: t('myFeature.title', { ns: 'setting' }),
width: 'min(80%, 800px)',
});
3. 使用方法
import { createMyFeatureModal } from '@/features/MyFeatureModal';
const handleOpen = useCallback(() => {
createMyFeatureModal();
}, []);
return <Button onClick={handleOpen}>Open</Button>;
i18n
- コンテンツ:コンポーネント内で
useTranslationを使用します。 createModalのオプション:フックを使用できない箇所ではimport { t } from 'i18next'を使用します。
useModalContext
const { close, setCanDismissByClickOutside } = useModalContext();
閉じるとき:実際に呼び出されるコールバック
コンテンツ内の useModalContext()、または返された ModalInstance からの close() は、スタックエントリーを open: false にするだけです。base-ui の閉じる処理は通らないため、次のようになります。
| コールバック | ユーザーによる閉じる操作(Esc/背景/ヘッダーの ✕) | コンテンツまたはインスタンスからの close() |
|---|---|---|
onOpenChange | 呼び出される | 呼び出されない |
onOpenChangeComplete | false を指定して呼び出される | false を指定して呼び出される |
呼び出し元側のクリーンアップ(編集中フラグの解除、プロバイダーの open 状態のリセット)は、onOpenChangeComplete に設定してください。onOpenChange に設定すると、フッターボタンでモーダルを閉じるまでは正しく見えますが、その場合は呼び出し元に閉じたことが通知されません。その結果、通常はフラグが設定されたままとなり、モーダルを再度開けなくなります。
createModal は常に false で完了します(命令型レンダラーが引数を自ら渡し、プロパティを base-ui に転送しないためです)。ただし、引き続き値を確認してください。DropdownMenu など、ほかの base-ui プリミティブは両方向を通知するため、この確認によって呼び出し側のコードがその違いに依存しないようにできます。
onOpenChangeComplete: (open) => {
if (!open) onClosed?.();
},
よく使うオプション(base-ui)
ImperativeModalProps は BaseModalProps を拡張します。title、width、maskClosable、open、onOpenChange、footer、styles/classNames(キー:backdrop、popup、header、title、close、content、…)などがあります。
| プロパティ | 説明 |
|---|---|
content | メインの本文(children よりも推奨される名前) |
maskClosable | 外側をクリックして閉じる |
styles.* | antd の styles.body ではなく、セマンティックな領域 |
確認
import { confirmModal } from '@lobehub/ui/base-ui';
confirmModal({
title: '…',
content: '…',
okText: '…',
cancelText: '…',
onOk: async () => {},
});
レガシー:@lobehub/ui(ルート)
ルートの @lobehub/ui エントリからの createModal は、antd Modal のプロパティ(children、allowFullscreen、getContainer、destroyOnHidden、styles.body など)として型付けされています。アプリのコードではもうインポートしていません。再導入せず、@lobehub/ui/base-ui を使用してください。
例
- Base-ui(推奨):上記のセクションに従い、base-ui の
ModalHostがマウントされていることを確認してください。 - Base-ui の呼び出し箇所:
src/features/SkillStore/index.tsx、src/features/LibraryModal/CreateNew/index.tsx