feat: improve empty state guidance for first-run experience

Show detailed import instructions and conditionally display common
config snippet hint for Claude/Codex/Gemini (not OpenCode/OpenClaw).
This commit is contained in:
Jason
2026-03-12 23:42:15 +08:00
parent 8e1204b1ee
commit 305c0f2e08
5 changed files with 18 additions and 4 deletions

View File

@@ -1,17 +1,22 @@
import { Download, Users } from "lucide-react";
import { useTranslation } from "react-i18next";
import { Button } from "@/components/ui/button";
import type { AppId } from "@/lib/api/types";
interface ProviderEmptyStateProps {
appId: AppId;
onCreate?: () => void;
onImport?: () => void;
}
export function ProviderEmptyState({
appId,
onCreate,
onImport,
}: ProviderEmptyStateProps) {
const { t } = useTranslation();
const showSnippetHint =
appId === "claude" || appId === "codex" || appId === "gemini";
return (
<div className="flex flex-col items-center justify-center rounded-lg border border-dashed border-border p-10 text-center">
@@ -19,9 +24,14 @@ export function ProviderEmptyState({
<Users className="h-7 w-7 text-muted-foreground" />
</div>
<h3 className="text-lg font-semibold">{t("provider.noProviders")}</h3>
<p className="mt-2 max-w-sm text-sm text-muted-foreground">
<p className="mt-2 max-w-lg text-sm text-muted-foreground">
{t("provider.noProvidersDescription")}
</p>
{showSnippetHint && (
<p className="mt-1 max-w-lg text-sm text-muted-foreground">
{t("provider.noProvidersDescriptionSnippet")}
</p>
)}
<div className="mt-6 flex flex-col gap-2">
{onImport && (
<Button onClick={onImport}>

View File

@@ -298,6 +298,7 @@ export function ProviderList({
if (sortedProviders.length === 0) {
return (
<ProviderEmptyState
appId={appId}
onCreate={onCreate}
onImport={() => importMutation.mutate()}
/>

View File

@@ -80,7 +80,8 @@
"tabProvider": "Provider",
"tabUniversal": "Universal",
"noProviders": "No providers added yet",
"noProvidersDescription": "Import your current live config below, or manually add a new provider",
"noProvidersDescription": "If you already have a config, click \"Import Current Config\" — all data will be safely saved in a default provider",
"noProvidersDescriptionSnippet": "Settings other than API key and endpoint (e.g. plugins) will be saved to a common config snippet for sharing across providers",
"importCurrent": "Import Current Config",
"importCurrentDescription": "Import current live config as default provider",
"currentlyUsing": "Currently Using",

View File

@@ -80,7 +80,8 @@
"tabProvider": "プロバイダー",
"tabUniversal": "統一プロバイダー",
"noProviders": "まだプロバイダーがありません",
"noProvidersDescription": "下の「現在の設定をインポート」ボタンで既存の設定を取り込むか、新しいプロバイダーを手動で追加してください",
"noProvidersDescription": "既存の設定がある場合は「現在の設定をインポート」をクリックしてください。すべてのデータが default プロバイダーに安全に保存されます",
"noProvidersDescriptionSnippet": "API キーとリクエスト URL 以外のデータ(プラグインなど)は共通設定スニペットに保存され、プロバイダー間で共有できます",
"importCurrent": "現在の設定をインポート",
"importCurrentDescription": "現在使用中の設定をデフォルトプロバイダーとしてインポート",
"currentlyUsing": "現在使用中",

View File

@@ -80,7 +80,8 @@
"tabProvider": "供应商",
"tabUniversal": "统一供应商",
"noProviders": "还没有添加任何供应商",
"noProvidersDescription": "点击下方的\"导入当前配置\"按钮导入已有配置,或手动添加新的供应商",
"noProvidersDescription": "如果你已有配置,请点击\"导入当前配置\",所有数据将安全保存在 default 供应商",
"noProvidersDescriptionSnippet": "除 Key 和请求地址外的数据(如插件配置)会被保存到通用配置片段,用于在不同供应商之间共享",
"importCurrent": "导入当前配置",
"importCurrentDescription": "将当前正在使用的配置导入为默认供应商",
"currentlyUsing": "当前使用",