Skip to content

Commit 0ee8181

Browse files
committed
Refactor prompt field placeholder rendering and relocate context empty warning to main view
- the placeholder text doesn't wrap around close button, tabs the same way as the actual value - 'context is empty' should not be integrated with 'attaching...' but shown as a separate status bar above the prompt field - placeholder should be placed in a mirrored container so that it doesn't interfere with the cursor placement ├── apps │ └── editor │ └── src │ └── views │ └── prompt │ └── frontend │ └── Main │ └── MainView │ ├── MainView.tsx │ └── components │ ├── BrowserConnectionStatus │ │ └── BrowserConnectionStatus.tsx │ └── PromptAttachments │ └── PromptAttachments.tsx └── packages └── ui └── src └── components └── editor └── common └── prompts └── PromptField ├── PromptField.module.scss └── PromptField.tsx
1 parent 257a86a commit 0ee8181

4 files changed

Lines changed: 76 additions & 49 deletions

File tree

‎apps/editor/src/views/prompt/frontend/Main/MainView/MainView.tsx‎

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { PromptAttachments } from './components/PromptAttachments'
55
import { Separator as UiSeparator } from '@ui/components/editor/prompt/Separator'
66
import { WebConfiguration } from '@shared/types/web-configuration'
77
import { Responses as UiResponses } from '@ui/components/editor/prompt/Responses'
8+
import { StatusBar as UiStatusBar } from '@ui/components/editor/prompt/StatusBar'
89
import { ResponseHistoryItem } from '@shared/types/response-history-item'
910
import { EditFormat } from '@shared/types/edit-format'
1011
import { TARGET, Target } from '@shared/types/mode'
@@ -260,6 +261,17 @@ export const MainView: React.FC<Props> = (props) => {
260261
}}
261262
/>
262263

264+
{context_is_empty_warning && (
265+
<>
266+
<UiStatusBar
267+
theme="warning"
268+
icon="codicon-warning"
269+
label={t('common.context-is-empty')}
270+
/>
271+
<UiSeparator height={4} />
272+
</>
273+
)}
274+
263275
<UiSeparator height={2} />
264276

265277
{props.response_history.length > 0 && (
@@ -342,8 +354,8 @@ export const MainView: React.FC<Props> = (props) => {
342354
? 'blue'
343355
: 'purple'
344356
: props.api_prompt_type == 'edit-files'
345-
? 'blue'
346-
: 'purple'
357+
? 'blue'
358+
: 'purple'
347359
}
348360
on_paste_image={props.on_paste_image}
349361
on_open_image={props.on_open_image}
@@ -403,13 +415,10 @@ export const MainView: React.FC<Props> = (props) => {
403415
? 'blue'
404416
: 'purple'
405417
: props.api_prompt_type == 'edit-files'
406-
? 'blue'
407-
: 'purple'
418+
? 'blue'
419+
: 'purple'
408420
}
409421
translations={{
410-
warning: context_is_empty_warning
411-
? t('common.context-is-empty')
412-
: undefined,
413422
attaching_file: t('selected-files.attaching-file'),
414423
attaching_files: t('selected-files.attaching-files')
415424
}}

‎apps/editor/src/views/prompt/frontend/Main/MainView/components/PromptAttachments/PromptAttachments.tsx‎

Lines changed: 13 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,31 @@ type Props = {
77
files_count?: number
88
theme?: 'default' | 'warning' | 'success' | 'error' | 'blue' | 'purple'
99
translations: {
10-
warning?: string
1110
attaching_file: string
1211
attaching_files: string
1312
}
1413
}
1514

1615
export const PromptAttachments: React.FC<Props> = (props) => {
17-
if (!props.translations.warning && props.files_count === undefined) {
18-
return null
19-
}
16+
2017

2118
const attaching_files_label = (
2219
props.files_count == 1
2320
? props.translations.attaching_file
2421
: props.translations.attaching_files
25-
).replace('{count}', String(props.files_count))
22+
).replace('{count}', String(props.files_count || 0))
2623

2724
return (
28-
<>
29-
{props.translations.warning && (
30-
<StatusBar
31-
placement="bottom"
32-
theme="warning"
33-
icon="codicon-warning"
34-
label={props.translations.warning}
35-
/>
36-
)}
37-
{props.files_count !== undefined && (
38-
<StatusBar
39-
placement="bottom"
40-
theme={props.theme ?? 'default'}
41-
icon="codicon-attach"
42-
label={attaching_files_label}
43-
description={
44-
(props.token_count ?? 0) > 0
45-
? display_token_count(props.token_count ?? 0)
46-
: undefined
47-
}
48-
/>
49-
)}
50-
</>
25+
<StatusBar
26+
placement="bottom"
27+
theme={props.theme ?? 'default'}
28+
icon="codicon-attach"
29+
label={attaching_files_label}
30+
description={
31+
(props.token_count ?? 0) > 0
32+
? display_token_count(props.token_count ?? 0)
33+
: undefined
34+
}
35+
/>
5136
)
5237
}

‎packages/ui/src/components/editor/common/prompts/PromptField/PromptField.module.scss‎

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,16 @@
4343
position: relative;
4444
}
4545

