wix-cli-dashboard-modal について
Wix CLI向けに、Dashboard SDKを使ったダッシュボードモーダル拡張の作成方法を示すスキルです。モーダルの設定、呼び出し元とのデータ交換、ライフサイクル制御、登録を扱います。
主な機能
- 013ファイルのモーダル構成
- 02SDKによるモーダルの開閉
- 03paramsを使ったデータ受け渡し
- 04モーダル状態の監視
- 05呼び出し元へのデータ返却
- 06ダッシュボード拡張の登録
活用シーン
- 01ダッシュボードページに編集ダイアログを追加
- 02選択した項目をモーダルに渡す
- 03モーダル終了時に保存データを返す
- 04モーダルのサイズとタイトルを設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ wix/ skills --skill wix-cli-dashboard-modalインストール後、Claude Code で/wix-cli-dashboard-modalを入力して読み込まれたか確認します。
詳細
概要
ダッシュボードモーダルは、ダッシュボードページまたはプラグインから起動されるポップアップダイアログです。3つのファイルで構成され、ライフサイクルの制御には Dashboard SDK の openModal() と closeModal() を使用します。
クイックリファレンス
| タスク | メソッド | 例 |
|---|---|---|
| モーダルを作成する | src/extensions/dashboard/modals/<folder>/ に3つのファイルを作成する | 詳細は以下のファイル構成を参照 |
| モーダルを開く | dashboard.openModal() | openModal({ modalId: "modal-id" }) |
| モーダルにデータを渡す | openModal() の params | params: { userId: "123" } |
| モーダルでデータを読み取る | observeState() | dashboard.observeState((state) => { ... }) |
| モーダルを閉じる | dashboard.closeModal() | closeModal() |
| 親にデータを返す | closeModal() にデータを渡す | closeModal({ ... }) |
| モーダルが閉じるのを待つ | modalClosed Promise | const { modalClosed } = openModal(...); |
ファイル構成
src/extensions/dashboard/modals/<folder-name>/ に3つのファイルを作成します。
extensions.ts- モーダル ID、タイトル、サイズ、コンポーネントのパスを含むビルダー設定<modal-name>.tsx- モーダルのコンテンツを描画する React コンポーネント<modal-name>.config.ts- モーダルの設定可能なプロパティ(タイトル、幅、高さ)
実装
モーダルの作成
必要な3つのファイルを作成します。
1. extensions.ts - モーダルビルダーの設定:
import { extensions } from '@wix/astro/builders';
import config from './<modal-name>.config.ts';
export default extensions.dashboardModal({
id: "{{GENERATE_UUID}}",
title: config.title,
width: config.width,
height: config.height,
component: './extensions/dashboard/modals/<modal-name>/<modal-name>.tsx',
});
重要:UUID の生成
id は、一意で固定の UUID v4 文字列である必要があります。拡張機能ごとに新しい UUID を生成してください。randomUUID() を使用したり、例の UUID をコピーしたりしないでください。{{GENERATE_UUID}} を、"a1b2c3d4-e5f6-7890-abcd-ef1234567890" のように新しく生成した UUID に置き換えます。
ビルダーのフィールド:
| フィールド | 型 | 説明 |
|---|---|---|
| id | string | 一意のモーダル ID(GUID)。openModal() で使用します |
| title | string | プロジェクトダッシュボードに表示されるモーダルのタイトル |
| width | number | 読み込み中の初期幅 |
| height | number | 読み込み中の初期高さ |
| component | string | モーダルコンテンツの .tsx ファイルへのパス |
2. <modal-name>.tsx - モーダルコンテンツのコンポーネント:
import type { FC } from 'react';
import { dashboard } from '@wix/dashboard';
import {
WixDesignSystemProvider,
Text,
Box,
CustomModalLayout,
} from '@wix/design-system';
import '@wix/design-system/styles.global.css';
import config from './<modal-name>.config.ts';
const { width, height, title } = config;
// To open your modal, call `openModal` with your modal id.
// e.g.
// import { dashboard } from '@wix/dashboard';
// function MyComponent() {
// return <button onClick={() => dashboard.openModal({ modalId: '8ef4d434-9c80-44f5-a3f5-6f15f3a34be7' })}>Open Modal</button>;
// }
const Modal: FC = () => {
return (
<WixDesignSystemProvider features={{ newColorsBranding: true }}>
<CustomModalLayout
width={width}
maxHeight={height}
primaryButtonText="Save"
secondaryButtonText="Cancel"
primaryButtonOnClick={() => dashboard.closeModal()}
secondaryButtonOnClick={() => dashboard.closeModal()}
title={title}
subtitle="Edit this file to customize your modal"
content={
<Box direction="vertical" align="center">
<Text>Wix CLI Modal</Text>
</Box>
}
/>
</WixDesignSystemProvider>
);
};
export default Modal;
3. <modal-name>.config.ts - 設定可能なプロパティ:
export default {
title: "My Modal",
width: 600,
height: 400,
};
次に、src/extensions.ts に登録します。
import { dashboardmodalYourModal } from './extensions/dashboard/modals/<modal-name>/extensions.ts';
export default app()
.use(dashboardmodalYourModal)
// ... other extensions
モーダルを開く
import { dashboard } from "@wix/dashboard";
// Simple open
const result = await dashboard.openModal({
modalId: "your-modal-id", // From .extension.ts id field
});
// Pass data to modal via params
const result = await dashboard.openModal({
modalId: "your-modal-id",
params: {
userId: user.id,
itemData: complexObject, // Objects are passed directly, no encoding needed
},
});
// Get notified when the modal is closed
const { modalClosed } = dashboard.openModal({
modalId: "your-modal-id",
});
const result = await modalClosed; // Resolves with data from closeModal()
モーダルでデータを受け取る
openModal() の params 経由で渡されたデータにアクセスするには、observeState() を使用します。
import { dashboard } from "@wix/dashboard";
import { useEffect, useState } from "react";
function MyModal() {
const [modalData, setModalData] = useState<{ userId?: string; itemData?: any }>({});
useEffect(() => {
dashboard.observeState((state) => {
// Access custom data passed through openModal params
if (state.userId) {
setModalData({
userId: state.userId,
itemData: state.itemData,
});
}
});
}, []);
return <div>User ID: {modalData.userId}</div>;
}
モーダルを閉じる
モーダルを閉じるには、モーダル拡張機能内から closeModal() を呼び出します。必要に応じて、呼び出し元にデータを返すこともできます。
import { dashboard } from "@wix/dashboard";
// Close without returning data
dashboard.closeModal();
// Close with custom return data
dashboard.closeModal({ saved: true, itemId: "123" });
| パラメーター | 型 | 説明 |
|---|---|---|
| closeData | シリアライズ可能(任意) | モーダルの呼び出し元に渡すデータです。構造化クローンアルゴリズムでクローン可能である必要があります。 |
サポートされる型: 文字列、数値、ブール値、プレーンオブジェクト、配列、Dates、Maps、Sets、ArrayBuffers。 サポートされない型: 関数、DOM ノード、メソッドを持つクラスインスタンス、Symbols、Promises。
戻り値: void
モーダルのカスタマイズ
設定を整理するには、.config.ts を編集します。
export default {
title: 'User Settings',
width: 600,
height: 500,
}
.tsx でインポートします。
import config from './modal.config.ts';
export default function MyModal() {
return (
<CustomModalLayout
title={config.title}
// ... rest of component
/>
);
}
よくある間違い
| 間違い | 修正方法 |
|---|---|
| モーダル ID が見つからない | .extension.ts ファイルの id フィールドを確認します |
extensions.ts への登録を忘れる | モーダルをインポートして .use() します |
modalId の代わりに extensionId を使用している | openModal() では modalId を使用します |
| モーダルで params にアクセスできない | 渡されたデータを読み取るには dashboard.observeState() を使用します |
| モーダルが閉じない | @wix/dashboard の dashboard.closeModal() を使用します |
実際の使用例
// Dashboard Page: Opening edit modal
const handleEdit = async (item: Item) => {
dashboard.openModal({
modalId: "edit-item-modal-guid",
params: {
itemId: item._id,
item: item, // Objects passed directly via params
},
});
};
// Modal: Receiving and saving data
export default function ItemEditModal() {
const [formData, setFormData] = useState<Item | null>(null);
useEffect(() => {
dashboard.observeState((state) => {
if (state.item) {
setFormData(state.item);
}
});
}, []);
const handleSave = async () => {
// Save logic
dashboard.showToast({ message: "Saved!", type: "success" });
dashboard.closeModal();
};
return (
<CustomModalLayout
title="Edit Item"
primaryButtonText="Save"
onCloseButtonClick={() => dashboard.closeModal()}
primaryButtonOnClick={handleSave}
content={/* form fields */}
/>
);
}