mirror of
https://github.com/block/goose.git
synced 2026-07-17 12:56:20 +02:00
fix: treat Option+Return as newline in multiline text inputs (#118)
* fix: treat Option+Return as newline in multiline text inputs Currently only Shift+Return inserts a newline in multiline text areas (like the chat input). Option+Return (Alt+Return) was treated the same as plain Return, triggering the send action. Add altKey checks alongside the existing shiftKey checks in both: - ChatInput: skip send when altKey is held - PromptInputTextarea: early-return (allow newline) when altKey is held * test: add alt-enter multiline regression coverage
This commit is contained in:
@@ -279,7 +279,7 @@ export function ChatInput({
|
||||
}
|
||||
}
|
||||
}
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
if (e.key === "Enter" && !e.shiftKey && !e.altKey) {
|
||||
e.preventDefault();
|
||||
handleSend();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect, vi } from "vitest";
|
||||
import { render, screen } from "@testing-library/react";
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { useState } from "react";
|
||||
import { ChatInput } from "../ChatInput";
|
||||
@@ -75,6 +75,23 @@ describe("ChatInput", () => {
|
||||
expect(onSend).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not call onSend on Alt+Enter (newline)", async () => {
|
||||
const onSend = vi.fn();
|
||||
const user = userEvent.setup();
|
||||
render(<ChatInput onSend={onSend} />);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
await user.type(input, "hello");
|
||||
const wasNotPrevented = fireEvent.keyDown(input, {
|
||||
altKey: true,
|
||||
key: "Enter",
|
||||
});
|
||||
|
||||
expect(wasNotPrevented).toBe(true);
|
||||
expect(onSend).not.toHaveBeenCalled();
|
||||
expect(input).toHaveValue("hello");
|
||||
});
|
||||
|
||||
it("shows current model name in model picker", () => {
|
||||
render(
|
||||
<ChatInput
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
import { fireEvent, render, screen } from "@testing-library/react";
|
||||
import userEvent from "@testing-library/user-event";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
import {
|
||||
PromptInput,
|
||||
PromptInputSubmit,
|
||||
PromptInputTextarea,
|
||||
} from "./prompt-input";
|
||||
|
||||
describe("PromptInputTextarea", () => {
|
||||
it("does not submit on Alt+Enter and inserts a newline", async () => {
|
||||
const onSubmit = vi.fn();
|
||||
const user = userEvent.setup();
|
||||
|
||||
render(
|
||||
<PromptInput onSubmit={onSubmit}>
|
||||
<PromptInputTextarea />
|
||||
<PromptInputSubmit />
|
||||
</PromptInput>,
|
||||
);
|
||||
|
||||
const input = screen.getByRole("textbox");
|
||||
await user.type(input, "hello");
|
||||
const wasNotPrevented = fireEvent.keyDown(input, {
|
||||
altKey: true,
|
||||
key: "Enter",
|
||||
});
|
||||
|
||||
expect(wasNotPrevented).toBe(true);
|
||||
expect(onSubmit).not.toHaveBeenCalled();
|
||||
expect(input).toHaveValue("hello");
|
||||
});
|
||||
});
|
||||
@@ -972,7 +972,7 @@ export const PromptInputTextarea = ({
|
||||
if (isComposing || e.nativeEvent.isComposing) {
|
||||
return;
|
||||
}
|
||||
if (e.shiftKey) {
|
||||
if (e.shiftKey || e.altKey) {
|
||||
return;
|
||||
}
|
||||
e.preventDefault();
|
||||
|
||||
Reference in New Issue
Block a user