dashboard: themedPrompt is a textarea — Enter submits, Shift+Enter newline
The approval deny-reason prompt (and every themedPrompt dialog) used a single-line input. Make themedPrompt always a resizable <textarea> with chat-box keys: Enter submits (clicks the confirm button), Shift+Enter inserts a newline. Short answers stay one keystroke; multi-line reasons (e.g. a deny note) are now possible. No single-line variant — themedPrompt is only used by the data-async data-prompt path, so all those dialogs get the textarea. Closes #1840.
This commit is contained in:
parent
0df52806f9
commit
08afa49c96
2 changed files with 23 additions and 3 deletions
|
|
@ -481,6 +481,14 @@ body.dashboard-shell {
|
|||
padding: 0.4em 0.6em;
|
||||
}
|
||||
.tc-input:focus { outline: 1px solid var(--green); }
|
||||
/* themedPrompt's field is always a resizable textarea (Enter submits,
|
||||
Shift+Enter inserts a newline) — sensible min-height, wrapped output. */
|
||||
.tc-textarea {
|
||||
resize: vertical;
|
||||
min-height: 4.5em;
|
||||
line-height: 1.4;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* themedToast — non-blocking transient notifications (errors/info/ok) */
|
||||
.tc-toasts {
|
||||
|
|
|
|||
|
|
@ -125,15 +125,27 @@ export function themedConfirm(opts = {}) {
|
|||
}
|
||||
|
||||
// themedPrompt({ title, message, label, placeholder, value, confirmLabel, cancelLabel })
|
||||
// → Promise<string | null>. Themed replacement for window.prompt(): an input
|
||||
// dialog that resolves to the entered string on confirm, or null on cancel.
|
||||
// → Promise<string | null>. Themed replacement for window.prompt(): a
|
||||
// resizable <textarea> dialog that resolves to the entered string on confirm,
|
||||
// or null on cancel. Chat-box key behaviour: **Enter submits**, **Shift+Enter
|
||||
// inserts a newline** — so short answers are one keystroke while multi-line
|
||||
// reasons (e.g. an approval deny note) are still possible. Escape cancels
|
||||
// (via openDialog).
|
||||
export function themedPrompt(opts = {}) {
|
||||
const {
|
||||
title = '', message = '', label = '', placeholder = '', value = '',
|
||||
confirmLabel = 'ok', cancelLabel = 'cancel',
|
||||
} = opts;
|
||||
const input = el('input', { type: 'text', class: 'tc-input', placeholder });
|
||||
const input = el('textarea', { class: 'tc-input tc-textarea', rows: '3', placeholder });
|
||||
if (value) input.value = value;
|
||||
// Enter submits (clicks the confirm button mounted by openDialog);
|
||||
// Shift+Enter falls through to the textarea's default newline insert.
|
||||
input.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter' && !e.shiftKey) {
|
||||
e.preventDefault();
|
||||
input.closest('.tc-box')?.querySelector('.tc-confirm')?.click();
|
||||
}
|
||||
});
|
||||
const content = el('div', { class: 'tc-promptfield' },
|
||||
label ? el('label', { class: 'tc-promptlabel' }, label) : null,
|
||||
input);
|
||||
|
|
|
|||
Loading…
Reference in a new issue