💬 feat: Explain Steering & Queuing at Every User-Facing Surface (#14260)

* 💬 feat: Explain Steering & Queuing at Every User-Facing Surface

Adds localized info affordances so users understand what steer / queue /
interrupt do wherever the feature appears, using the app's existing
norms (InfoHoverCard in Settings, TooltipAnchor in the composer, inline
descriptions in menus).

- Settings → Chat: an InfoHoverCard "?" beside the during-run action
  toggle explaining steer vs queue (matches every neighboring setting)
- During-run send button: the hover action list gains a header and a
  one-line description under each action (steer / queue / interrupt),
  turning the menu into a self-explaining card
- "Turn on steering / queueing" overflow entry: a description sub-line
  explaining the mode the user would switch to (the label alone doesn't
  say what steering/queueing means)
- Steered in-thread message: a subtle "Steered" badge with a tooltip
  clarifying why a user message appears inside the assistant response
- New English keys only (others automated)

* 🔤 style: Sort SteerPart imports (repo import-order)

* 🎐 refactor: Subtle "?" Info Affordances for Steering (Feedback)

Reworked the info UI toward the app's "?" InfoHoverCard norm and away
from always-on text / a loud badge:

- Steered message: replaced the amber "Steered" pill with a subtle "?"
  InfoHoverCard in the header (the norm; muted, hover-reveals why a user
  message appears inside the response)
- During-run send button: reverted the per-action description lines —
  the hovercard is already a hover-reveal affordance, so it stays a
  clean action list (labels + shortcuts)
- "Turn on steering/queueing" overflow entry: reverted the description
  sub-line back to a clean menu item
- Settings → Chat "While generating, Enter will…": keeps its "?"
  InfoHoverCard (the canonical, discoverable explanation)
- Pruned the 5 now-unused i18n keys; kept com_nav_info_during_run_action
  and com_ui_steered_info
This commit is contained in:
Danny Avila 2026-07-14 15:25:27 -04:00 committed by GitHub
parent e813934731
commit 5b0330fdfb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 15 additions and 2 deletions

View file

@ -2,6 +2,7 @@ import { memo, useMemo, useState, useCallback } from 'react';
import { X } from 'lucide-react';
import { useAtomValue } from 'jotai';
import { useRecoilValue } from 'recoil';
import { InfoHoverCard, ESide } from '@librechat/client';
import type { TFile, TMessage } from 'librechat-data-provider';
import type { TMessageIcon } from '~/common';
import FilePreviewDialog from '~/components/Chat/Messages/Content/FilePreviewDialog';
@ -101,8 +102,10 @@ const SteerPart = memo(function SteerPart({
</div>
</div>
<div className="user-turn relative flex w-11/12 flex-col">
<h2 className={cn('select-none font-semibold', fontSize)}>
<h2 className={cn('flex select-none items-center gap-1.5 font-semibold', fontSize)}>
{label}
{/* Subtle "?" explaining why a user message appears inside the response. */}
<InfoHoverCard side={ESide.Top} text={localize('com_ui_steered_info')} />
<MessageTimestamp value={timestamp} />
{onCancel != null && (
<button

View file

@ -72,4 +72,11 @@ describe('SteerPart author label', () => {
expect(screen.queryByText('Danny')).toBeNull();
expect(screen.getByText('com_user_message')).toBeInTheDocument();
});
it('shows a subtle info affordance explaining the mid-run message', () => {
renderPart();
// The "?" InfoHoverCard clarifies why a user message appears inside the
// assistant response (its text is the trigger's accessible label).
expect(screen.getByLabelText('com_ui_steered_info')).toBeInTheDocument();
});
});

View file

@ -1,6 +1,6 @@
import React from 'react';
import { useRecoilState } from 'recoil';
import { Button } from '@librechat/client';
import { Button, InfoHoverCard, ESide } from '@librechat/client';
import { useLocalize } from '~/hooks';
import store from '~/store';
@ -27,6 +27,7 @@ const DuringRunAction = () => {
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<span id="during-run-action-label">{localize('com_nav_during_run_action')}</span>
<InfoHoverCard side={ESide.Bottom} text={localize('com_nav_info_during_run_action')} />
</div>
<Button
variant="outline"

View file

@ -518,6 +518,7 @@
"com_nav_help_faq": "Help & FAQ",
"com_nav_info_balance": "Balance shows how many token credits you have left to use. Token credits translate to monetary value (e.g., 1000 credits = $0.001 USD)",
"com_nav_info_default_temporary_chat": "When enabled, new chats will start with temporary chat mode activated by default. Temporary chats are not saved to your history.",
"com_nav_info_during_run_action": "Choose what pressing Enter does while the assistant is still responding. \"Steer the response\" inserts your message into the current response at its next step; \"Queue for after\" sends it as a new turn once the response finishes. You can always override this per message from the send button.",
"com_nav_info_enter_to_send": "When enabled, pressing `ENTER` will send your message. When disabled, pressing Enter will add a new line, and you'll need to press `CTRL + ENTER` / `⌘ + ENTER` to send your message.",
"com_nav_info_fork_change_default": "`Visible messages only` includes just the direct path to the selected message. `Include related branches` adds branches along the path. `Include all to/from here` includes all connected messages and branches.",
"com_nav_info_fork_split_target_setting": "When enabled, forking will commence from the target message to the latest message in the conversation, according to the behavior selected.",
@ -1874,6 +1875,7 @@
"com_ui_steer_paused_queued": "The agent is waiting for your review — your message was queued instead",
"com_ui_steer_retry": "Retry steering",
"com_ui_steer_send": "Steer the current response",
"com_ui_steered_info": "You added this message while the response was generating, so it was inserted into the response at this point.",
"com_ui_stop": "Stop",
"com_ui_storage": "Storage",
"com_ui_storage_filter_sort": "Filter and Sort by Storage",