Skip to content

💬 refactor: ChatForm UI redesign with unified palette - #14473

Open
berry-13 wants to merge 118 commits into
canaryfrom
redesign/chat-form
Open

berry-13 wants to merge 118 commits into
canaryfrom
redesign/chat-form

Conversation

@berry-13

@berry-13 berry-13 commented Jul 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Redesigns the input composer from scattered tool/badge controls into a cohesive system: a unified palette merges the attach menu, badge row, and tool dropdown into one searchable catalog with favorites; a composer bar holds active tools as chips with model effort and speech controls; a tray stages files and manual context; and a queue rail buffers messages while a reply is running. Removes ~40 old component files and replaces them with 8 new ones in Composer/ plus supporting hooks.

Change Type

  • Refactor

Testing

Run from client/:

cd packages/client && npm test -- --testPathPattern='(Palette|Queue|Tray|Bar|Thinking|Hints|useComposerItems|useAttachItems|useAttachTarget|useChipPacking|usePaletteEntries|useDictation|useToolFavorites|useRecentFiles|useSpeechToTextBrowser|useThinkingSetting|useAudioLevels|useComposerHint|useAttachExisting|useSteerRecovery)'

Manual verification (light and dark mode):

  • Click + in composer → palette opens with search, section headers, mode toggles for Artifacts
  • Type to search tools, skills, MCP servers, upload destinations, recent files
  • Star a row with ⌘D (Mac) or Ctrl+D (Windows/Linux) → moves to Favourites
  • Files uploaded → appear in tray with preview/progress
  • Quote another message → chip appears in tray
  • Select skill → chip in tray
  • During a run with steering enabled → queue rail shows queued messages, reorderable by arrow keys or drag
  • Mic icon → dictate, waveform shows levels, ⌘⏎/Ctrl+⏎ sends while recording
  • Effort button in bar → opens popover, slider and Auto toggle, no freeze on close

Test Configuration

Node 24, MongoDB in-memory via mongodb-memory-server

Checklist

  • Removed old badge row, tools dropdown, audio recorder, steer chips components
  • Added Composer subcomponents (Bar, Palette, Tray, Queue, Thinking, Hints, Waveform, Chip)
  • Added hooks for item management, packing, favorites, dictation, effort, audio levels, recent files
  • Palette is virtualized, searchable, supports drag-reorder in queue, favorites persist to user state
  • During-run steering integrated into queue rail instead of floating chips
  • BadgeRowContext memoized to prevent catalog rebuild on every keystroke
  • New tests cover row model, keyboard navigation, drag, favorites, search filtering, queue reorder
  • i18n keys added for new UI strings
  • Composer lift on landing screen keeps popup from pushing page scrollbar

Screenshots

Captured with the same local account, light theme, desktop viewport, and Ollama model. Before images use a clean dev checkout at 33e42e6d, which predates the redesign. After images use the current local redesign worktree, including the latest follow-up fixes that were not yet pushed when captured.

Composer redesign

Before: separate attachment and tool controls After: unified composer bar, active tools, thinking, and hints
Composer before Composer after
Before: upload-only attachment menu After: searchable Attach and tools palette
Attachment menu before Unified palette after

Palette, active tools, uploads, and thinking

Palette search Active tool chip
Filtered palette search Active File Search tool
Upload destinations Request-scoped thinking levels
Expanded upload destinations Thinking level popover

Staged file tray

Staged image preview in the composer tray

Queue and steering during a run

Queued messages with per-item actions Applied steer inside the response with the remaining queue preserved
Two queued messages during generation Applied steering message and remaining queue

Preferences and controls

General: composer tips Chat: sending, queue, steering, and drafts
General composer settings Chat sending and queue settings
Speech: transcription and auto-send Keyboard shortcuts, including stop and steer actions
Speech settings Keyboard shortcuts dialog

Copilot AI review requested due to automatic review settings July 28, 2026 02:18

This comment was marked as resolved.

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Unused i18next Keys Detected

