refine prompt overlay layout
This commit is contained in:
@@ -7,7 +7,6 @@ import { createFileAttachment, createTextAttachment, createAgentAttachment } fro
|
|||||||
import type { Attachment } from "../types/attachment"
|
import type { Attachment } from "../types/attachment"
|
||||||
import type { Agent } from "../types/session"
|
import type { Agent } from "../types/session"
|
||||||
import Kbd from "./kbd"
|
import Kbd from "./kbd"
|
||||||
import HintRow from "./hint-row"
|
|
||||||
import { getActiveInstance } from "../stores/instances"
|
import { getActiveInstance } from "../stores/instances"
|
||||||
import { agents, getSessionDraftPrompt, setSessionDraftPrompt, clearSessionDraftPrompt } from "../stores/sessions"
|
import { agents, getSessionDraftPrompt, setSessionDraftPrompt, clearSessionDraftPrompt } from "../stores/sessions"
|
||||||
import { showAlertDialog } from "../stores/alerts"
|
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 shellHint = () => (mode() === "shell" ? { key: "Esc", text: "to exit shell mode" } : { key: "!", text: "for shell mode" })
|
||||||
|
const shouldShowOverlay = () => prompt().length === 0
|
||||||
|
|
||||||
const instance = () => getActiveInstance()
|
const instance = () => getActiveInstance()
|
||||||
|
|
||||||
@@ -884,28 +884,62 @@ export default function PromptInput(props: PromptInputProps) {
|
|||||||
</For>
|
</For>
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
<textarea
|
<div class="prompt-input-field">
|
||||||
ref={textareaRef}
|
<textarea
|
||||||
class={`prompt-input ${mode() === "shell" ? "shell-mode" : ""}`}
|
ref={textareaRef}
|
||||||
placeholder={
|
class={`prompt-input ${mode() === "shell" ? "shell-mode" : ""}`}
|
||||||
mode() === "shell"
|
placeholder={
|
||||||
? "Run a shell command (Esc to exit)..."
|
mode() === "shell"
|
||||||
: "Type your message, @file, @agent, or paste images and text..."
|
? "Run a shell command (Esc to exit)..."
|
||||||
}
|
: "Type your message, @file, @agent, or paste images and text..."
|
||||||
value={prompt()}
|
}
|
||||||
onInput={handleInput}
|
value={prompt()}
|
||||||
onKeyDown={handleKeyDown}
|
onInput={handleInput}
|
||||||
onPaste={handlePaste}
|
onKeyDown={handleKeyDown}
|
||||||
onFocus={() => setIsFocused(true)}
|
onPaste={handlePaste}
|
||||||
onBlur={() => setIsFocused(false)}
|
onFocus={() => setIsFocused(true)}
|
||||||
disabled={props.disabled}
|
onBlur={() => setIsFocused(false)}
|
||||||
rows={4}
|
disabled={props.disabled}
|
||||||
style={attachments().length > 0 ? { "padding-top": "8px" } : {}}
|
rows={4}
|
||||||
spellcheck={false}
|
style={attachments().length > 0 ? { "padding-top": "8px" } : {}}
|
||||||
autocorrect="off"
|
spellcheck={false}
|
||||||
autoCapitalize="off"
|
autocorrect="off"
|
||||||
autocomplete="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>
|
</div>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
@@ -925,33 +959,6 @@ export default function PromptInput(props: PromptInputProps) {
|
|||||||
</Show>
|
</Show>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,9 +9,13 @@
|
|||||||
@apply flex items-end gap-2 p-3;
|
@apply flex items-end gap-2 p-3;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prompt-input-field {
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.prompt-input {
|
.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;
|
font-family: inherit;
|
||||||
background-color: var(--surface-base);
|
background-color: var(--surface-base);
|
||||||
color: inherit;
|
color: inherit;
|
||||||
@@ -19,6 +23,45 @@
|
|||||||
line-height: var(--line-height-normal);
|
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 {
|
.prompt-input.shell-mode {
|
||||||
border-color: var(--status-success);
|
border-color: var(--status-success);
|
||||||
box-shadow: inset 0 0 0 1px rgba(76, 175, 80, 0.4);
|
box-shadow: inset 0 0 0 1px rgba(76, 175, 80, 0.4);
|
||||||
@@ -80,9 +123,6 @@
|
|||||||
height: 1rem;
|
height: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.prompt-input-hints {
|
|
||||||
@apply px-4 pb-2 flex justify-between items-center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
@apply text-xs;
|
@apply text-xs;
|
||||||
@@ -141,3 +181,26 @@
|
|||||||
.attachment-download:hover {
|
.attachment-download:hover {
|
||||||
background-color: var(--attachment-chip-ring);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user