mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(site): make TaskPrompt PromptTextarea read-only when submitting (#20363)
- Makes the text area of TaskPrompt read-only when submitting - Adds a "scanning" animation to the textarea on submit.
This commit is contained in:
@@ -103,6 +103,35 @@ export const SubmitDisabledWhenPromptEmpty: Story = {
|
||||
},
|
||||
};
|
||||
|
||||
export const Submitting: Story = {
|
||||
decorators: [withGlobalSnackbar],
|
||||
beforeEach: () => {
|
||||
spyOn(API.experimental, "createTask").mockImplementation(
|
||||
() =>
|
||||
// Never resolve to keep the component in the submitting state for visual testing.
|
||||
new Promise(() => {}),
|
||||
);
|
||||
},
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
const prompt = await canvas.findByLabelText(/prompt/i);
|
||||
await userEvent.type(
|
||||
prompt,
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.{enter}{enter}Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
|
||||
);
|
||||
|
||||
const submitButton = canvas.getByRole("button", { name: /run task/i });
|
||||
await waitFor(() => expect(submitButton).toBeEnabled());
|
||||
await userEvent.click(submitButton);
|
||||
},
|
||||
parameters: {
|
||||
chromatic: {
|
||||
disableSnapshot: true,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const OnSuccess: Story = {
|
||||
decorators: [withGlobalSnackbar],
|
||||
parameters: {
|
||||
|
||||
@@ -259,6 +259,7 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
|
||||
value={prompt}
|
||||
onChange={(e) => setPrompt(e.target.value)}
|
||||
readOnly={isPromptReadOnly}
|
||||
isSubmitting={createTaskMutation.isPending}
|
||||
/>
|
||||
<div className="flex items-center justify-between pt-2">
|
||||
<div className="flex items-center gap-1">
|
||||
@@ -457,17 +458,35 @@ async function createTaskWithLatestTemplateVersion(
|
||||
});
|
||||
}
|
||||
|
||||
const PromptTextarea: FC<TextareaAutosizeProps> = (props) => {
|
||||
type PromptTextareaProps = TextareaAutosizeProps & {
|
||||
isSubmitting?: boolean;
|
||||
};
|
||||
|
||||
const PromptTextarea: FC<PromptTextareaProps> = ({
|
||||
isSubmitting,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<TextareaAutosize
|
||||
{...props}
|
||||
required
|
||||
id="prompt"
|
||||
name="prompt"
|
||||
placeholder="Prompt your AI agent to start a task..."
|
||||
className={`border-0 px-3 py-2 resize-none w-full h-full bg-transparent rounded-lg
|
||||
outline-none flex min-h-24 text-sm shadow-sm text-content-primary
|
||||
placeholder:text-content-secondary md:text-sm ${props.readOnly ? "opacity-60 cursor-not-allowed" : ""}`}
|
||||
/>
|
||||
<div className="relative">
|
||||
<TextareaAutosize
|
||||
{...props}
|
||||
required
|
||||
id="prompt"
|
||||
name="prompt"
|
||||
placeholder="Prompt your AI agent to start a task..."
|
||||
className={`border-0 px-3 py-2 resize-none w-full h-full bg-transparent rounded-lg
|
||||
outline-none flex min-h-24 text-sm shadow-sm text-content-primary
|
||||
placeholder:text-content-secondary md:text-sm ${props.readOnly || isSubmitting ? "opacity-60 cursor-not-allowed" : ""}`}
|
||||
/>
|
||||
{isSubmitting && (
|
||||
<div className="absolute inset-0 pointer-events-none overflow-hidden">
|
||||
<div
|
||||
className={`absolute top-0 w-0.5 h-full
|
||||
bg-green-400/90 animate-caret-scan rounded-sm
|
||||
shadow-[-15px_0_15px_rgba(0,255,0,0.9),-30px_0_30px_rgba(0,255,0,0.7),-45px_0_45px_rgba(0,255,0,0.5),-60px_0_60px_rgba(0,255,0,0.3)]`}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -83,6 +83,14 @@ module.exports = {
|
||||
"75%": { opacity: 0.3 },
|
||||
"100%": { opacity: 0.2 },
|
||||
},
|
||||
"caret-scan": {
|
||||
"0%": { left: "0%" },
|
||||
"100%": { left: "100%" },
|
||||
},
|
||||
},
|
||||
animation: {
|
||||
loading: "loading 2s ease-in-out infinite alternate",
|
||||
"caret-scan": "caret-scan 3s ease-in-out infinite",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user