The following translation keys are defined in translation.json but are not used in the codebase:

  • com_ui_artifacts_options
  • com_ui_custom_prompt_mode
  • com_ui_include_shadcnui
  • com_ui_quote_selections
  • com_ui_quotes_queued
  • com_ui_remove_all_quotes
  • com_ui_remove_skill_var
  • com_ui_save_badge_changes
  • com_ui_skills_queued
  • com_ui_x_selected

⚠️ Please remove these unused keys to keep the translation files clean.

@berry-13 berry-13 changed the title refactor: composer UI redesign with unified palette refactor: ChatForm UI redesign with unified palette Jul 28, 2026
@berry-13
berry-13 marked this pull request as draft July 28, 2026 02:20
@berry-13 berry-13 changed the title refactor: ChatForm UI redesign with unified palette 💬 refactor: ChatForm UI redesign with unified palette Jul 28, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 22dd4fd932

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/hooks/Input/useDictation.ts Outdated
Comment thread client/src/hooks/Input/useDictation.ts
Comment thread client/src/hooks/Input/useAttachItems.tsx
Comment thread client/src/hooks/Input/useDictation.ts Outdated
Comment thread client/src/hooks/Input/useComposerHint.ts
Comment thread client/src/components/Chat/Input/Composer/Palette.tsx Outdated
Comment thread client/src/hooks/Nav/useSideNavLinks.ts
Comment thread client/src/hooks/Input/usePaletteEntries.tsx Outdated
Comment thread client/src/components/Chat/Input/ChatForm.tsx
Comment thread client/src/hooks/Chat/useSteerRecovery.ts Outdated
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Unused i18next Keys Detected

The following translation keys are defined in translation.json but are not used in the codebase:

  • com_ui_artifacts_options
  • com_ui_custom_prompt_mode
  • com_ui_include_shadcnui
  • com_ui_quote_selections
  • com_ui_quotes_queued
  • com_ui_remove_all_quotes
  • com_ui_remove_skill_var
  • com_ui_save_badge_changes
  • com_ui_skills_queued
  • com_ui_x_selected

⚠️ Please remove these unused keys to keep the translation files clean.

@berry-13
berry-13 force-pushed the redesign/chat-form branch from 91c9023 to ea17702 Compare July 29, 2026 01:50
@github-actions

github-actions Bot commented Jul 29, 2026 •

Copy link
Copy Markdown
Contributor

🚨 Unused i18next Keys Detected

The following translation keys are defined in translation.json but are not used in the codebase:

  • com_ui_artifacts_options
  • com_ui_custom_prompt_mode
  • com_ui_include_shadcnui
  • com_ui_quote_selections
  • com_ui_quotes_queued
  • com_ui_remove_all_quotes
  • com_ui_remove_skill_var
  • com_ui_save_badge_changes
  • com_ui_skills_queued
  • com_ui_x_selected

⚠️ Please remove these unused keys to keep the translation files clean.

@berry-13
berry-13 force-pushed the redesign/chat-form branch from 9b16e98 to 3253b02 Compare July 29, 2026 13:13
@berry-13

Copy link
Copy Markdown
Collaborator Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 3253b02e5e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/hooks/Chat/useSteerRecovery.ts Outdated
Comment thread client/src/components/Chat/Input/Composer/Queue.tsx Outdated
Comment thread client/src/components/Chat/Input/ChatForm.tsx Outdated
Comment thread client/src/locales/en/translation.json Outdated
Comment thread client/src/hooks/Input/useDictation.ts
Comment thread client/src/components/Chat/Input/ChatForm.tsx Outdated
Comment thread client/src/Providers/BadgeRowContext.tsx
Comment thread client/src/components/Chat/Input/Composer/Queue.tsx
@berry-13
berry-13 force-pushed the redesign/chat-form branch from 3253b02 to ed3b2f8 Compare July 31, 2026 14:37
@github-actions

github-actions Bot commented Jul 31, 2026 •

Copy link
Copy Markdown
Contributor

🚨 Unused i18next Keys Detected

