clean up recipe form fields display, formatting and messaging

This commit is contained in:
Zane Staggs
2025-09-21 13:05:42 -07:00
parent 3365a36b4e
commit 4bd54e241f
4 changed files with 54 additions and 62 deletions
@@ -59,14 +59,14 @@ export default function RecipeActivityEditor({
<label htmlFor="activities" className="block text-md text-textProminent mb-2 font-bold">
Activities
</label>
<p className="text-textSubtle space-y-2 pb-4">
The top-line prompts and activities that will display within your goose home page.
<p className="text-sm text-textSubtle space-y-2 pb-4">
The top-line prompts and activity buttons that will display in the recipe chat window.
</p>
{/* Message Field */}
<div className="mb-6">
<div>
<label htmlFor="message" className="block text-sm font-medium text-textStandard mb-2">
Message (Optional)
Message
</label>
<p className="text-xs text-textSubtle mb-2">
A formatted message that will appear at the top of the recipe. Supports markdown
@@ -78,7 +78,7 @@ export default function RecipeActivityEditor({
onChange={(e) => handleMessageChange(e.target.value)}
onBlur={onBlur}
className="w-full px-4 py-3 border rounded-lg bg-background-default text-textStandard placeholder-textPlaceholder focus:outline-none focus:ring-2 focus:ring-borderProminent resize-vertical"
placeholder="Enter a message for your recipe (supports **bold**, *italic*, `code`, etc.)"
placeholder="Enter a user facing introduction message for your recipe (supports **bold**, *italic*, `code`, etc.)"
rows={3}
autoCorrect="off"
autoCapitalize="off"
@@ -93,30 +93,33 @@ export default function RecipeActivityEditor({
Activity Buttons
</label>
<p className="text-xs text-textSubtle mb-3">
Clickable buttons that will appear below the message.
Clickable buttons that will appear below the message to help users interact with your
recipe.
</p>
</div>
<div className="flex flex-wrap gap-3">
{nonMessageActivities.map((activity, index) => (
<div
key={index}
className="inline-flex items-center bg-background-default border-2 border-borderSubtle rounded-full px-4 py-2 text-sm text-textStandard"
title={activity.length > 100 ? activity : undefined}
>
<span>{activity.length > 100 ? activity.slice(0, 100) + '...' : activity}</span>
<Button
type="button"
onClick={() => handleRemoveActivity(activity)}
variant="ghost"
size="sm"
className="ml-2 text-textStandard hover:text-textSubtle transition-colors p-0 h-auto"
{nonMessageActivities.length > 0 && (
<div className="flex flex-wrap gap-3">
{nonMessageActivities.map((activity, index) => (
<div
key={index}
className="inline-flex items-center bg-background-default border-2 border-borderSubtle rounded-full px-4 py-2 text-sm text-textStandard"
title={activity.length > 100 ? activity : undefined}
>
×
</Button>
</div>
))}
</div>
<span>{activity.length > 100 ? activity.slice(0, 100) + '...' : activity}</span>
<Button
type="button"
onClick={() => handleRemoveActivity(activity)}
variant="ghost"
size="sm"
className="ml-2 text-textStandard hover:text-textSubtle transition-colors p-0 h-auto"
>
×
</Button>
</div>
))}
</div>
)}
<div className="flex gap-2 mt-3">
<input
type="text"
@@ -90,9 +90,7 @@ Use {{parameter_name}} syntax for any user-provided values.`;
<div className="flex-1 flex flex-col min-h-0">
<div className="mb-4">
<div className="flex items-center justify-between mb-2">
<label className="block text-sm font-medium text-text-standard">
Instructions <span className="text-red-500">*</span>
</label>
<label className="block text-sm font-medium text-text-standard">Instructions</label>
<Button
type="button"
onClick={insertExample}
@@ -116,7 +114,7 @@ Use {{parameter_name}} syntax for any user-provided values.`;
className={`w-full h-full min-h-[500px] p-3 border rounded-lg bg-background-default text-text-standard focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none font-mono text-sm ${
error ? 'border-red-500' : 'border-border-subtle'
}`}
placeholder="Detailed instructions for the AI agent..."
placeholder="Detailed instructions for the AI, hidden from the user..."
/>
{error && <p className="text-red-500 text-sm mt-2">{error}</p>}
</div>
@@ -111,7 +111,7 @@ export default function JsonSchemaEditor({
<div className="mb-4">
<div className="flex items-center justify-between mb-2">
<label className="block text-sm font-medium text-text-standard">
Response JSON Schema (Optional)
Response JSON Schema
</label>
<Button
type="button"
@@ -240,7 +240,7 @@ export default function RecipeFormFields({
className={`w-full p-3 border rounded-lg bg-background-default text-text-standard focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none font-mono text-sm ${
field.state.meta.errors.length > 0 ? 'border-red-500' : 'border-border-subtle'
}`}
placeholder="Detailed instructions for the AI agent..."
placeholder="Detailed instructions for the AI, hidden from the user..."
rows={8}
/>
<p className="text-xs text-text-muted mt-1">
@@ -288,7 +288,7 @@ export default function RecipeFormFields({
updateParametersFromFields();
}}
className="w-full p-3 border border-border-subtle rounded-lg bg-background-default text-text-standard focus:outline-none focus:ring-2 focus:ring-blue-500 resize-none"
placeholder="First message to send when the recipe starts..."
placeholder="Pre-filled prompt when the recipe starts..."
rows={3}
/>
</div>
@@ -358,7 +358,11 @@ export default function RecipeFormFields({
return (
<div>
<h3 className="text-sm font-medium text-text-standard mb-2">Parameters</h3>
<label className="block text-md text-textProminent mb-2 font-bold">Parameters</label>
<p className="text-textSubtle text-sm space-y-2 pb-4">
Parameters will be automatically detected from {`{{parameter_name}}`} syntax in
instructions/prompt/activities or you can manually add them below.
</p>
{/* Add Parameter Input - Always Visible */}
<div className="flex gap-2 mb-4">
@@ -380,7 +384,7 @@ export default function RecipeFormFields({
</button>
</div>
{field.state.value.length > 0 ? (
{field.state.value.length > 0 &&
field.state.value
.filter((parameter: Parameter) => parameter.key && parameter.key.trim()) // Filter out empty parameters
.map((parameter: Parameter) => {
@@ -408,16 +412,7 @@ export default function RecipeFormFields({
}}
/>
);
})
) : (
<div className="border border-border-subtle rounded-lg p-4 bg-background-muted">
<p className="text-sm text-text-muted text-left">
No parameters defined. Parameters will be automatically detected from{' '}
{`{{parameter_name}}`} syntax in instructions/prompt, or you can manually add
them using the input above.
</p>
</div>
)}
})}
</div>
);
}}
@@ -427,10 +422,13 @@ export default function RecipeFormFields({
<form.Field name="jsonSchema">
{(field: FormFieldApi<string | undefined>) => (
<div>
<label className="block text-md text-textProminent mb-2 font-bold">
Response JSON Schema
</label>
<p className="text-textSubtle text-sm space-y-2 pb-4">
Define the expected structure of the AI's response using JSON Schema format
</p>
<div className="flex items-center justify-between mb-2">
<label className="block text-sm font-medium text-text-standard">
Response JSON Schema (Optional)
</label>
<Button
type="button"
onClick={() => setShowJsonSchemaEditor(true)}
@@ -442,25 +440,18 @@ export default function RecipeFormFields({
</Button>
</div>
<div
className={`border rounded-lg p-3 bg-background-muted ${
field.state.meta.errors.length > 0 ? 'border-red-500' : 'border-border-subtle'
}`}
>
{field.state.value && field.state.value.trim() ? (
{field.state.value && field.state.value.trim() && (
<div
className={`border rounded-lg p-3 bg-background-muted ${
field.state.meta.errors.length > 0 ? 'border-red-500' : 'border-border-subtle'
}`}
>
<pre className="text-xs font-mono text-text-standard whitespace-pre-wrap break-words max-h-32 overflow-y-auto">
{field.state.value}
</pre>
) : (
<p className="text-xs text-text-muted italic">
No JSON schema defined. Click "Open Editor" to add one.
</p>
)}
</div>
</div>
)}
<p className="text-xs text-text-muted mt-1">
Define the expected structure of the AI's response using JSON Schema format
</p>
{field.state.meta.errors.length > 0 && (
<p className="text-red-500 text-sm mt-1">{field.state.meta.errors[0]}</p>
)}