style: strip the multi-line composer down to a bare editor #3
@@ -1,14 +1,34 @@
|
|||||||
import { useNavigation } from "@vicinae/api";
|
import { Action, ActionPanel, Form, Icon, useNavigation } from "@vicinae/api";
|
||||||
import { Form, Action, ActionPanel, Icon } from "@vicinae/api";
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The multi-line composer.
|
* The multi-line composer.
|
||||||
*
|
*
|
||||||
* This exists because the launcher's search bar is single-line and there is no
|
* This view exists because the launcher's search bar is single-line and there
|
||||||
* API to change that. Pressing ⌘↩ in the chat view pushes this view, where a
|
* is no API to change that. Pressing ⌘↩ in the chat view pushes this view, where
|
||||||
* real multi-line text area gives the behaviour people expect from a chat box:
|
* a real multi-line text area gives the behaviour people expect from a chat box:
|
||||||
* Return inserts a newline, and ⌘↩ sends.
|
* Return inserts a newline, ⌘↩ sends.
|
||||||
|
*
|
||||||
|
* It is deliberately stripped down to a single bare editor:
|
||||||
|
*
|
||||||
|
* - no field label, so nothing competes with the text itself
|
||||||
|
* - no description block, because the action bar already renders "Send ⌘↩"
|
||||||
|
* next to the button, which documents the shortcut without a paragraph
|
||||||
|
* - the placeholder is one short line rather than an instructions sentence
|
||||||
|
*
|
||||||
|
* ## The width limit
|
||||||
|
*
|
||||||
|
* A `Form.TextArea` cannot be made truly full-width from the extension API.
|
||||||
|
* Vicinae always renders it inside its `FormField` component
|
||||||
|
* (`ExtensionFormView.qml` → `textareaFieldComp`), and `FormField.qml` always
|
||||||
|
* lays out as three columns with proportional widths 2 / 5 / 2 — a label
|
||||||
|
* gutter, the editor, and an empty right spacer. That leaves roughly five
|
||||||
|
* ninths of the width for the editor, and the spacer stays even when there is
|
||||||
|
* no label. None of it is reachable from the extension side.
|
||||||
|
*
|
||||||
|
* So the only lever here is removing clutter, not reclaiming width. If Vicinae
|
||||||
|
* ever exposes a label-less or full-width field variant, this is the file to
|
||||||
|
* simplify further.
|
||||||
*/
|
*/
|
||||||
export interface ComposeFormProps {
|
export interface ComposeFormProps {
|
||||||
initialValue: string;
|
initialValue: string;
|
||||||
@@ -21,7 +41,7 @@ export function ComposeForm({ initialValue, onSubmit }: ComposeFormProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Form
|
<Form
|
||||||
navigationTitle="Compose message"
|
navigationTitle="Compose"
|
||||||
actions={
|
actions={
|
||||||
<ActionPanel>
|
<ActionPanel>
|
||||||
<Action.SubmitForm
|
<Action.SubmitForm
|
||||||
@@ -46,13 +66,11 @@ export function ComposeForm({ initialValue, onSubmit }: ComposeFormProps) {
|
|||||||
>
|
>
|
||||||
<Form.TextArea
|
<Form.TextArea
|
||||||
id="prompt"
|
id="prompt"
|
||||||
title="Message"
|
placeholder="Ask Lam anything…"
|
||||||
placeholder="Ask Lam anything. Return starts a new line."
|
|
||||||
defaultValue={initialValue}
|
defaultValue={initialValue}
|
||||||
error={error}
|
error={error}
|
||||||
autoFocus
|
autoFocus
|
||||||
/>
|
/>
|
||||||
<Form.Description title="Keyboard" text="Return — new line · ⌘↩ — send" />
|
|
||||||
</Form>
|
</Form>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user