Merge pull request #2536 from arc53/better-dropdown-prompt

feat: better prompt dropdown
This commit is contained in:
Alex authored and GitHub committed 2026-06-12 16:47:51 +01:00
commit f8bb0002af
10 files changed
+311 -153

No files matched your search

+1 -1
View File
@@ -1523,7 +1523,7 @@ function AddPromptModal({
onClose();
setNewPromptName('');
setNewPromptContent('');
onSelect?.(newPromptName, newPrompt.id, newPromptContent);
onSelect?.(newPromptName, newPrompt.id, 'private');
} catch (error) {
console.error('Error adding prompt:', error);
}
+5
View File
@@ -481,6 +481,11 @@
"addDescription": "Füge deinen benutzerdefinierten Prompt hinzu und speichere ihn in DocsGPT",
"editPrompt": "Prompt bearbeiten",
"editDescription": "Bearbeite deinen benutzerdefinierten Prompt und speichere ihn in DocsGPT",
"viewPrompt": "Prompt ansehen",
"viewDescription": "Integrierte Prompts können nicht bearbeitet werden. Dupliziere ihn, um eine eigene bearbeitbare Kopie zu erstellen.",
"duplicate": "Duplizieren",
"duplicatePrompt": "Prompt duplizieren",
"duplicateDescription": "Du bearbeitest eine Kopie von „{{name}}“ – speichere sie als eigenen Prompt",
"promptName": "Prompt-Name",
"promptText": "Prompt-Text",
"save": "Speichern",
+5
View File
@@ -574,6 +574,11 @@
"addDescription": "Add your custom prompt and save it to DocsGPT",
"editPrompt": "Edit Prompt",
"editDescription": "Edit your custom prompt and save it to DocsGPT",
"viewPrompt": "View Prompt",
"viewDescription": "Built-in prompts can't be edited. Duplicate to create your own editable copy.",
"duplicate": "Duplicate",
"duplicatePrompt": "Duplicate Prompt",
"duplicateDescription": "You're editing a copy of \"{{name}}\" — save it as your own prompt",
"promptName": "Prompt Name",
"promptText": "Prompt Text",
"save": "Save",
+5
View File
@@ -499,6 +499,11 @@
"addDescription": "Agrega tu prompt personalizado y guárdalo en DocsGPT",
"editPrompt": "Editar Prompt",
"editDescription": "Edita tu prompt personalizado y guárdalo en DocsGPT",
"viewPrompt": "Ver Prompt",
"viewDescription": "Los prompts integrados no se pueden editar. Duplícalo para crear tu propia copia editable.",
"duplicate": "Duplicar",
"duplicatePrompt": "Duplicar Prompt",
"duplicateDescription": "Estás editando una copia de \"{{name}}\"; guárdala como tu propio prompt",
"promptName": "Nombre del Prompt",
"promptText": "Texto del Prompt",
"save": "Guardar",
+5
View File
@@ -499,6 +499,11 @@
"addDescription": "カスタムプロンプトを追加して DocsGPT に保存します",
"editPrompt": "プロンプトを編集",
"editDescription": "カスタムプロンプトを編集して DocsGPT に保存します",
"viewPrompt": "プロンプトを表示",
"viewDescription": "組み込みプロンプトは編集できません。複製して編集可能なコピーを作成してください。",
"duplicate": "複製",
"duplicatePrompt": "プロンプトを複製",
"duplicateDescription": "「{{name}}」のコピーを編集中です。自分のプロンプトとして保存してください",
"promptName": "プロンプト名",
"promptText": "プロンプトのテキスト",
"save": "保存",
+5
View File
@@ -499,6 +499,11 @@
"addDescription": "Добавьте свой собственный промпт и сохраните его в DocsGPT",
"editPrompt": "Редактировать промпт",
"editDescription": "Отредактируйте свой промпт и сохраните его в DocsGPT",
"viewPrompt": "Просмотр промпта",
"viewDescription": "Встроенные промпты нельзя редактировать. Дублируйте, чтобы создать свою редактируемую копию.",
"duplicate": "Дублировать",
"duplicatePrompt": "Дублировать промпт",
"duplicateDescription": "Вы редактируете копию «{{name}}» — сохраните её как свой промпт",
"promptName": "Название промпта",
"promptText": "Текст промпта",
"save": "Сохранить",
+5
View File
@@ -499,6 +499,11 @@
"addDescription": "新增自定義提示並儲存到 DocsGPT",
"editPrompt": "編輯提示",
"editDescription": "編輯自定義提示並儲存到 DocsGPT",
"viewPrompt": "檢視提示",
"viewDescription": "內建提示無法編輯。建立副本後即可自行編輯。",
"duplicate": "建立副本",
"duplicatePrompt": "建立提示副本",
"duplicateDescription": "正在編輯「{{name}}」的副本,儲存後即為您自己的提示",
"promptName": "提示名稱",
"promptText": "提示文字",
"save": "儲存",
+5
View File
@@ -499,6 +499,11 @@
"addDescription": "添加自定义提示并保存到 DocsGPT",
"editPrompt": "编辑提示",
"editDescription": "编辑自定义提示并保存到 DocsGPT",
"viewPrompt": "查看提示",
"viewDescription": "内置提示无法编辑。复制后可创建您自己的可编辑副本。",
"duplicate": "创建副本",
"duplicatePrompt": "创建提示副本",
"duplicateDescription": "正在编辑“{{name}}”的副本,保存后即为您自己的提示",
"promptName": "提示名称",
"promptText": "提示文本",
"save": "保存",
+125 -99
View File
@@ -175,6 +175,7 @@ type PromptTextareaProps = {
value: string;
onChange: (event: React.ChangeEvent<HTMLTextAreaElement>) => void;
ariaLabel: string;
readOnly?: boolean;
};
function PromptTextarea({
@@ -182,6 +183,7 @@ function PromptTextarea({
value,
onChange,
ariaLabel,
readOnly = false,
}: PromptTextareaProps) {
const [scrollOffsets, setScrollOffsets] = React.useState({ top: 0, left: 0 });
const highlightedValue = React.useMemo(
@@ -220,6 +222,7 @@ function PromptTextarea({
onScroll={handleScroll}
placeholder=" "
aria-label={ariaLabel}
readOnly={readOnly}
/>
</>
);
@@ -298,6 +301,7 @@ function AddPrompt({
newPromptContent,
setNewPromptContent,
disableSave,
duplicateSourceName,
}: {
setModalState: (state: ActiveState) => void;
handleAddPrompt?: () => void;
@@ -306,6 +310,7 @@ function AddPrompt({
newPromptContent: string;
setNewPromptContent: (content: string) => void;
disableSave: boolean;
duplicateSourceName?: string | null;
}) {
const { t } = useTranslation();
const systemVariableOptions = React.useMemo(
@@ -317,10 +322,16 @@ function AddPrompt({
return (
<div>
<p className="mb-1 text-xl font-semibold text-[#2B2B2B] dark:text-white">
{t('modals.prompts.addPrompt')}
{duplicateSourceName
? t('modals.prompts.duplicatePrompt')
: t('modals.prompts.addPrompt')}
</p>
<p className="dark:text-muted-foreground mb-6 text-sm text-[#6B6B6B]">
{t('modals.prompts.addDescription')}
{duplicateSourceName
? t('modals.prompts.duplicateDescription', {
name: duplicateSourceName,
})
: t('modals.prompts.addDescription')}
</p>
<div>
<Input
@@ -433,6 +444,7 @@ function EditPrompt({
setEditPromptContent,
currentPromptEdit,
disableSave,
onDuplicate,
}: {
setModalState: (state: ActiveState) => void;
handleEditPrompt?: (id: string, type: string) => void;
@@ -442,6 +454,7 @@ function EditPrompt({
setEditPromptContent: (content: string) => void;
currentPromptEdit: { name: string; id: string; type: string };
disableSave: boolean;
onDuplicate?: () => void;
}) {
const { t } = useTranslation();
const systemVariableOptions = React.useMemo(
@@ -449,14 +462,23 @@ function EditPrompt({
[t],
);
const toolVariables = useToolVariables();
const isReadOnly = currentPromptEdit.type === 'public';
return (
<div>
<p className="mb-1 text-xl font-semibold text-[#2B2B2B] dark:text-white">
{t('modals.prompts.editPrompt')}
{t(
isReadOnly
? 'modals.prompts.viewPrompt'
: 'modals.prompts.editPrompt',
)}
</p>
<p className="dark:text-muted-foreground mb-6 text-sm text-[#6B6B6B]">
{t('modals.prompts.editDescription')}
{t(
isReadOnly
? 'modals.prompts.viewDescription'
: 'modals.prompts.editDescription',
)}
</p>
<div>
<Input
@@ -466,6 +488,7 @@ function EditPrompt({
value={editPromptName}
onChange={(e) => setEditPromptName(e.target.value)}
labelBgClassName="bg-card"
disabled={isReadOnly}
/>
<div className="relative w-full">
@@ -474,6 +497,7 @@ function EditPrompt({
value={editPromptContent}
onChange={(e) => setEditPromptContent(e.target.value)}
ariaLabel={t('prompts.textAriaLabel')}
readOnly={isReadOnly}
/>
<label
htmlFor="edit-prompt-content"
@@ -486,36 +510,38 @@ function EditPrompt({
</div>
</div>
<div className="mt-6 flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center sm:gap-4">
<p className="flex flex-col text-sm font-medium text-gray-700 dark:text-gray-300">
<span className="font-bold">
{t('modals.prompts.variablesLabel')}
</span>
<span className="text-muted-foreground text-xs font-medium">
{t('modals.prompts.variablesDescription')}
</span>
</p>
{!isReadOnly && (
<div className="mt-6 flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center sm:gap-4">
<p className="flex flex-col text-sm font-medium text-gray-700 dark:text-gray-300">
<span className="font-bold">
{t('modals.prompts.variablesLabel')}
</span>
<span className="text-muted-foreground text-xs font-medium">
{t('modals.prompts.variablesDescription')}
</span>
</p>
<div className="flex flex-wrap items-center gap-2 sm:gap-3">
<VariableMenu
options={systemVariableOptions}
label={t('modals.prompts.systemVariablesDropdownLabel')}
textareaId="edit-prompt-content"
content={editPromptContent}
setContent={setEditPromptContent}
triggerClassName="w-[140px] sm:w-[185px]"
/>
<div className="flex flex-wrap items-center gap-2 sm:gap-3">
<VariableMenu
options={systemVariableOptions}
label={t('modals.prompts.systemVariablesDropdownLabel')}
textareaId="edit-prompt-content"
content={editPromptContent}
setContent={setEditPromptContent}
triggerClassName="w-[140px] sm:w-[185px]"
/>
<VariableMenu
options={toolVariables}
label="Tool Variables"
textareaId="edit-prompt-content"
content={editPromptContent}
setContent={setEditPromptContent}
triggerClassName="w-[140px] sm:w-[171px]"
/>
<VariableMenu
options={toolVariables}
label="Tool Variables"
textareaId="edit-prompt-content"
content={editPromptContent}
setContent={setEditPromptContent}
triggerClassName="w-[140px] sm:w-[171px]"
/>
</div>
</div>
</div>
)}
<div className="mt-4 flex flex-col justify-between gap-4 text-sm sm:flex-row sm:gap-0">
<div className="flex justify-start">
<Link
@@ -546,26 +572,37 @@ function EditPrompt({
{t('modals.prompts.cancel')}
</Button>
<Button
type="button"
onClick={() => {
handleEditPrompt &&
handleEditPrompt(currentPromptEdit.id, currentPromptEdit.type);
}}
className="h-auto rounded-3xl px-6 py-2 text-sm font-medium text-white"
disabled={
currentPromptEdit.type === 'public' ||
disableSave ||
!editPromptName
}
title={
disableSave && editPromptName
? t('modals.prompts.nameExists')
: ''
}
>
{t('modals.prompts.save')}
</Button>
{isReadOnly ? (
onDuplicate && (
<Button
type="button"
onClick={onDuplicate}
className="h-auto rounded-3xl px-6 py-2 text-sm font-medium text-white"
>
{t('modals.prompts.duplicate')}
</Button>
)
) : (
<Button
type="button"
onClick={() => {
handleEditPrompt &&
handleEditPrompt(
currentPromptEdit.id,
currentPromptEdit.type,
);
}}
className="h-auto rounded-3xl px-6 py-2 text-sm font-medium text-white"
disabled={disableSave || !editPromptName}
title={
disableSave && editPromptName
? t('modals.prompts.nameExists')
: ''
}
>
{t('modals.prompts.save')}
</Button>
)}
</div>
</div>
</div>
@@ -588,6 +625,8 @@ export default function PromptsModal({
currentPromptEdit,
handleAddPrompt,
handleEditPrompt,
onDuplicate,
duplicateSourceName,
}: {
existingPrompts: { name: string; id: string; type: string }[];
modalState: ActiveState;
@@ -609,53 +648,30 @@ export default function PromptsModal({
};
handleAddPrompt?: () => void;
handleEditPrompt?: (id: string, type: string) => void;
onDuplicate?: () => void;
duplicateSourceName?: string | null;
}) {
const [disableSave, setDisableSave] = React.useState(true);
const handlePromptNameChange = (edit: boolean, newName: string) => {
if (edit) {
const nameExists = existingPrompts.find(
const disableSave = React.useMemo(() => {
if (type === 'EDIT') {
const nameExists = existingPrompts.some(
(prompt) =>
newName === prompt.name && prompt.id !== currentPromptEdit.id,
prompt.name === editPromptName && prompt.id !== currentPromptEdit.id,
);
setDisableSave(
!(
newName &&
!nameExists &&
editPromptName &&
editPromptContent.trim() !== ''
),
);
setEditPromptName(newName);
} else {
const nameExists = existingPrompts.find(
(prompt) => newName === prompt.name,
);
setDisableSave(
!(newName && !nameExists && newPromptContent.trim() !== ''),
);
setNewPromptName(newName);
return !editPromptName || nameExists || editPromptContent.trim() === '';
}
};
const handleContentChange = (edit: boolean, newContent: string) => {
if (edit) {
const nameValid =
editPromptName &&
!existingPrompts.find(
(prompt) =>
editPromptName === prompt.name &&
prompt.id !== currentPromptEdit.id,
);
setDisableSave(!(nameValid && newContent.trim() !== ''));
setEditPromptContent(newContent);
} else {
const nameValid =
newPromptName &&
!existingPrompts.find((prompt) => newPromptName === prompt.name);
setDisableSave(!(nameValid && newContent.trim() !== ''));
setNewPromptContent(newContent);
}
};
const nameExists = existingPrompts.some(
(prompt) => prompt.name === newPromptName,
);
return !newPromptName || nameExists || newPromptContent.trim() === '';
}, [
type,
existingPrompts,
editPromptName,
editPromptContent,
currentPromptEdit.id,
newPromptName,
newPromptContent,
]);
let view;
@@ -665,10 +681,11 @@ export default function PromptsModal({
setModalState={setModalState}
handleAddPrompt={handleAddPrompt}
newPromptName={newPromptName}
setNewPromptName={handlePromptNameChange.bind(null, false)}
setNewPromptName={setNewPromptName}
newPromptContent={newPromptContent}
setNewPromptContent={handleContentChange.bind(null, false)}
setNewPromptContent={setNewPromptContent}
disableSave={disableSave}
duplicateSourceName={duplicateSourceName}
/>
);
} else if (type === 'EDIT') {
@@ -677,11 +694,12 @@ export default function PromptsModal({
setModalState={setModalState}
handleEditPrompt={handleEditPrompt}
editPromptName={editPromptName}
setEditPromptName={handlePromptNameChange.bind(null, true)}
setEditPromptName={setEditPromptName}
editPromptContent={editPromptContent}
setEditPromptContent={handleContentChange.bind(null, true)}
setEditPromptContent={setEditPromptContent}
currentPromptEdit={currentPromptEdit}
disableSave={disableSave}
onDuplicate={onDuplicate}
/>
);
} else {
@@ -701,7 +719,15 @@ export default function PromptsModal({
}
}}
hideTitle
title={type === 'ADD' ? 'Add Prompt' : 'Edit Prompt'}
title={
type === 'ADD'
? duplicateSourceName
? 'Duplicate Prompt'
: 'Add Prompt'
: currentPromptEdit.type === 'public'
? 'View Prompt'
: 'Edit Prompt'
}
size="lg"
mobileVariant="sheet"
className="bg-card dark:bg-card w-[95vw] max-w-[650px] rounded-2xl px-4 py-4 sm:px-6 sm:py-6 md:max-w-[860px] md:px-8 md:py-6 lg:max-w-[980px]"
+150 -53
View File
@@ -1,4 +1,4 @@
import { ChevronDown, Pencil, Trash2 } from 'lucide-react';
import { ChevronDown, Copy, Eye, Pencil, Trash2 } from 'lucide-react';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
@@ -14,6 +14,7 @@ import {
import { Button } from '../components/ui/button';
import {
Popover,
PopoverAnchor,
PopoverContent,
PopoverTrigger,
} from '../components/ui/popover';
@@ -57,6 +58,9 @@ export default function Prompts({
type: '',
});
const [modalType, setModalType] = React.useState<'ADD' | 'EDIT'>('ADD');
const [duplicateSource, setDuplicateSource] = React.useState<string | null>(
null,
);
const [modalState, setModalState] = React.useState<ActiveState>('INACTIVE');
const [open, setOpen] = React.useState(false);
@@ -95,7 +99,7 @@ export default function Prompts({
]);
}
setModalState('INACTIVE');
onSelectPrompt(newPromptName, newPrompt.id, newPromptContent);
onSelectPrompt(newPromptName, newPrompt.id, 'private');
setNewPromptName('');
setNewPromptContent('');
} catch (error) {
@@ -155,6 +159,62 @@ export default function Prompts({
}
};
const openEditModal = (prompt: {
id: string;
name: string;
type: string;
}) => {
setModalType('EDIT');
setEditPromptName(prompt.name);
setEditPromptContent('');
handleFetchPromptContent(prompt.id);
setCurrentPromptEdit({
id: prompt.id,
name: prompt.name,
type: prompt.type,
});
setModalState('ACTIVE');
setOpen(false);
};
const generateCopyName = (baseName: string) => {
let candidate = `${baseName} copy`;
let counter = 2;
while (prompts.some((prompt) => prompt.name === candidate)) {
candidate = `${baseName} copy ${counter}`;
counter += 1;
}
return candidate;
};
const handleDuplicatePrompt = async (prompt: {
id: string;
name: string;
}) => {
try {
const response = await userService.getSinglePrompt(prompt.id, token);
if (!response.ok) {
throw new Error('Failed to fetch prompt content');
}
const promptContent = await response.json();
setModalType('ADD');
setDuplicateSource(prompt.name);
setNewPromptName(generateCopyName(prompt.name));
setNewPromptContent(promptContent.content);
setModalState('ACTIVE');
setOpen(false);
} catch (error) {
console.error(error);
}
};
const handleDuplicateFromModal = () => {
setDuplicateSource(currentPromptEdit.name);
setNewPromptName(generateCopyName(currentPromptEdit.name));
setNewPromptContent(editPromptContent);
setModalType('ADD');
};
const handleSaveChanges = (id: string, type: string) => {
userService
.updatePrompt(
@@ -196,8 +256,8 @@ export default function Prompts({
});
};
const triggerClassName = cn(
'border-border bg-card text-foreground hover:bg-accent flex w-56 items-center justify-between rounded-3xl border px-5 py-3 text-sm',
const pillClassName = cn(
'border-border bg-card text-foreground hover:bg-accent flex w-56 items-stretch rounded-3xl border text-sm transition-colors',
dropdownProps.className,
);
@@ -210,28 +270,54 @@ export default function Prompts({
</p>
<div className="flex flex-row flex-wrap items-end justify-start gap-6">
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
type="button"
variant="outline"
className={cn('h-auto justify-between', triggerClassName)}
>
<span
className={cn(
'truncate',
!selectedPrompt?.name && 'text-muted-foreground',
)}
<PopoverAnchor asChild>
<div className={pillClassName}>
<PopoverTrigger asChild>
<button
type="button"
className="focus-visible:ring-ring/50 flex min-w-0 flex-1 items-center rounded-l-3xl py-3 pl-5 text-left outline-none focus-visible:ring-[3px]"
>
<span
className={cn(
'truncate',
!selectedPrompt?.name && 'text-muted-foreground',
)}
>
{selectedPrompt?.name || 'Select a prompt'}
</span>
</button>
</PopoverTrigger>
{selectedPrompt?.id && selectedPrompt.type !== 'public' && (
<>
<button
type="button"
onClick={() => openEditModal(selectedPrompt)}
className="text-muted-foreground hover:bg-foreground/15 hover:text-foreground dark:hover:bg-foreground/20 focus-visible:ring-ring/50 mx-1 my-auto shrink-0 rounded-full p-1.5 transition-colors outline-none focus-visible:ring-[3px]"
aria-label="Edit prompt"
>
<Pencil className="h-4 w-4" />
</button>
<div
className="bg-border my-2.5 w-px shrink-0"
aria-hidden="true"
/>
</>
)}
<button
type="button"
onClick={() => setOpen(!open)}
className="text-muted-foreground hover:bg-foreground/15 hover:text-foreground dark:hover:bg-foreground/20 focus-visible:ring-ring/50 my-auto mr-2.5 ml-1 shrink-0 rounded-full p-1.5 transition-colors outline-none focus-visible:ring-[3px]"
aria-label="Toggle prompt list"
>
{selectedPrompt?.name || 'Select a prompt'}
</span>
<ChevronDown
className={cn(
'text-muted-foreground ml-2 h-4 w-4 shrink-0 transition-transform',
open && 'rotate-180',
)}
/>
</Button>
</PopoverTrigger>
<ChevronDown
className={cn(
'h-4 w-4 transition-transform',
open && 'rotate-180',
)}
/>
</button>
</div>
</PopoverAnchor>
<PopoverContent
align="start"
className={cn(
@@ -245,7 +331,7 @@ export default function Prompts({
<CommandEmpty>No results found</CommandEmpty>
{prompts.map((prompt) => {
const isActive = selectedPrompt?.id === prompt.id;
const canDelete = prompt.type !== 'public';
const canModify = prompt.type !== 'public';
return (
<CommandItem
key={prompt.id}
@@ -258,31 +344,39 @@ export default function Prompts({
>
<span className="truncate">{prompt.name}</span>
<div className="flex shrink-0 items-center gap-1">
{prompt.type !== 'public' && (
<Button
type="button"
variant="ghost"
size="icon-sm"
onClick={(e) => {
e.stopPropagation();
setModalType('EDIT');
setEditPromptName(prompt.name);
handleFetchPromptContent(prompt.id);
setCurrentPromptEdit({
id: prompt.id,
name: prompt.name,
type: prompt.type,
});
setModalState('ACTIVE');
setOpen(false);
}}
className="h-auto w-auto rounded p-1"
aria-label="Edit prompt"
>
<Pencil className="text-muted-foreground h-3.5 w-3.5" />
</Button>
)}
{canDelete && (
<Button
type="button"
variant="ghost"
size="icon-sm"
onClick={(e) => {
e.stopPropagation();
openEditModal(prompt);
}}
className="group/btn hover:bg-foreground/15 dark:hover:bg-foreground/20 h-auto w-auto rounded p-1"
aria-label={
canModify ? 'Edit prompt' : 'View prompt'
}
>
{canModify ? (
<Pencil className="text-muted-foreground group-hover/btn:text-foreground h-3.5 w-3.5" />
) : (
<Eye className="text-muted-foreground group-hover/btn:text-foreground h-3.5 w-3.5" />
)}
</Button>
<Button
type="button"
variant="ghost"
size="icon-sm"
onClick={(e) => {
e.stopPropagation();
handleDuplicatePrompt(prompt);
}}
className="group/btn hover:bg-foreground/15 dark:hover:bg-foreground/20 h-auto w-auto rounded p-1"
aria-label="Duplicate prompt"
>
<Copy className="text-muted-foreground group-hover/btn:text-foreground h-3.5 w-3.5" />
</Button>
{canModify && (
<Button
type="button"
variant="ghost"
@@ -291,10 +385,10 @@ export default function Prompts({
e.stopPropagation();
handleDeletePrompt(prompt.id);
}}
className="h-auto w-auto rounded p-1"
className="group/btn hover:bg-destructive/15 dark:hover:bg-destructive/25 h-auto w-auto rounded p-1"
aria-label="Delete prompt"
>
<Trash2 className="text-muted-foreground h-3.5 w-3.5" />
<Trash2 className="text-muted-foreground group-hover/btn:text-destructive h-3.5 w-3.5" />
</Button>
)}
</div>
@@ -311,6 +405,7 @@ export default function Prompts({
className="h-auto w-20 rounded-3xl border border-transparent py-3"
onClick={() => {
setModalType('ADD');
setDuplicateSource(null);
setModalState('ACTIVE');
}}
>
@@ -336,6 +431,8 @@ export default function Prompts({
currentPromptEdit={currentPromptEdit}
handleAddPrompt={handleAddPrompt}
handleEditPrompt={handleSaveChanges}
onDuplicate={handleDuplicateFromModal}
duplicateSourceName={duplicateSource}
/>
{promptToDelete && (
<ConfirmationModal