mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
chore(desktop): delete dead persona catalog UI cluster (#2886)
## Summary - Deletes 6 orphaned files in `desktop/src/features/agents/ui/` (556 lines) that formed a closed cluster with zero imports from the reachable module graph — orphaned by the 1B dialog consolidation (`PersonaCatalogSurface`, `PersonaCatalogSection`, `PersonaCatalogDetailsSheet`, `PersonaCatalogSelectionBadge`, `PersonaIdentity`, `PersonaLibraryEntryPoints`). - Removes a stale `check-file-sizes.mjs` override entry for the no-longer-existent `PersonaDialog.tsx`. Verified dead two ways: import-graph reachability walk from all entry points puts all six outside the reachable set, and `tsc --noEmit` passes clean after deletion. Their `data-testid`s have zero references outside the cluster. `PersonaCatalogDialog.tsx` is alive (`AgentsView` imports it) and stays. Independent of #1968 — pure dead code removal, no behavioral change.
This commit is contained in:
@@ -219,20 +219,6 @@ const overrides = new Map([
|
||||
// (+3) — the new team-id spawn link and the runtime-layered instructions
|
||||
// field.
|
||||
["src/shared/api/types.ts", 1047],
|
||||
// readiness-gate: PersonaDialog.tsx threads computeLocalModeGate +
|
||||
// requiredCredentialEnvKeys + RequiredFieldLabel so the "New agent" dialog
|
||||
// shows required markers and credential amber rows (parity with
|
||||
// CreateAgentDialog). +23 lines of gate wiring. Queued to split.
|
||||
// config-bridge-aware requirements: useRuntimeFileConfigQuery wiring adds
|
||||
// ~16 lines. Queued to split.
|
||||
// baked-env-required-badge: useBakedBuildEnvKeysQuery + bakedEnvKeys wiring
|
||||
// + correct exclusion-semantics for requiredEnvKeys adds ~14 lines.
|
||||
// +2 lines: filter managed provider key from requiredEnvKeys (suppress dead-input locked row).
|
||||
// global-agent-config parity: wire useGlobalAgentConfig into PersonaDialog
|
||||
// (Gap A: global-aware computeLocalModeGate + drop bare requiredCredentialEnvKeys;
|
||||
// Gap B: hasAutoOpenedAdvancedRef auto-expand effect) + effective-provider
|
||||
// save gate + Inherit/Select-a-provider label. Queued to split.
|
||||
["src/features/agents/ui/PersonaDialog.tsx", 1080],
|
||||
// harness-persona-sync feature growth, queued to split in the resolver-unify
|
||||
// refactor followup. discovery.rs is dominated by the new test module
|
||||
// (the effective_agent_command / divergent / create-time override matrix);
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
import { isCatalogPersonaSelected } from "@/features/agents/lib/catalog";
|
||||
import { ProfileAvatar } from "@/features/profile/ui/ProfileAvatar";
|
||||
import type { AgentPersona } from "@/shared/api/types";
|
||||
import { cn } from "@/shared/lib/cn";
|
||||
import { promptPreview } from "@/shared/lib/promptPreview";
|
||||
import {
|
||||
Sheet,
|
||||
SheetContent,
|
||||
SheetDescription,
|
||||
SheetHeader,
|
||||
SheetTitle,
|
||||
} from "@/shared/ui/sheet";
|
||||
|
||||
import { PersonaCatalogSelectionBadge } from "./PersonaCatalogSelectionBadge";
|
||||
import {
|
||||
getPersonaCatalogDetailSelectionCopy,
|
||||
getPersonaCatalogSelectionAriaLabel,
|
||||
} from "./personaLibraryCopy";
|
||||
|
||||
type PersonaCatalogDetailsSheetProps = {
|
||||
feedbackErrorMessage: string | null;
|
||||
feedbackNoticeMessage: string | null;
|
||||
isPending: boolean;
|
||||
onOpenChange: (open: boolean) => void;
|
||||
onTogglePersona: (persona: AgentPersona) => void;
|
||||
open: boolean;
|
||||
persona: AgentPersona | null;
|
||||
};
|
||||
|
||||
export function PersonaCatalogDetailsSheet({
|
||||
feedbackErrorMessage,
|
||||
feedbackNoticeMessage,
|
||||
isPending,
|
||||
onOpenChange,
|
||||
onTogglePersona,
|
||||
open,
|
||||
persona,
|
||||
}: PersonaCatalogDetailsSheetProps) {
|
||||
const preview = persona ? promptPreview(persona.systemPrompt) : "";
|
||||
const isSelected = persona ? isCatalogPersonaSelected(persona) : false;
|
||||
const selectionCopy = getPersonaCatalogDetailSelectionCopy(isSelected);
|
||||
|
||||
return (
|
||||
<Sheet onOpenChange={onOpenChange} open={open}>
|
||||
<SheetContent
|
||||
className="flex w-full flex-col gap-0 overflow-hidden bg-background p-0 sm:max-w-xl"
|
||||
data-testid="persona-catalog-details-sheet"
|
||||
>
|
||||
{persona ? (
|
||||
<>
|
||||
<SheetHeader className="relative z-10 space-y-4 bg-background/25 px-6 py-6 pr-16 text-left shadow-[0_4px_24px_rgba(0,0,0,0.06)] backdrop-blur-xl supports-[backdrop-filter]:bg-background/20 dark:shadow-[0_4px_24px_rgba(0,0,0,0.25)]">
|
||||
<div className="flex items-start gap-3">
|
||||
<ProfileAvatar
|
||||
avatarUrl={persona.avatarUrl}
|
||||
className="h-12 w-12 text-sm"
|
||||
label={persona.displayName}
|
||||
/>
|
||||
<div className="min-w-0 flex-1">
|
||||
<div className="flex flex-wrap items-center gap-2">
|
||||
<SheetTitle className="truncate text-xl">
|
||||
{persona.displayName}
|
||||
</SheetTitle>
|
||||
<PersonaCatalogSelectionBadge isActive={isSelected} />
|
||||
</div>
|
||||
<SheetDescription className="mt-2">
|
||||
{preview || "No summary available."}
|
||||
</SheetDescription>
|
||||
</div>
|
||||
</div>
|
||||
</SheetHeader>
|
||||
<div className="flex-1 space-y-6 overflow-y-auto px-6 py-6">
|
||||
<button
|
||||
aria-label={getPersonaCatalogSelectionAriaLabel(
|
||||
persona.displayName,
|
||||
isSelected,
|
||||
)}
|
||||
aria-pressed={isSelected}
|
||||
className={cn(
|
||||
"w-full rounded-xl border p-4 text-left transition-[background-color,border-color,box-shadow] focus:outline-hidden focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2",
|
||||
isSelected
|
||||
? "border-primary bg-primary/10 text-foreground"
|
||||
: "border-border/80 bg-background/60 text-muted-foreground hover:bg-accent hover:text-accent-foreground",
|
||||
isPending && "cursor-not-allowed opacity-70",
|
||||
)}
|
||||
data-state={isSelected ? "selected" : "available"}
|
||||
data-testid={`persona-catalog-detail-selection-target-${persona.id}`}
|
||||
disabled={isPending}
|
||||
onClick={() => {
|
||||
onTogglePersona(persona);
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
<div className="flex items-start justify-between gap-4">
|
||||
<div>
|
||||
<p
|
||||
className="text-sm font-semibold tracking-tight"
|
||||
data-testid="persona-catalog-detail-selection-title"
|
||||
>
|
||||
{selectionCopy.title}
|
||||
</p>
|
||||
<p
|
||||
className="mt-1 text-sm text-muted-foreground"
|
||||
data-testid="persona-catalog-detail-selection-description"
|
||||
>
|
||||
{selectionCopy.description}
|
||||
</p>
|
||||
</div>
|
||||
<PersonaCatalogSelectionBadge isActive={isSelected} />
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{feedbackNoticeMessage ? (
|
||||
<p className="rounded-2xl border border-primary/20 bg-primary/10 px-4 py-3 text-sm text-primary">
|
||||
{feedbackNoticeMessage}
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{feedbackErrorMessage ? (
|
||||
<p className="rounded-2xl border border-destructive/30 bg-destructive/10 px-4 py-3 text-sm text-destructive">
|
||||
{feedbackErrorMessage}
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
<div className="grid gap-3 sm:grid-cols-2">
|
||||
<div className="rounded-xl border border-border/70 bg-card/70 p-4">
|
||||
<p className="text-2xs font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
Type
|
||||
</p>
|
||||
<p className="mt-2 text-sm font-medium">Built-in agent</p>
|
||||
</div>
|
||||
<div className="rounded-xl border border-border/70 bg-card/70 p-4">
|
||||
<p className="text-2xs font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
Preferred model
|
||||
</p>
|
||||
<p className="mt-2 text-sm font-medium">
|
||||
{persona.model ?? "Use app default"}
|
||||
</p>
|
||||
</div>
|
||||
<div className="rounded-xl border border-border/70 bg-card/70 p-4 sm:col-span-2">
|
||||
<p className="text-2xs font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
Preferred runtime
|
||||
</p>
|
||||
<p className="mt-2 text-sm font-medium">
|
||||
{persona.runtime ?? "Use app default"}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="rounded-xl border border-border/70 bg-card/70 p-4">
|
||||
<p className="text-2xs font-semibold uppercase tracking-wide text-muted-foreground">
|
||||
System prompt
|
||||
</p>
|
||||
<pre className="mt-3 whitespace-pre-wrap break-words font-sans text-sm leading-6 text-foreground">
|
||||
{persona.systemPrompt}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : null}
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
);
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
import { isCatalogPersonaSelected } from "@/features/agents/lib/catalog";
|
||||
import type { AgentPersona } from "@/shared/api/types";
|
||||
import { promptPreview } from "@/shared/lib/promptPreview";
|
||||
import { cn } from "@/shared/lib/cn";
|
||||
import { Button } from "@/shared/ui/button";
|
||||
import { Card } from "@/shared/ui/card";
|
||||
import { Skeleton } from "@/shared/ui/skeleton";
|
||||
import { PersonaCatalogSelectionBadge } from "./PersonaCatalogSelectionBadge";
|
||||
import { PersonaIdentity } from "./PersonaIdentity";
|
||||
import {
|
||||
getPersonaCatalogSelectionActionCopy,
|
||||
getPersonaCatalogSelectionAriaLabel,
|
||||
personaCatalogCopy,
|
||||
} from "./personaLibraryCopy";
|
||||
|
||||
type PersonaCatalogSectionProps = {
|
||||
emptyDescription?: string;
|
||||
emptyTitle?: string;
|
||||
error: Error | null;
|
||||
isLoading: boolean;
|
||||
isPending: boolean;
|
||||
onTogglePersona: (persona: AgentPersona) => void;
|
||||
onViewDetails: (persona: AgentPersona) => void;
|
||||
personas: AgentPersona[];
|
||||
showHeader?: boolean;
|
||||
};
|
||||
|
||||
export function PersonaCatalogSection({
|
||||
emptyDescription = personaCatalogCopy.emptyCatalogDescription,
|
||||
emptyTitle = personaCatalogCopy.emptyCatalogTitle,
|
||||
error,
|
||||
isLoading,
|
||||
isPending,
|
||||
onTogglePersona,
|
||||
onViewDetails,
|
||||
personas,
|
||||
showHeader = true,
|
||||
}: PersonaCatalogSectionProps) {
|
||||
return (
|
||||
<section className="space-y-4" data-testid="agents-persona-catalog">
|
||||
{showHeader ? (
|
||||
<div>
|
||||
<h3 className="text-sm font-semibold tracking-tight">
|
||||
{personaCatalogCopy.title}
|
||||
</h3>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
{personaCatalogCopy.description}
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{isLoading ? (
|
||||
<div className="grid gap-3 md:grid-cols-3 xl:grid-cols-4">
|
||||
{["first", "second", "third", "fourth"].map((key) => (
|
||||
<Card className="p-3" key={key}>
|
||||
<div className="flex items-center gap-2.5">
|
||||
<Skeleton className="h-8 w-8 rounded-lg" />
|
||||
<div className="space-y-2">
|
||||
<Skeleton className="h-4 w-24" />
|
||||
<Skeleton className="h-3 w-20" />
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{!isLoading && personas.length > 0 ? (
|
||||
<div className="grid gap-3 md:grid-cols-3 xl:grid-cols-4">
|
||||
{personas.map((persona) => {
|
||||
const preview = promptPreview(persona.systemPrompt);
|
||||
const isSelected = isCatalogPersonaSelected(persona);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"group relative flex flex-col gap-4 rounded-xl border p-3 shadow-xs transition-[background-color,border-color,box-shadow]",
|
||||
isPending
|
||||
? "cursor-not-allowed opacity-70"
|
||||
: "cursor-pointer",
|
||||
isSelected
|
||||
? "border-primary bg-primary/10 text-foreground"
|
||||
: "border-border/80 bg-background/60 hover:bg-accent hover:text-accent-foreground",
|
||||
)}
|
||||
data-testid={`persona-catalog-card-${persona.id}`}
|
||||
data-state={isSelected ? "selected" : "available"}
|
||||
key={persona.id}
|
||||
>
|
||||
<button
|
||||
aria-label={getPersonaCatalogSelectionAriaLabel(
|
||||
persona.displayName,
|
||||
isSelected,
|
||||
)}
|
||||
aria-pressed={isSelected}
|
||||
className="absolute inset-0 z-0 rounded-xl focus:outline-hidden focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2"
|
||||
data-testid={`persona-catalog-card-target-${persona.id}`}
|
||||
disabled={isPending}
|
||||
onClick={() => {
|
||||
onTogglePersona(persona);
|
||||
}}
|
||||
type="button"
|
||||
/>
|
||||
|
||||
<div className="pointer-events-none relative z-10 flex h-full flex-col gap-4">
|
||||
<div className="flex items-start justify-between gap-3">
|
||||
<PersonaIdentity
|
||||
className="min-w-0 flex-1"
|
||||
persona={persona}
|
||||
showBuiltInBadge={false}
|
||||
showPromptTooltip={false}
|
||||
/>
|
||||
|
||||
<PersonaCatalogSelectionBadge isActive={isSelected} />
|
||||
</div>
|
||||
|
||||
<p className="min-h-12 text-xs leading-5 text-muted-foreground">
|
||||
{preview}
|
||||
</p>
|
||||
|
||||
<div
|
||||
className={cn(
|
||||
"mt-auto flex items-center justify-between gap-3 border-t pt-3",
|
||||
isSelected ? "border-primary/20" : "border-border/60",
|
||||
)}
|
||||
>
|
||||
<Button
|
||||
className="pointer-events-auto"
|
||||
data-testid={`persona-catalog-details-${persona.id}`}
|
||||
onClick={() => {
|
||||
onViewDetails(persona);
|
||||
}}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant="ghost"
|
||||
>
|
||||
{personaCatalogCopy.detailsAction}
|
||||
</Button>
|
||||
|
||||
<span className="text-xs font-medium text-muted-foreground">
|
||||
{getPersonaCatalogSelectionActionCopy(isSelected)}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{!isLoading && personas.length === 0 ? (
|
||||
<div className="rounded-xl border border-dashed border-border/70 px-6 py-10 text-center">
|
||||
<p className="text-sm font-semibold tracking-tight">{emptyTitle}</p>
|
||||
<p className="mt-2 text-sm text-muted-foreground">
|
||||
{emptyDescription}
|
||||
</p>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{error ? (
|
||||
<p className="rounded-2xl border border-destructive/30 bg-destructive/10 px-4 py-3 text-sm text-destructive">
|
||||
{error.message}
|
||||
</p>
|
||||
) : null}
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
import { Check } from "lucide-react";
|
||||
|
||||
import { cn } from "@/shared/lib/cn";
|
||||
|
||||
import { personaCatalogCopy } from "./personaLibraryCopy";
|
||||
|
||||
type PersonaCatalogSelectionBadgeProps = {
|
||||
isActive: boolean;
|
||||
};
|
||||
|
||||
export function PersonaCatalogSelectionBadge({
|
||||
isActive,
|
||||
}: PersonaCatalogSelectionBadgeProps) {
|
||||
return (
|
||||
<span
|
||||
className={cn(
|
||||
"inline-flex items-center gap-1 whitespace-nowrap rounded-full px-2.5 py-1 text-2xs font-semibold uppercase tracking-[0.14em]",
|
||||
isActive
|
||||
? "bg-primary text-primary-foreground shadow-xs"
|
||||
: "border border-border/70 bg-background/85 text-muted-foreground",
|
||||
)}
|
||||
>
|
||||
{isActive ? <Check className="h-4 w-4" /> : null}
|
||||
{isActive
|
||||
? personaCatalogCopy.selectedState
|
||||
: personaCatalogCopy.availableState}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
import * as React from "react";
|
||||
|
||||
import { isCatalogPersonaSelected } from "@/features/agents/lib/catalog";
|
||||
import type { AgentPersona } from "@/shared/api/types";
|
||||
import { useFeedbackToasts } from "@/shared/hooks/useToastEffect";
|
||||
|
||||
import { PersonaCatalogDetailsSheet } from "./PersonaCatalogDetailsSheet";
|
||||
import { PersonaCatalogSection } from "./PersonaCatalogSection";
|
||||
|
||||
type PersonaCatalogSurfaceProps = {
|
||||
error: Error | null;
|
||||
feedbackErrorMessage: string | null;
|
||||
feedbackNoticeMessage: string | null;
|
||||
isLoading: boolean;
|
||||
isPending: boolean;
|
||||
onClearFeedback: () => void;
|
||||
onSelectPersona: (persona: AgentPersona, active: boolean) => void;
|
||||
personas: AgentPersona[];
|
||||
showHeader?: boolean;
|
||||
};
|
||||
|
||||
export function PersonaCatalogSurface({
|
||||
error,
|
||||
feedbackErrorMessage,
|
||||
feedbackNoticeMessage,
|
||||
isLoading,
|
||||
isPending,
|
||||
onClearFeedback,
|
||||
onSelectPersona,
|
||||
personas,
|
||||
showHeader = true,
|
||||
}: PersonaCatalogSurfaceProps) {
|
||||
const [detailPersonaId, setDetailPersonaId] = React.useState<string | null>(
|
||||
null,
|
||||
);
|
||||
const detailPersona = React.useMemo(
|
||||
() =>
|
||||
detailPersonaId
|
||||
? (personas.find((persona) => persona.id === detailPersonaId) ?? null)
|
||||
: null,
|
||||
[detailPersonaId, personas],
|
||||
);
|
||||
const handleTogglePersona = (persona: AgentPersona) => {
|
||||
onSelectPersona(persona, !isCatalogPersonaSelected(persona));
|
||||
};
|
||||
|
||||
useFeedbackToasts(feedbackNoticeMessage, feedbackErrorMessage);
|
||||
|
||||
return (
|
||||
<>
|
||||
<PersonaCatalogSection
|
||||
error={error}
|
||||
isLoading={isLoading}
|
||||
isPending={isPending}
|
||||
onTogglePersona={handleTogglePersona}
|
||||
onViewDetails={(persona) => {
|
||||
onClearFeedback();
|
||||
setDetailPersonaId(persona.id);
|
||||
}}
|
||||
personas={personas}
|
||||
showHeader={showHeader}
|
||||
/>
|
||||
|
||||
<PersonaCatalogDetailsSheet
|
||||
feedbackErrorMessage={feedbackErrorMessage}
|
||||
feedbackNoticeMessage={feedbackNoticeMessage}
|
||||
isPending={isPending}
|
||||
onOpenChange={(open) => {
|
||||
if (!open) {
|
||||
setDetailPersonaId(null);
|
||||
}
|
||||
}}
|
||||
onTogglePersona={handleTogglePersona}
|
||||
open={detailPersonaId !== null}
|
||||
persona={detailPersona}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
import { Info } from "lucide-react";
|
||||
|
||||
import { ProfileAvatar } from "@/features/profile/ui/ProfileAvatar";
|
||||
import type { AgentPersona } from "@/shared/api/types";
|
||||
import { cn } from "@/shared/lib/cn";
|
||||
import { promptPreview } from "@/shared/lib/promptPreview";
|
||||
import { Badge } from "@/shared/ui/badge";
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/shared/ui/tooltip";
|
||||
|
||||
type PersonaIdentityProps = {
|
||||
className?: string;
|
||||
persona: AgentPersona;
|
||||
showBuiltInBadge?: boolean;
|
||||
showPromptTooltip?: boolean;
|
||||
};
|
||||
|
||||
export function PersonaIdentity({
|
||||
className,
|
||||
persona,
|
||||
showBuiltInBadge = persona.isBuiltIn,
|
||||
showPromptTooltip = true,
|
||||
}: PersonaIdentityProps) {
|
||||
const preview = promptPreview(persona.systemPrompt);
|
||||
|
||||
return (
|
||||
<div className={cn("min-w-0 flex-1", className)}>
|
||||
<div className="flex min-w-0 items-center gap-2.5">
|
||||
<ProfileAvatar
|
||||
avatarUrl={persona.avatarUrl}
|
||||
className="h-8 w-8 rounded-lg text-xs"
|
||||
label={persona.displayName}
|
||||
/>
|
||||
<div className="min-w-0">
|
||||
<div className="flex min-w-0 items-center gap-2">
|
||||
<p className="truncate text-sm font-semibold tracking-tight">
|
||||
{persona.displayName}
|
||||
</p>
|
||||
{showBuiltInBadge ? (
|
||||
<Badge variant="secondary">Built-in</Badge>
|
||||
) : null}
|
||||
{showPromptTooltip && preview ? (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
aria-label="View system prompt"
|
||||
className="flex h-4 w-4 shrink-0 items-center justify-center text-muted-foreground transition-colors hover:text-foreground"
|
||||
type="button"
|
||||
>
|
||||
<Info className="h-4 w-4" />
|
||||
</button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="bottom" className="max-w-xs">
|
||||
<p>{preview}</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { Upload } from "lucide-react";
|
||||
|
||||
import { Button } from "@/shared/ui/button";
|
||||
|
||||
import { CreateNewButton } from "./CreateNewButton";
|
||||
import { personaLibraryCopy } from "./personaLibraryCopy";
|
||||
|
||||
type PersonaLibraryEntryPointsProps = {
|
||||
canChooseCatalog?: boolean;
|
||||
isPending: boolean;
|
||||
layout: "header" | "empty";
|
||||
onCreate: () => void;
|
||||
onChooseCatalog?: () => void;
|
||||
onImport?: () => void;
|
||||
};
|
||||
|
||||
export function PersonaLibraryEntryPoints({
|
||||
canChooseCatalog = false,
|
||||
isPending,
|
||||
layout,
|
||||
onCreate,
|
||||
onChooseCatalog,
|
||||
onImport,
|
||||
}: PersonaLibraryEntryPointsProps) {
|
||||
const isHeader = layout === "header";
|
||||
const chooseVariant = isHeader ? "outline" : "default";
|
||||
const createVariant = isHeader ? "default" : "outline";
|
||||
|
||||
return (
|
||||
<>
|
||||
{canChooseCatalog && onChooseCatalog ? (
|
||||
<Button
|
||||
data-testid="open-persona-catalog"
|
||||
disabled={isPending}
|
||||
onClick={onChooseCatalog}
|
||||
size="sm"
|
||||
type="button"
|
||||
variant={chooseVariant}
|
||||
>
|
||||
{personaLibraryCopy.chooseFromCatalog}
|
||||
</Button>
|
||||
) : null}
|
||||
<CreateNewButton
|
||||
disabled={isPending}
|
||||
label={personaLibraryCopy.createNew}
|
||||
onClick={onCreate}
|
||||
variant={createVariant}
|
||||
/>
|
||||
{!isHeader && onImport ? (
|
||||
<Button onClick={onImport} size="sm" type="button" variant="outline">
|
||||
<Upload className="h-4 w-4" />
|
||||
{personaLibraryCopy.import}
|
||||
</Button>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user