From ef251a481d193fba38e46fb5180fe4a0eeba052f Mon Sep 17 00:00:00 2001
From: Marco Beretta <81851188+berry-13@users.noreply.github.com>
Date: Fri, 31 Jul 2026 18:58:45 +0200
Subject: [PATCH] style(client): rebuild the ask question surfaces on shared
option rows
The popover and the chat card rendered the same question two different
ways: numbered rows in one, wrapped chip buttons in the other, and the
panel was painted with hardcoded white/gray instead of theme tokens.
Both surfaces now render one AskOptions list, so numbering, check badges,
rounding and hover states match wherever a question appears. The card
groups its prompt with the description, styles the answer box like the
composer, and gains a Skip button beside Submit so declining does not
require the popover. While the popover holds the question the card keeps
a hidden copy of itself in the thread, reserving the exact space the card
will need so nothing reflows when the question moves back.
---
.../Chat/Input/AskUserQuestionPopover.tsx | 91 ++++------
.../Chat/Messages/Content/AskUserQuestion.tsx | 157 ++++++++++++------
client/src/components/Chat/ask/options.tsx | 76 +++++++++
client/src/locales/en/translation.json | 2 +
4 files changed, 213 insertions(+), 113 deletions(-)
create mode 100644 client/src/components/Chat/ask/options.tsx
diff --git a/client/src/components/Chat/Input/AskUserQuestionPopover.tsx b/client/src/components/Chat/Input/AskUserQuestionPopover.tsx
index 1df592e213..8493258705 100644
--- a/client/src/components/Chat/Input/AskUserQuestionPopover.tsx
+++ b/client/src/components/Chat/Input/AskUserQuestionPopover.tsx
@@ -1,11 +1,11 @@
import { memo, useEffect, useRef } from 'react';
import { useWatch } from 'react-hook-form';
-import { Button } from '@librechat/client';
-import { Check, ChevronDown, CornerDownLeft, TriangleAlert, X } from 'lucide-react';
+import { Button, TooltipAnchor } from '@librechat/client';
+import { ChevronDown, CornerDownLeft, TriangleAlert } from 'lucide-react';
import useAskAnswerMode from '~/hooks/Input/useAskAnswerMode';
+import AskOptions from '~/components/Chat/ask/options';
import { useChatFormContext } from '~/Providers';
import { useLocalize } from '~/hooks';
-import { cn } from '~/utils';
/**
* Composer popover for a live `ask_user_question` pause. Single-select rows
@@ -15,10 +15,10 @@ import { cn } from '~/utils';
* Submit confirms —
* folding in any free-form text typed in the composer, exactly like Enter
* would. The footer hint is a button that focuses the composer — the
- * free-form answer box. Collapse (chevron) hides the popover but keeps
- * answer mode live via the chat card; × dismisses it entirely. Pure
- * rendering off {@link useAskAnswerMode}; disappears the moment an answer
- * submits from any surface, and locks while one is in flight.
+ * free-form answer box. The chevron moves the question to the chat card and
+ * releases the composer (the card's chevron moves it back). Pure rendering
+ * off {@link useAskAnswerMode}; disappears the moment an answer submits from
+ * any surface, and locks while one is in flight.
*/
function AskUserQuestionPopoverContent({
conversationId,
@@ -66,7 +66,6 @@ function AskUserQuestionPopoverPanel({
submit,
submitOption,
skip,
- dismiss,
collapse,
handlePopoverKeyDown,
} = ask;
@@ -108,7 +107,7 @@ function AskUserQuestionPopoverPanel({
scroll region: the panel is absolutely positioned, so anything that
overflows it is unreachable by page scroll. */}
@@ -122,60 +121,34 @@ function AskUserQuestionPopoverPanel({
)}
+ (multiSelect ? toggleChecked(index) : submitOption(index))}
+ optionRefs={optionRefs}
+ listRef={listRef}
+ className="relative min-h-0 flex-1 overflow-y-auto"
+ />
{/** A failed submission keeps the question answerable (controls stay
* enabled), but the chat card that would show the error is hidden
* while the popover is up — so surface it here for retry guidance. */}
@@ -188,7 +161,7 @@ function AskUserQuestionPopoverPanel({