aiMessageInput

The aiMessageInput component is where the user writes a message: a growing text area with a send button, optional controls beside the field, and optional application content above and below it.

XML Element

aiMessageInput

Java Class

AiMessageInput

Use it on its own wherever an application collects a message from the user. aiChat embeds it and configures it on your behalf, so everything on this page is reachable through the chat as well.

Overview

The message input keeps its controls on one row while the text fits a single line:

Message input in its collapsed state

Once the text grows past one line, the field takes the full width and the controls reflow into a toolbar row beneath it:

Message input in its expanded state

Basics

Declare the aichat namespace in the view’s XML descriptor:

<view xmlns="http://jmix.io/schema/flowui/view"
      xmlns:aichat="http://jmix.io/schema/aichat/ui"
      title="msg://MessageInputView.title">
Studio adds the namespace automatically when you add the component using the Add Component action in the top actions panel. See Component Palette.

A message input needs nothing but its element:

<aichat:aiMessageInput id="basicsComposer"/>

A standalone message input fills the width of its container. Unlike inside a chat, it has no width of its own, so give it a width or place it in a container that constrains one.

Submitting a Message

The text reaches the application through the submit event:

@Subscribe("basicsComposer")
public void onBasicsComposerSubmit(final AiMessageInput.SubmitEvent event) {
    lastMessageSpan.setText(event.getValue());
}

The event carries the submitted text, and the field clears itself afterwards, so the application does not have to.

The message input does not expose the text it holds. There is no getValue() or setValue(), so the application cannot read what the user is typing, pre-fill the field with a suggested prompt, or clear it early. The text becomes available only when the user submits it.

Text Area

The field grows with its content up to maxRows lines, ten by default, and scrolls internally beyond that:

<aichat:aiMessageInput id="maxRowsComposer" maxRows="3"/>

By default, Enter submits the message and Shift+Enter inserts a line break. Set enterAction to NEWLINE to swap the two, so that Enter inserts a line break and Ctrl/Cmd+Enter submits:

<aichat:aiMessageInput id="newlineComposer" enterAction="NEWLINE"/>

The setting also tells mobile keyboards how to label their action key.

Prefix and Suffix

The prefix and suffix elements put application controls inside the input box, before and after the field:

<aichat:aiMessageInput id="slotsComposer">
    <aichat:prefix>
        <button id="promptLibraryButton"
                icon="PLUS"
                themeNames="tertiary"
                title="msg://promptLibraryButton.title"/>
    </aichat:prefix>
    <aichat:suffix>
        <button id="clearButton"
                icon="MICROPHONE"
                themeNames="tertiary"
                title="msg://clearButton.title"/>
    </aichat:suffix>
</aichat:aiMessageInput>

A component declared in either element is injectable by id, exactly like a top-level component of the view:

@ViewComponent
private JmixButton promptLibraryButton;

@Subscribe
public void onInit(final InitEvent event) {
    promptLibraryButton.addClickListener(clickEvent ->
            notifications.show(messageBundle.getMessage("promptLibraryButton.notification")));
}

Header and Footer Bands

The header and footer elements hold application content inside the message input but outside the input box, such as a context line above the field or a disclaimer under it:

Message input with header and footer bands
XML
<aichat:aiMessageInput id="bandsComposer">
    <aichat:header>
        <span id="contextSpan" text="msg://contextSpan.text"/>
    </aichat:header>
    <aichat:footer>
        <span text="msg://disclaimer.text"/>
    </aichat:footer>
</aichat:aiMessageInput>
Message bundle
com.company.demo.view.messageinput/disclaimer.text=AI can make mistakes. Check important information.

Bands follow the width and centering of the box, so they line up with the field rather than with the surrounding layout. Their content is injectable by id and is disabled together with the message input.

To pull a band tight against the box, removing the gap that separates them, apply the no-header-footer-gap theme variant:

<aichat:aiMessageInput id="noGapComposer"
                       themeNames="no-header-footer-gap">
    <aichat:footer>
        <span text="msg://disclaimer.text"/>
    </aichat:footer>
</aichat:aiMessageInput>

The variant affects both bands at once and leaves the spacing inside the box untouched.

Fixed Toolbar

By default the message input switches between the two layouts shown in the overview as the text grows. The fixed-toolbar theme variant keeps the toolbar layout at all times, so the controls stay in a row of their own even when the field holds a single line:

