Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitf009ebd

Browse files
feat: minor prompt redesign (#20045)
When I navigate to tasks, the prompt doesn’t feel prominent enough—eventhough it should be the primary element on the screen. To give it morefocus, I made some small design changes. Here are both versions:**Before:**<img width="1624" height="970" alt="Screenshot 2025-09-30 at 12 10 58"src="https://github.com/user-attachments/assets/b5451ad5-4d32-4716-8e0f-e4596e7c92c8"/>**After:**<img width="1624" height="970" alt="Screenshot 2025-09-30 at 12 10 46"src="https://github.com/user-attachments/assets/f478e327-12c0-4f49-829f-8b094a6b613e"/>
1 parentfe189b9 commitf009ebd

File tree

1 file changed

+73
-71
lines changed

1 file changed

+73
-71
lines changed

‎site/src/pages/TasksPage/TaskPrompt.tsx‎

Lines changed: 73 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
importtype{SelectTriggerProps}from"@radix-ui/react-select";
12
import{API}from"api/api";
23
import{getErrorDetail,getErrorMessage}from"api/errors";
34
import{templateVersionPresets}from"api/queries/templates";
@@ -29,15 +30,16 @@ import {
2930
}from"components/Tooltip/Tooltip";
3031
import{useAuthenticated}from"hooks/useAuthenticated";
3132
import{useExternalAuth}from"hooks/useExternalAuth";
32-
import{RedoIcon,RotateCcwIcon,SendIcon}from"lucide-react";
33+
import{ArrowUpIcon,RedoIcon,RotateCcwIcon}from"lucide-react";
3334
import{AI_PROMPT_PARAMETER_NAME}from"modules/tasks/tasks";
3435
import{typeFC,useEffect,useState}from"react";
3536
import{useMutation,useQuery,useQueryClient}from"react-query";
36-
importTextareaAutosizefrom"react-textarea-autosize";
37+
importTextareaAutosize,{
38+
typeTextareaAutosizeProps,
39+
}from"react-textarea-autosize";
40+
import{cn}from"utils/cn";
3741
import{docs}from"utils/docs";
3842

39-
consttextareaPlaceholder="Prompt your AI agent to start a task...";
40-
4143
typeTaskPromptProps={
4244
templates:Template[]|undefined;
4345
error:unknown;
@@ -92,23 +94,14 @@ const TaskPromptLoadingError: FC<{
9294

9395
constTaskPromptSkeleton:FC=()=>{
9496
return(
95-
<divclassName="border border-border border-solid rounded-lg p-4">
96-
<divclassName="space-y-4">
97-
{/* Textarea skeleton */}
98-
<TextareaAutosize
99-
disabled
100-
id="prompt"
101-
name="prompt"
102-
placeholder={textareaPlaceholder}
103-
className={`border-0 resize-none w-full h-full bg-transparent rounded-lg outline-none flex min-h-[60px]
104-
text-sm shadow-sm text-content-primary placeholder:text-content-secondary md:text-sm`}
105-
/>
97+
<divclassName="border border-border border-solid rounded-3xl p-3 bg-surface-secondary">
98+
{/* Textarea skeleton */}
99+
<PromptTextareadisabled/>
106100

107-
{/* Bottom controls skeleton */}
108-
<divclassName="flex items-center justify-between pt-2">
109-
<SkeletonclassName="w-[208px] h-8"/>
110-
<SkeletonclassName="w-[96px] h-8"/>
111-
</div>
101+
{/* Bottom controls skeleton */}
102+
<divclassName="flex items-center justify-between pt-2">
103+
<SkeletonclassName="w-[208px] h-8 rounded-full"/>
104+
<SkeletonclassName="size-8 rounded-full"/>
112105
</div>
113106
</div>
114107
);
@@ -225,7 +218,7 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
225218
{externalAuthError&&<ErrorAlerterror={externalAuthError}/>}
226219

227220
<fieldset
228-
className="border border-border border-solid rounded-lg p-4"
221+
className="border border-border border-solid rounded-3xl p-3 bg-surface-secondary"
229222
disabled={createTaskMutation.isPending}
230223
>
231224
<label
@@ -238,25 +231,15 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
238231
>
239232
{isPromptReadOnly ?"Prompt defined by preset" :"Prompt"}
240233
</label>
241-
<TextareaAutosize
234+
<PromptTextarea
242235
required
243-
id="prompt"
244-
name="prompt"
245236
value={presetAIPrompt||undefined}
246237
readOnly={isPromptReadOnly}
247-
placeholder={textareaPlaceholder}
248-
className={`border-0 resize-none w-full h-full bg-transparent rounded-lg outline-none flex min-h-[60px]
249-
text-sm shadow-sm text-content-primary placeholder:text-content-secondary md:text-sm${
250-
isPromptReadOnly ?"opacity-60 cursor-not-allowed" :""
251-
}`}
252238
/>
253239
<divclassName="flex items-center justify-between pt-2">
254-
<divclassName="flex items-center gap-4">
240+
<divclassName="flex items-center gap-1">
255241
<divclassName="flex flex-col gap-1">
256-
<label
257-
htmlFor="templateID"
258-
className="text-xs font-medium text-content-primary"
259-
>
242+
<labelhtmlFor="templateID"className="sr-only">
260243
Template
261244
</label>
262245
<Select
@@ -265,12 +248,9 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
265248
defaultValue={templates[0].id}
266249
required
267250
>
268-
<SelectTrigger
269-
id="templateID"
270-
className="w-80 text-xs [&_svg]:size-icon-xs border-0 bg-surface-secondary h-8 px-3"
271-
>
251+
<PromptSelectTriggerid="templateID">
272252
<SelectValueplaceholder="Select a template"/>
273-
</SelectTrigger>
253+
</PromptSelectTrigger>
274254
<SelectContent>
275255
{templates.map((template)=>{
276256
return(
@@ -285,40 +265,26 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
285265
</Select>
286266
</div>
287267

288-
{isLoadingPresets ?(
289-
<divclassName="flex flex-col gap-1">
290-
<label
291-
htmlFor="presetID"
292-
className="text-xs font-medium text-content-primary"
293-
>
294-
Preset
295-
</label>
268+
<divclassName="flex flex-col gap-1">
269+
<labelhtmlFor="presetID"className="sr-only">
270+
Preset
271+
</label>
272+
{isLoadingPresets ?(
296273
<SkeletonclassName="w-[320px] h-8"/>
297-
</div>
298-
) :(
299-
presets&&
300-
presets.length>0&&(
301-
<divclassName="flex flex-col gap-1">
302-
<label
303-
htmlFor="presetID"
304-
className="text-xs font-medium text-content-primary"
305-
>
306-
Preset
307-
</label>
274+
) :(
275+
presets&&
276+
presets.length>0&&(
308277
<Select
309278
key={`preset-select-${selectedTemplate.active_version_id}`}
310279
name="presetID"
311280
value={selectedPresetId||undefined}
312281
onValueChange={setSelectedPresetId}
313282
>
314-
<SelectTrigger
315-
id="presetID"
316-
className="w-80 text-xs [&_svg]:size-icon-xs border-0 bg-surface-secondary h-8 px-3"
317-
>
283+
<PromptSelectTriggerid="presetID">
318284
<SelectValueplaceholder="Select a preset"/>
319-
</SelectTrigger>
285+
</PromptSelectTrigger>
320286
<SelectContent>
321-
{presets.toSorted(sortByDefault).map((preset)=>(
287+
{presets?.toSorted(sortByDefault).map((preset)=>(
322288
<SelectItemvalue={preset.ID}key={preset.ID}>
323289
<spanclassName="overflow-hidden text-ellipsis block">
324290
{preset.Name}{preset.Default&&"(Default)"}
@@ -327,9 +293,9 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
327293
))}
328294
</SelectContent>
329295
</Select>
330-
</div>
331-
)
332-
)}
296+
)
297+
)}
298+
</div>
333299
</div>
334300

335301
<divclassName="flex items-center gap-2">
@@ -340,17 +306,22 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
340306
/>
341307
)}
342308

343-
<Buttonsize="sm"type="submit"disabled={isMissingExternalAuth}>
309+
<Button
310+
size="icon"
311+
type="submit"
312+
disabled={isMissingExternalAuth}
313+
className="rounded-full disabled:bg-surface-invert-primary disabled:opacity-70"
314+
>
344315
<Spinner
345316
loading={
346317
isLoadingExternalAuth||
347318
isPollingExternalAuth||
348319
createTaskMutation.isPending
349320
}
350321
>
351-
<SendIcon/>
322+
<ArrowUpIcon/>
352323
</Spinner>
353-
Run task
324+
<spanclassName="sr-only">Run task</span>
354325
</Button>
355326
</div>
356327
</div>
@@ -359,6 +330,23 @@ const CreateTaskForm: FC<CreateTaskFormProps> = ({ templates, onSuccess }) => {
359330
);
360331
};
361332

333+
constPromptSelectTrigger:FC<SelectTriggerProps>=({
334+
className,
335+
...props
336+
})=>{
337+
return(
338+
<SelectTrigger
339+
{...props}
340+
className={cn([
341+
className,
342+
`border-0 bg-surface-secondary text-sm text-content-primary gap-2 px-3
343+
[&_svg]:text-inherit cursor-pointer hover:bg-surface-quaternary rounded-full
344+
h-8 data-[state=open]:bg-surface-tertiary`,
345+
])}
346+
/>
347+
);
348+
};
349+
362350
typeExternalAuthButtonProps={
363351
template:Template;
364352
missedExternalAuth:TemplateVersionExternalAuth[];
@@ -379,7 +367,7 @@ const ExternalAuthButtons: FC<ExternalAuthButtonProps> = ({
379367
return(
380368
<divclassName="flex items-center gap-2"key={auth.id}>
381369
<Button
382-
variant="outline"
370+
className="bg-surface-tertiary hover:bg-surface-quaternary rounded-full text-white"
383371
size="sm"
384372
disabled={isPollingExternalAuth||auth.authenticated}
385373
onClick={()=>{
@@ -446,3 +434,17 @@ async function createTaskWithLatestTemplateVersion(
446434
template_version_preset_id:presetId,
447435
});
448436
}
437+
438+
constPromptTextarea:FC<TextareaAutosizeProps>=(props)=>{
439+
return(
440+
<TextareaAutosize
441+
required
442+
id="prompt"
443+
name="prompt"
444+
placeholder="Prompt your AI agent to start a task..."
445+
className={`border-0 px-3 py-2 resize-none w-full h-full bg-transparent rounded-lg
446+
outline-none flex min-h-24 text-sm shadow-sm text-content-primary
447+
placeholder:text-content-secondary md:text-sm${props.readOnly ?"opacity-60 cursor-not-allowed" :""}`}
448+
/>
449+
);
450+
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp