refine prompt overlay layout

This commit is contained in:
Shantur Rathore
2025-11-24 14:16:25 +00:00
parent b434bfd3e9
commit 01effb8924
2 changed files with 124 additions and 54 deletions

View File

@@ -7,7 +7,6 @@ import { createFileAttachment, createTextAttachment, createAgentAttachment } fro
import type { Attachment } from "../types/attachment"
import type { Agent } from "../types/session"
import Kbd from "./kbd"
import HintRow from "./hint-row"
import { getActiveInstance } from "../stores/instances"
import { agents, getSessionDraftPrompt, setSessionDraftPrompt, clearSessionDraftPrompt } from "../stores/sessions"
import { showAlertDialog } from "../stores/alerts"
@@ -777,6 +776,7 @@ export default function PromptInput(props: PromptInputProps) {
}
const shellHint = () => (mode() === "shell" ? { key: "Esc", text: "to exit shell mode" } : { key: "!", text: "for shell mode" })
const shouldShowOverlay = () => prompt().length === 0
const instance = () => getActiveInstance()
@@ -884,28 +884,62 @@ export default function PromptInput(props: PromptInputProps) {
</For>
</div>
</Show>
<textarea
ref={textareaRef}
class={`prompt-input ${mode() === "shell" ? "shell-mode" : ""}`}
placeholder={
mode() === "shell"
? "Run a shell command (Esc to exit)..."
: "Type your message, @file, @agent, or paste images and text..."
}
value={prompt()}
onInput={handleInput}
onKeyDown={handleKeyDown}
onPaste={handlePaste}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
disabled={props.disabled}
rows={4}
style={attachments().length > 0 ? { "padding-top": "8px" } : {}}
spellcheck={false}
autocorrect="off"
autoCapitalize="off"
autocomplete="off"
/>
<div class="prompt-input-field">
<textarea
ref={textareaRef}
class={`prompt-input ${mode() === "shell" ? "shell-mode" : ""}`}
placeholder={
mode() === "shell"
? "Run a shell command (Esc to exit)..."
: "Type your message, @file, @agent, or paste images and text..."
}
value={prompt()}
onInput={handleInput}
onKeyDown={handleKeyDown}
onPaste={handlePaste}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
disabled={props.disabled}
rows={4}
style={attachments().length > 0 ? { "padding-top": "8px" } : {}}
spellcheck={false}
autocorrect="off"
autoCapitalize="off"
autocomplete="off"
/>
<Show when={shouldShowOverlay()}>
<div class={`prompt-input-overlay ${mode() === "shell" ? "shell-mode" : ""}`}>
<Show
when={props.escapeInDebounce}
fallback={
<>
<span class="prompt-overlay-text">
<Kbd>Enter</Kbd> for new line <Kbd shortcut="cmd+enter" /> to send <Kbd>@</Kbd> for files/agents <Kbd></Kbd> for history
</span>
<Show when={attachments().length > 0}>
<span class="prompt-overlay-text prompt-overlay-muted"> {attachments().length} file(s) attached</span>
</Show>
<span class="prompt-overlay-text">
<Kbd>{shellHint().key}</Kbd> {shellHint().text}
</span>
<Show when={mode() === "shell"}>
<span class="prompt-overlay-shell-active">Shell mode active</span>
</Show>
</>
}
>
<>
<span class="prompt-overlay-text prompt-overlay-warning">
Press <Kbd>Esc</Kbd> again to abort session
</span>
<Show when={mode() === "shell"}>
<span class="prompt-overlay-shell-active">Shell mode active</span>
</Show>
</>
</Show>
</div>
</Show>
</div>
</div>
<button
@@ -925,33 +959,6 @@ export default function PromptInput(props: PromptInputProps) {
</Show>
</button>
</div>
<div class="prompt-input-hints">
<div class="flex justify-between w-full gap-4">
<HintRow>
<Show
when={props.escapeInDebounce}
fallback={
<>
<Kbd>Enter</Kbd> for new line <Kbd shortcut="cmd+enter" /> to send <Kbd>@</Kbd> for files/agents <Kbd></Kbd> for history
<Show when={attachments().length > 0}>
<span class="ml-2 text-xs" style="color: var(--text-muted);"> {attachments().length} file(s) attached</span>
</Show>
<span class="ml-2">
<Kbd>{shellHint().key}</Kbd> {shellHint().text}
</span>
</>
}
>
<span class="font-medium" style="color: var(--status-warning);">
Press <Kbd>Esc</Kbd> again to abort session
</span>
</Show>
</HintRow>
<Show when={mode() === "shell"}>
<HintRow>Shell mode active</HintRow>
</Show>
</div>
</div>
</div>
)
}

View File

@@ -9,9 +9,13 @@
@apply flex items-end gap-2 p-3;
}
.prompt-input-field {
position: relative;
width: 100%;
}
.prompt-input {
@apply flex-1 min-h-[96px] max-h-[200px] p-2.5 border rounded-md text-sm resize-none outline-none transition-colors;
@apply flex-1 w-full min-h-[56px] max-h-[96px] px-3 pt-2.5 pb-12 border rounded-md text-sm resize-none outline-none transition-colors;
font-family: inherit;
background-color: var(--surface-base);
color: inherit;
@@ -19,6 +23,45 @@
line-height: var(--line-height-normal);
}
.prompt-input-overlay {
position: absolute;
bottom: 1rem;
left: 0.75rem;
right: 0.75rem;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
font-size: 0.75rem;
line-height: 1.3;
color: var(--text-muted);
pointer-events: none;
z-index: 1;
}
.prompt-input-overlay.shell-mode {
color: var(--text-primary);
}
.prompt-overlay-text {
display: inline-flex;
align-items: center;
gap: 0.35rem;
}
.prompt-overlay-warning {
color: var(--status-warning);
font-weight: 500;
}
.prompt-overlay-shell-active {
color: var(--status-success);
font-weight: 600;
}
.prompt-overlay-muted {
color: var(--text-muted);
}
.prompt-input.shell-mode {
border-color: var(--status-success);
box-shadow: inset 0 0 0 1px rgba(76, 175, 80, 0.4);
@@ -80,9 +123,6 @@
height: 1rem;
}
.prompt-input-hints {
@apply px-4 pb-2 flex justify-between items-center;
}
.hint {
@apply text-xs;
@@ -141,3 +181,26 @@
.attachment-download:hover {
background-color: var(--attachment-chip-ring);
}
@media (pointer: coarse) {
.prompt-input-overlay {
display: none;
}
.prompt-input {
padding-bottom: 1.5rem;
}
}
@media (max-width: 640px) {
.prompt-input {
min-height: 64px;
padding: 0.5rem 0.75rem;
padding-bottom: 2.25rem;
}
.prompt-input-wrapper {
gap: 0.75rem;
padding: 0.75rem;
}
}