Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add: ダイアログのデザインを調整し、文言も調整していく #2410

13 changes: 10 additions & 3 deletions docs/UX・UIデザインの方針.md
Original file line number Diff line number Diff line change
@@ -59,9 +59,16 @@
- それ以外はトーストで通知(`SHOW_NOTIFY_`系)
- 例: 音声を書き出しました。
- 例: エンジンが異常終了しました。エンジンの再起動が必要です。
- ダイアログの warning と confirm の使い分け
- 続行することが望まれそうな場合は confirm
- キャンセルすることが望まれそうな場合は warning
- ダイアログに関して
- warning と confirm の使い分け
- 続行することが望まれそうな場合は confirm
- キャンセルすることが望まれそうな場合は warning
- ダイアログの文面
- タイトルは疑問文「~しますか?」
- 本文は簡潔にし、「よろしいですか?」などを避ける
- ボタンの色
- 肯定的で、そちらを選ぶ可能性が高いボタンはPrimary色にする
- 破壊的で、状態を戻すのに手間がかかる操作を行うボタンはWarningn色にする

## 文章など

41 changes: 34 additions & 7 deletions src/components/Dialog/Dialog.ts
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ import { withProgress } from "@/store/ui";
type MediaType = "audio" | "text";

export type TextDialogResult = "OK" | "CANCEL";
export type AlertDialogOptions = {
export type MessageDialogOptions = {
type?: DialogType;
title: string;
message: string;
@@ -26,21 +26,23 @@ export type ConfirmDialogOptions = {
type?: DialogType;
title: string;
message: string;
actionName: string;
actionName: string; // ボタンテキスト
idPrimaryColorButton?: boolean; // ボタンをPrimary色にするか
Hiroshiba marked this conversation as resolved.
Show resolved Hide resolved
cancel?: string;
};
export type WarningDialogOptions = {
type?: DialogType;
title: string;
message: string;
actionName: string;
actionName: string; // ボタンテキスト
isWarningColorButton?: boolean; // ボタンをWarning色にするか
cancel?: string;
};
export type QuestionDialogOptions = {
type?: DialogType;
title: string;
message: string;
buttons: string[];
buttons: (string | { text: string; color: string })[];
cancel: number;
default?: number;
};
@@ -55,7 +57,9 @@ export type NotifyAndNotShowAgainButtonOption = {
export type LoadingScreenOption = { message: string };

// 汎用ダイアログを表示
export const showAlertDialog = async (options: AlertDialogOptions) => {

/** メッセージを知らせるダイアログ */
export const showMessageDialog = async (options: MessageDialogOptions) => {
options.ok ??= "閉じる";

const { promise, resolve } = Promise.withResolvers<void>();
@@ -74,6 +78,17 @@ export const showAlertDialog = async (options: AlertDialogOptions) => {
return "OK" as const;
};

/** エラーが起こったことを知らせるダイアログ */
export const showAlertDialog = async (
options: Omit<MessageDialogOptions, "type">,
) => {
return await showMessageDialog({
...options,
type: "error",
});
};

/** 続行することが望まれそうな場合の質問ダイアログ */
export const showConfirmDialog = async (options: ConfirmDialogOptions) => {
options.cancel ??= "キャンセル";

@@ -84,7 +99,12 @@ export const showConfirmDialog = async (options: ConfirmDialogOptions) => {
type: options.type ?? "question",
title: options.title,
message: options.message,
buttons: [options.cancel, options.actionName],
buttons: [
options.cancel,
options.idPrimaryColorButton
? { text: options.actionName, color: "primary" }
: options.actionName,
],
default: 1,
},
}).onOk(({ index }: { index: number }) => resolve(index));
@@ -94,6 +114,7 @@ export const showConfirmDialog = async (options: ConfirmDialogOptions) => {
return index === 1 ? "OK" : "CANCEL";
};

/** キャンセルすることが望まれそうな場合の質問ダイアログ */
export const showWarningDialog = async (options: WarningDialogOptions) => {
options.cancel ??= "キャンセル";

@@ -104,7 +125,12 @@ export const showWarningDialog = async (options: WarningDialogOptions) => {
type: options.type ?? "warning",
title: options.title,
message: options.message,
buttons: [options.cancel, options.actionName],
buttons: [
options.cancel,
options.isWarningColorButton
? { text: options.actionName, color: "warning" }
: options.actionName,
],
default: 0,
},
}).onOk(({ index }: { index: number }) => resolve(index));
@@ -114,6 +140,7 @@ export const showWarningDialog = async (options: WarningDialogOptions) => {
return index === 1 ? "OK" : "CANCEL";
};

/** キャンセル以外に複数の選択肢がある質問ダイアログ */
export const showQuestionDialog = async (options: QuestionDialogOptions) => {
const { promise, resolve } = Promise.withResolvers<number>();
Dialog.create({
10 changes: 6 additions & 4 deletions src/components/Dialog/DictionaryManageDialog.vue
Original file line number Diff line number Diff line change
@@ -599,9 +599,10 @@ const saveWord = async () => {
};
const deleteWord = async () => {
const result = await store.actions.SHOW_WARNING_DIALOG({
title: "登録された単語を削除しますか?",
title: "単語を削除しますか?",
message: "削除された単語は元に戻せません。",
actionName: "削除",
actionName: "削除する",
isWarningColorButton: true,
});
if (result === "OK") {
try {
@@ -625,7 +626,7 @@ const resetWord = async (id: string) => {
const result = await store.actions.SHOW_WARNING_DIALOG({
title: "単語の変更をリセットしますか?",
message: "単語の変更は破棄されてリセットされます。",
actionName: "リセット",
actionName: "リセットする",
});
if (result === "OK") {
selectedId.value = id;
@@ -640,7 +641,8 @@ const discardOrNotDialog = async (okCallback: () => void) => {
const result = await store.actions.SHOW_WARNING_DIALOG({
title: "単語の追加・変更を破棄しますか?",
message: "破棄すると、単語の追加・変更はリセットされます。",
actionName: "破棄",
actionName: "破棄する",
isWarningColorButton: true,
});
if (result === "OK") {
okCallback();
30 changes: 15 additions & 15 deletions src/components/Dialog/EngineManageDialog.vue
Original file line number Diff line number Diff line change
@@ -409,10 +409,10 @@ const getEngineDirValidationMessage = (result: EngineDirValidationResult) => {

const addEngine = async () => {
const result = await store.actions.SHOW_WARNING_DIALOG({
title: "エンジン追加の確認",
title: "エンジンを追加しますか?",
message:
"この操作はコンピュータに損害を与える可能性があります。エンジンの配布元が信頼できない場合は追加しないでください。",
actionName: "追加",
actionName: "追加する",
});
if (result === "OK") {
if (engineLoaderType.value === "dir") {
@@ -424,7 +424,7 @@ const addEngine = async () => {
);

void requireReload(
"エンジンを追加しました。反映には再読み込みが必要です。今すぐ再読み込みしますか?",
"エンジンを追加しました。反映には再読み込みが必要です。",
);
} else {
const success = await lockUi(
@@ -433,7 +433,7 @@ const addEngine = async () => {
);
if (success) {
void requireReload(
"エンジンを追加しました。反映には再読み込みが必要です。今すぐ再読み込みしますか?",
"エンジンを追加しました。反映には再読み込みが必要です。",
);
}
}
@@ -450,10 +450,11 @@ const deleteEngine = async () => {
throw new Error("default engine cannot be deleted");
}

const result = await store.actions.SHOW_CONFIRM_DIALOG({
title: "エンジン削除の確認",
message: "選択中のエンジンを削除します。よろしいですか?",
actionName: "削除",
const result = await store.actions.SHOW_WARNING_DIALOG({
title: "エンジンを削除しますか?",
message: "選択中のエンジンを削除します。",
actionName: "削除する",
isWarningColorButton: true,
});
if (result === "OK") {
switch (engineInfo.type) {
@@ -468,7 +469,7 @@ const deleteEngine = async () => {
}),
);
void requireReload(
"エンジンを削除しました。反映には再読み込みが必要です。今すぐ再読み込みしますか?",
"エンジンを削除しました。反映には再読み込みが必要です。",
);
break;
}
@@ -478,9 +479,7 @@ const deleteEngine = async () => {
store.actions.UNINSTALL_VVPP_ENGINE(engineId),
);
if (success) {
void requireReload(
"エンジンの削除には再読み込みが必要です。今すぐ再読み込みしますか?",
);
void requireReload("エンジンの削除には再読み込みが必要です。");
}
break;
}
@@ -509,11 +508,12 @@ const restartSelectedEngine = () => {
};

const requireReload = async (message: string) => {
const result = await store.actions.SHOW_WARNING_DIALOG({
title: "再読み込みが必要です",
const result = await store.actions.SHOW_CONFIRM_DIALOG({
title: "再読み込みしますか?",
message: message,
actionName: "再読み込み",
actionName: "再読み込みする",
cancel: "後で",
idPrimaryColorButton: true,
});
toInitialState();
if (result === "OK") {
5 changes: 2 additions & 3 deletions src/components/Dialog/HotkeySettingDialog.vue
Original file line number Diff line number Diff line change
@@ -242,10 +242,9 @@ const isDefaultCombination = (action: string) => {

const resetHotkey = async (action: string) => {
const result = await store.actions.SHOW_CONFIRM_DIALOG({
title: "ショートカットキーをデフォルトに戻します",
message: `${action}のショートカットキーをデフォルトに戻します。\n本当に戻しますか?`,
title: "デフォルトに戻しますか?",
message: `${action}のショートカットキーをデフォルトに戻します。`,
actionName: "デフォルトに戻す",
cancel: "デフォルトに戻さない",
});

if (result !== "OK") return;
9 changes: 5 additions & 4 deletions src/components/Dialog/PresetManageDialog.vue
Original file line number Diff line number Diff line change
@@ -103,10 +103,11 @@ const reorderPreset = (featurePresetList: (Preset & { key: PresetKey })[]) => {
};

const deletePreset = async (key: PresetKey) => {
const result = await store.actions.SHOW_CONFIRM_DIALOG({
title: "プリセット削除の確認",
message: `プリセット "${presetItems.value[key].name}" を削除してもよろしいですか?`,
actionName: "削除",
const result = await store.actions.SHOW_WARNING_DIALOG({
title: "プリセットを削除しますか?",
message: `プリセット "${presetItems.value[key].name}" を削除します。`,
actionName: "削除する",
isWarningColorButton: true,
});
if (result === "OK") {
await store.actions.DELETE_PRESET({
5 changes: 2 additions & 3 deletions src/components/Dialog/SettingDialog/SettingDialog.vue
Original file line number Diff line number Diff line change
@@ -767,11 +767,10 @@ const outputSamplingRate = computed({
set: async (outputSamplingRate: SamplingRateOption) => {
if (outputSamplingRate !== "engineDefault") {
const result = await store.actions.SHOW_CONFIRM_DIALOG({
title: "出力サンプリングレートを変更します",
title: "出力サンプリングレートを変更しますか?",
message:
"出力サンプリングレートを変更しても、音質は変化しません。また、音声の生成処理に若干時間がかかる場合があります。\n変更しますか?",
"出力サンプリングレートを変更しても、音質は変化しません。また、音声の生成処理に若干時間がかかる場合があります。",
actionName: "変更する",
cancel: "変更しない",
});
if (result !== "OK") {
return;
18 changes: 12 additions & 6 deletions src/components/Dialog/TextDialog/MessageDialog.vue
Original file line number Diff line number Diff line change
@@ -13,20 +13,26 @@
<QCard class="q-py-sm q-px-md dialog-card">
<QCardSection class="title">
<QIcon
v-if="props.type !== 'none'"
:name="iconName"
class="text-h5 q-mr-sm"
v-if="props.type !== 'info'"
:name="`sym_o_${iconName}`"
size="2rem"
class="q-mr-sm"
:color
/>
<div class="text-h5" :class="[`text-${color}`]">{{ props.title }}</div>
<div class="text-h5">{{ props.title }}</div>
</QCardSection>

<QCardSection class="q-py-none message">
<QSeparator />

<QCardSection class="message">
{{ props.message }}
</QCardSection>

<QSeparator />

<QCardActions align="right">
<QBtn
unelevated
outline
:label="props.ok"
color="toolbar-button"
textColor="toolbar-button-display"
14 changes: 13 additions & 1 deletion src/components/Dialog/TextDialog/QuestionDialog.stories.ts
Original file line number Diff line number Diff line change
@@ -33,11 +33,23 @@ export const Opened: Story = {
export const OpenedMultiline: Story = {
name: "開いている:複数行",
args: {
modelValue: true,
...Opened.args,
message: "メッセージ\n複数行",
},
};

export const OpenedButtonColor: Story = {
name: "開いている:ボタン色を変える",
args: {
...Opened.args,
buttons: [
{ text: "primary", color: "primary" },
{ text: "warning", color: "warning" },
"default",
],
},
};

export const Close: Story = {
name: "Aを押す",
args: { ...Opened.args },
Loading
Loading