46+
.placeholder-mirror {
47+
position: absolute;
48+
width: 100%;
49+
}
50+
51+
.placeholder-text {
52+
padding: var(--padding);
53+
color: var(--vscode-input-placeholderForeground);
54+
}
55+
4656
.top-right {
4757
float: right;
4858
display: flex;
@@ -102,19 +112,6 @@
102112
outline: none;
103113
}
104114

105-
&--empty::before {
106-
content: attr(data-placeholder);
107-
position: absolute;
108-
color: var(--vscode-input-placeholderForeground);
109-
pointer-events: none;
110-
padding-right: 7px;
111-
}
112-
113-
&--empty::selection,
114-
&--empty *::selection {
115-
background-color: transparent;
116-
}
117-
118115
& [data-type='ghost-text']::before {
119116
content: '\200B';
120117
}

‎packages/ui/src/components/editor/common/prompts/PromptField/PromptField.tsx‎

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,43 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
873873
onClick={() => input_ref.current?.focus()}
874874
>
875875
<div className={styles['input-wrapper']}>
876+
{!props.value && (
877+
<div className={styles['placeholder-mirror']}>
878+
<div className={styles['top-right']} style={{ visibility: 'hidden' }}>
879+
{has_content && props.prompt_token_count > 250 && (
880+
<div className={styles['top-right__prompt-token-count']}>
881+
{display_token_count(props.prompt_token_count)}
882+
</div>
883+
)}
884+
{props.tabs_count > 1 && (
885+
<div
886+
className={cn(
887+
styles['top-right__clear-button'],
888+
'codicon',
889+
'codicon-close-small'
890+
)}
891+
/>
892+
)}
893+
</div>
894+
{props.tabs_count > 1 ? (
895+
<div className={styles.tabs} style={{ visibility: 'hidden' }}>
896+
{tab_items.map((item) => (
897+
<div key={item.id} className={styles.tabs__tab} />
898+
))}
899+
<div
900+
className={cn(styles.tabs__tab, styles['tabs__tab--new'])}
901+
/>
902+
</div>
903+
) : props.tabs_count === 1 ? (
904+
<div className={styles.tabs} style={{ visibility: 'hidden' }}>
905+
<div
906+
className={cn(styles.tabs__tab, styles['tabs__tab--new'])}
907+
/>
908+
</div>
909+
) : null}
910+
<div className={styles['placeholder-text']}>{placeholder}</div>
911+
</div>
912+
)}
876913
<div className={styles['top-right']}>
877914
{has_content && props.prompt_token_count > 250 && (
878915
<div className={styles['top-right__prompt-token-count']}>
@@ -990,7 +1027,6 @@ export const PromptField: React.FC<PromptFieldProps> = (props) => {
9901027
className={cn(styles.input, {
9911028
[styles['input--empty']]: !props.value
9921029
})}
993-
data-placeholder={placeholder}
9941030
/>
9951031
</div>
9961032

0 commit comments

Comments
 (0)