Make the formula bar mouse-resizable and wrapping

Switches the formula bar from a single-line <input> to a <textarea>:

- A plain <textarea> gets a free, native mouse-draggable resize handle in
  its bottom-right corner (CSS resize: vertical) -- exactly the "erweiterbar/
  erhöhbar mit der Maus" ask, no custom drag code needed.
- Unlike the old <input>, it actually wraps a long formula instead of just
  scrolling it sideways, so dragging the handle taller has something to
  show (min-height keeps the collapsed case looking like before; max-height
  caps it at half the viewport).
- Brought its keyboard handling in line with the in-cell editor from the
  last two changes: Alt+Enter/Cmd+Enter insert a literal newline, F4 cycles
  every reference a selection overlaps, Escape reverts and blurs.
- .formula-bar switches to align-items: flex-start (with matching top
  margins on the labels) so the cell-name/fx labels stay pinned to the
  first line instead of vertically centering in a now-tall box.

Verified interactively: dragging the handle down 80px grows the bar from
~34px to ~113px; Alt+Enter inserts a real newline in the (now multi-line-
capable) field.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
wkh
2026-09-02 11:11:01 +02:00
co-authored by Claude Sonnet 5
parent 8c9f3bbc87
commit 67b011637d
2 changed files with 49 additions and 8 deletions
+43 -8
View File
@@ -35,8 +35,7 @@ function onEscape() {
/** F4: cycle relative -> absolute -> row-locked -> col-locked (Excel/Numbers
* "Bezug sperren") -- for the reference at the caret, or every reference a
* real text selection overlaps at once. */
function onF4(e: KeyboardEvent) {
const el = e.target as HTMLInputElement;
function onF4(el: HTMLTextAreaElement) {
const start = el.selectionStart ?? draft.value.length;
const end = el.selectionEnd ?? start;
const res = cycleReferenceLocks(draft.value, start, end);
@@ -44,6 +43,31 @@ function onF4(e: KeyboardEvent) {
draft.value = res.text;
nextTick(() => el.setSelectionRange(res.start, res.end));
}
function onKeydown(e: KeyboardEvent) {
const el = e.target as HTMLTextAreaElement;
// Alt+Enter (Windows/Excel-365-Mac) or Cmd+Enter (a macOS-safe fallback --
// Option is a compose key there, so `altKey` alone isn't fully reliable;
// `e.code` sidesteps `key` being altered by that composition).
const isEnter = e.key === 'Enter' || e.code === 'Enter' || e.code === 'NumpadEnter';
if (isEnter && (e.altKey || e.metaKey)) {
e.preventDefault();
const start = el.selectionStart ?? draft.value.length;
const end = el.selectionEnd ?? start;
draft.value = draft.value.slice(0, start) + '\n' + draft.value.slice(end);
nextTick(() => el.setSelectionRange(start + 1, start + 1));
return;
}
if (isEnter) {
e.preventDefault();
onEnter();
} else if (e.key === 'Escape') {
e.preventDefault();
onEscape();
} else if (e.key === 'F4') {
e.preventDefault();
onF4(el);
}
}
</script>
<template>
@@ -52,17 +76,16 @@ function onF4(e: KeyboardEvent) {
{{ store.activeCellName.value }}
</span>
<span class="fx">fx</span>
<input
<textarea
v-model="draft"
class="formula-input"
type="text"
spellcheck="false"
rows="1"
placeholder="Wert oder =Formel"
title="Ziehen an der unteren Kante, um mehr Zeilen zu zeigen"
@focus="focused = true"
@blur="onBlur"
@keydown.enter.prevent="onEnter"
@keydown.esc.prevent="onEscape"
@keydown.f4.prevent="onF4"
@keydown="onKeydown"
/>
</div>
</template>
@@ -70,7 +93,7 @@ function onF4(e: KeyboardEvent) {
<style scoped>
.formula-bar {
display: flex;
align-items: center;
align-items: flex-start;
gap: 10px;
padding: 6px 12px;
background: var(--surface);
@@ -79,6 +102,7 @@ function onF4(e: KeyboardEvent) {
.cell-name {
min-width: 128px;
max-width: 128px;
margin-top: 6px;
font-weight: 600;
font-size: 12px;
color: var(--text-dim);
@@ -97,12 +121,19 @@ function onF4(e: KeyboardEvent) {
}
}
.fx {
margin-top: 6px;
font-style: italic;
color: var(--text-dim);
font-size: 13px;
}
/* a plain <textarea> gives a free, native mouse-draggable resize handle
(bottom-right corner) -- exactly the "erweiterbar/erhöhbar mit der Maus"
ask -- and, unlike the old <input>, actually wraps a long formula instead
of just scrolling it sideways, so growing the box has something to show. */
.formula-input {
flex: 1;
min-height: 30px;
max-height: 50vh;
border: 1px solid var(--border);
border-radius: var(--radius-sm);
padding: 6px 10px;
@@ -110,6 +141,10 @@ function onF4(e: KeyboardEvent) {
font-variant-numeric: tabular-nums;
color: var(--text);
background: var(--surface-2);
resize: vertical;
overflow-y: auto;
white-space: pre-wrap;
word-break: break-word;
}
.formula-input:focus {
outline: none;