The following translation keys are defined in translation.json but are not used in the codebase:

  • com_ui_steer_in_flight_preempt

⚠️ Please remove these unused keys to keep the translation files clean.

@berry-13
berry-13 force-pushed the redesign/chat-form branch from 94dc760 to 6237d8d Compare August 2, 2026 02:34
@berry-13 berry-13 linked an issue Aug 2, 2026 that may be closed by this pull request
1 task
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

🚨 Unused i18next Keys Detected

The following translation keys are defined in translation.json but are not used in the codebase:

  • com_ui_always_interrupt
  • com_ui_steer_interrupts_enable_info
  • com_ui_wait_for_tool_steps

⚠️ Please remove these unused keys to keep the translation files clean.

@LibreChat-AI LibreChat-AI deleted a comment from github-actions Bot Aug 2, 2026
@berry-13
berry-13 force-pushed the redesign/chat-form branch from cf8f3dc to 0ea503b Compare August 2, 2026 17:52
@danny-avila
danny-avila marked this pull request as ready for review August 6, 2026 13:27
@berry-13
berry-13 force-pushed the redesign/chat-form branch from 0ea503b to 02f7f79 Compare August 6, 2026 14:18
@berry-13

berry-13 commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

@github-actions

github-actions Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

🚨 Unused i18next Keys Detected

The following translation keys are defined in translation.json but are not used in the codebase:

  • com_ui_wait_for_tool_steps

⚠️ Please remove these unused keys to keep the translation files clean.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb93796dc5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/components/Chat/Messages/Content/ContentParts.tsx Outdated
Comment thread client/src/hooks/Input/useAskAnswerMode.ts Outdated
Comment thread client/src/components/Chat/Input/Composer/Queue.tsx Outdated
Comment thread client/src/components/Chat/Input/Composer/Queue.tsx Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c18cad1f57

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/hooks/Input/usePaletteEntries.tsx
Comment thread client/src/components/Chat/Input/Composer/Effort.tsx Outdated
Comment thread client/src/hooks/Input/usePaletteEntries.tsx Outdated
Comment thread client/src/components/Chat/Input/Composer/Effort.tsx Outdated
@berry-13
berry-13 force-pushed the redesign/chat-form branch from c18cad1 to 2f6dad3 Compare August 6, 2026 20:14

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2f6dad3827

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread client/src/hooks/SSE/useResumableSSE.ts
Comment thread client/src/hooks/Input/useDictation.ts Outdated
Comment thread client/src/hooks/Chat/useSteerRecovery.ts
Comment thread client/src/components/Chat/Input/Composer/Effort.tsx Outdated
Comment thread client/src/hooks/Input/useDictation.ts Outdated
@berry-13

berry-13 commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator Author

@codex review

Stripping a replayed reasoning override that no longer validates removed
only the metadata field, while the resume had already replayed the paused
turn's model parameters with the override applied into the endpoint
option, so the provider still received what validation had refused. The
strip now inverts the application from the replayed base: the recorded
pre-override value returns and the thinking flag the override forced on
comes off.
The attach target returned the conversation or agent's saved
useResponsesApi flag, so an Azure chat auto-routed to the Responses API
by responsesApiRouting preflighted its uploads against the chat
completions route and lost provider-document uploads. The resolver now
applies resolveEffectiveUseResponsesApi with the endpoint, model,
web-search state and routing policy, the same resolution the during-run
upload target makes.
The during-run hint advertised Alt+Enter Interrupt & send even when the
chord had been claimed: a submitMessage rebound to Alt+Enter, a chord
yielded to a global shortcut, or shortcuts disabled altogether each make
the keydown resolver return something else. The hint now reads the same
resolver verdict the during-run send button does and omits the chord it
no longer owns.
…seline

