Refactor renamed the component groups to something less obtuse:

Elements -> Groups -> Screens -> Views
This commit is contained in:
cliffhall 2026-03-28 12:58:47 -04:00
commit dd46acba87
2 changed files with 151 additions and 144 deletions

View file

@ -0,0 +1,93 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { fn } from "storybook/test";
import { PromptArgumentsForm } from "./PromptArgumentsForm";
const meta: Meta<typeof PromptArgumentsForm> = {
title: "Groups/PromptArgumentsForm",
component: PromptArgumentsForm,
args: {
onSelectPrompt: fn(),
onArgumentChange: fn(),
onGetPrompt: fn(),
},
};
export default meta;
type Story = StoryObj<typeof PromptArgumentsForm>;
const samplePrompts = [
{
name: "summarize",
description: "Summarize the given text into key points",
},
{
name: "translate",
description: "Translate text from one language to another",
},
{ name: "analyze", description: "Analyze sentiment and tone of the text" },
];
export const NoSelection: Story = {
args: {
prompts: samplePrompts,
selectedPrompt: undefined,
arguments: [],
argumentValues: {},
},
};
export const Selected: Story = {
args: {
prompts: samplePrompts,
selectedPrompt: "translate",
arguments: [
{ name: "text", required: true, description: "The text to translate" },
{
name: "targetLanguage",
required: true,
description: "The language to translate into",
},
],
argumentValues: {},
},
};
export const WithRequiredArgs: Story = {
args: {
prompts: samplePrompts,
selectedPrompt: "summarize",
arguments: [
{ name: "text", required: true, description: "The text to summarize" },
{
name: "maxLength",
required: true,
description: "Maximum length of summary in words",
},
{
name: "format",
required: false,
description: "Output format (bullets or paragraph)",
},
],
argumentValues: {},
},
};
export const AllFilled: Story = {
args: {
prompts: samplePrompts,
selectedPrompt: "translate",
arguments: [
{ name: "text", required: true, description: "The text to translate" },
{
name: "targetLanguage",
required: true,
description: "The language to translate into",
},
],
argumentValues: {
text: "Hello, how are you?",
targetLanguage: "Spanish",
},
},
};

View file

@ -0,0 +1,82 @@
import { Button, Select, Stack, Text, TextInput, Title } from "@mantine/core";
export interface PromptArgument {
name: string;
required: boolean;
description?: string;
}
export interface PromptInfo {
name: string;
description?: string;
}
export interface PromptArgumentsFormProps {
prompts: PromptInfo[];
selectedPrompt?: string;
arguments: PromptArgument[];
argumentValues: Record<string, string>;
onSelectPrompt: (name: string) => void;
onArgumentChange: (name: string, value: string) => void;
onGetPrompt: () => void;
}
const DescriptionText = Text.withProps({
size: "sm",
c: "dimmed",
});
function formatPlaceholder(name: string): string {
return `Enter ${name}...`;
}
export function PromptArgumentsForm({
prompts,
selectedPrompt,
arguments: promptArguments,
argumentValues,
onSelectPrompt,
onArgumentChange,
onGetPrompt,
}: PromptArgumentsFormProps) {
const selectedPromptInfo = prompts.find((p) => p.name === selectedPrompt);
return (
<Stack gap="md">
<Title order={4}>Prompts</Title>
<Select
data={prompts.map((p) => ({ value: p.name, label: p.name }))}
value={selectedPrompt ?? null}
onChange={(value) => {
if (value) {
onSelectPrompt(value);
}
}}
placeholder="Choose a prompt..."
/>
{selectedPrompt && selectedPromptInfo?.description && (
<DescriptionText>{selectedPromptInfo.description}</DescriptionText>
)}
{promptArguments.length > 0 && (
<>
{promptArguments.map((arg) => (
<TextInput
key={arg.name}
label={arg.name}
withAsterisk={arg.required}
description={arg.description}
placeholder={formatPlaceholder(arg.name)}
value={argumentValues[arg.name] || ""}
onChange={(event) =>
onArgumentChange(arg.name, event.currentTarget.value)
}
/>
))}
</>
)}
<Button fullWidth onClick={onGetPrompt} disabled={!selectedPrompt}>
Get Prompt
</Button>
</Stack>
);
}