<aichat:aiMessageInput id="fixedToolbarComposer"
                       themeNames="fixed-toolbar">
    <aichat:prefix>
        <button id="modelButton"
                text="msg://modelButton.text"
                themeNames="tertiary"/>
    </aichat:prefix>
</aichat:aiMessageInput>

Localization

The placeholder and the accessible names of the buttons come from the add-on’s message bundle, under the aiMessageInput.i18n.* keys. Override them in the application’s message bundle to re-word the message input everywhere.

To re-word a single message input, add a nested i18n element:

XML
<aichat:aiMessageInput id="i18nComposer">
    <aichat:i18n placeholder="msg://i18nComposer.placeholder"/>
</aichat:aiMessageInput>
Message bundle
com.company.demo.view.messageinput/i18nComposer.placeholder=Ask about this ticket

See Precedence for how the two levels combine.

Styling

The message input exposes its internals as shadow parts, addressable with the ::part() selector.

The following style properties can be used in CSS stylesheets to customize the appearance of this component.

Name Description

--jmix-ai-message-input-background

Background of the input box.

--jmix-ai-message-input-padding

Padding inside the input box.

--jmix-ai-message-input-gap

Gap between the parts of the message input: the bands, the chips tray, the field, and the buttons.

--jmix-ai-message-input-max-width

Width the component is centered within. Unset outside a chat, so a standalone message input fills its container.

--jmix-ai-message-input-icon-send

Glyph of the send button.

--jmix-ai-message-input-icon-stop

Glyph the send button shows while an answer is generating.

Theme Variants

Theme name Effect

fixed-toolbar

Keeps the controls in a row of their own at all times, instead of only once the text grows past one line. See Fixed Toolbar.

no-header-footer-gap

Removes the gap between the bands and the input box, so a band reads as a continuation of the field. See Header and Footer Bands.

Applied to a chat, both reach its message input. See Styling there.

The components are styled for both Jmix themes, Aura and Lumo, and follow the theme’s own tokens for focus rings, borders, radii, and spacing, which is why the properties above have no single default value. Dark mode, high-contrast mode, and reduced motion are handled, and layout is expressed in direction-agnostic properties, so the components follow the text direction of the document.

Attachments

The message input can accept files, by drag and drop or from a file picker, and pass them along with the message. Attachments span several components, so they are described together in Attachments.

Attributes

The following attributes are specific to aiMessageInput:

Name Description Default

acceptedFileExtensions

Restricts attachments to the listed file extensions. See Attachments.

—

acceptedMimeTypes

Restricts attachments to the listed media types. See Attachments.

—

attachmentsEnabled

Sets whether the message input accepts attachments. See Attachments.

false

enterAction

Sets what Enter does: SEND submits the message, NEWLINE inserts a line break. See Text Area.

SEND

maxFileSize

Sets the maximum size of a single attachment in bytes. See Attachments.

26214400

maxFiles

Sets how many files can be attached to one message. See Attachments.

10

maxRows

Sets how many lines the field grows to before it scrolls internally. See Text Area.

10

uploadDropZoneEnabled

Sets whether files can be dropped onto the message input. See Attachments.

true

themeNames

Applies theme variants: fixed-toolbar keeps the toolbar layout at all times, no-header-footer-gap removes the gap between the bands and the box.

—

The following shared attributes are supported by aiMessageInput:

Handlers

The following handlers are specific to aiMessageInput:

Name Description

AttachmentRejectedEvent

Fired when a file is refused by one of the attachment limits. Carries the file name and the reason. See Rejected Files.

StopEvent

Fired when the user clicks the stop button while an answer is generating.

SubmitEvent

Fired when the user submits a message. Carries the submitted text and its attachments. See Submitting a Message.

The following shared handlers are supported by aiMessageInput:

Focus and blur are reported for the message input as a whole: moving focus from the field to the send button, or to a control in a slot, does not fire them.

Elements

An aiMessageInput can include prefix, suffix, header, footer, tooltip, and i18n as its nested elements.

prefix, suffix

The prefix and suffix elements each hold one component placed inside the input box, before and after the field. See Prefix and Suffix.

The header and footer elements each hold one component placed inside the message input but outside the input box. See Header and Footer Bands.

i18n

The i18n element re-words this message input. It supports the placeholder, send, stop, and attach attributes, each accepting a message key. Omitted attributes keep their values from the message bundle. See Localization.