The tab title counts every unseen conversation, and a shared
verification run leaves legitimately-unseen conversations from earlier
scenarios behind, so the three title-count scenarios failed on other
scenarios' leftovers instead of the behavior they seed. Each now reads
its baseline and asserts the count it adds and clears.
The away poll that lights a dot also discovers conversations the client
had not counted yet, so on the mobile project the title count can jump
past any baseline taken mid-test. Opening still has to clear this
conversation's contribution and an away reply still has to raise the
count, which is what the assertions now hold.
The MCP Apps integration spec still drove the old composer's MCP
Servers menu, which the redesign replaced with toggleable rows in the
attach-and-tools palette; the lane failed on the missing menu on every
run. The helper now opens the palette, waits for the server wave, and
flips the row's pressed state.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 723e1371dd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +267 to +271
...(message.parentMessageId != null &&
message.expectedPredecessorCreatedAt != null && {
lineage: {
parentMessageId: message.parentMessageId,
predecessorCreatedAt: message.expectedPredecessorCreatedAt,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve durability when requeuing recovered steers

When a receipt-bound recovered steer is edited after an aborted or failed run, discardQueued cancels its durable recovery source; if the user occupies the composer during that await, this requeue supplies lineage only when the original row already had both anchor fields. Fresh evidence beyond the resolved server-row thread is that useSteerConvert creates ordinary recovered rows with recoverySteerId but no parentMessageId or expectedPredecessorCreatedAt, so enqueue now has neither a live generation nor explicit lineage and creates only a client-local row that is lost on reload. Preserve a durable anchor for recovered rows before cancelling their parked source, or replace that source atomically.

AGENTS.md reference: AGENTS.md:L31-L34

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in c2bdafd. A recovered row is now handed to the composer before its parked steer is cancelled, so a refusing composer leaves the parked copy untouched; a cancel that fails after the composer took the words holds the row out of the run-end drain. Covered by Queue.spec (handing a recovered row to the composer).

Comment thread client/src/hooks/Input/useRecentFiles.ts
return { text: localize('com_ui_composer_hint_typing'), kind: 'tip' };
}

return { text: localize('com_ui_composer_hint_idle'), kind: 'tip' };

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Derive idle hints from enabled composer actions

When a user disables slash or mention commands, lacks prompt or multi-conversation access, uses an Assistants endpoint, or cannot attach files, this unconditional idle copy still says / for prompts · @ for models · + to attach. Hints also exposes it through the textarea's always-present aria-describedby, so screen-reader users are told to invoke actions that the key handler deliberately suppresses. Pass the resolved command and upload availability into the hint and omit unavailable actions.

AGENTS.md reference: AGENTS.md:L31-L34

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 2ba2b35. The idle hint is now built from idleActions resolved in ChatForm: / only with prompts access and the slash command on, @ only with the @ command on, + only when the attach target accepts files. Covered by useComposerHint.spec.

…kes it

A recovered row's only durable copy is the steer parked on the server, and
once its run has ended nothing can re-create it, so a composer that refused
the row after the cancel left the words in memory until the next reload.
The composer now takes the words first; a cancel that then fails holds the
row out of the run-end drain instead of sending it a second time.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2ba2b352d0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

const queryClient = useQueryClient();
const cachedMessages =
queryClient.getQueryData<TMessage[]>([QueryKeys.messages, conversationId]) ?? [];
const latestMessage = useLatestMessage(index, conversationId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Bind pause checks to the rendered conversation

When a cached branched conversation renders before conversationIdByIndex(index) catches up during initial load or warm navigation, this override selects the new message query but useLatestMessage still uses the stale pane conversation ID as its root sibling key—and returns null entirely if that ID is absent. Because the multi-message branch below treats a null or wrong tail as unpaused, Escalate becomes actionable while the rendered branch is paused on approval or a question. Fresh evidence beyond the earlier pane-index thread is that passing the correct pane index does not replace this stale root identity; gate the control until the pane owns conversationId, or let the hook accept that ID for both query and root selection.

AGENTS.md reference: AGENTS.md:L31-L34

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🗺️ Chat UI Shell codegraph: the taxonomy area this belongs to (classifier, confidence ≥ 0.9)

Projects

None yet

4 participants