From a7b2d569048400f3b9646ca2aac52e9af53850fd 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 | 99 ++++------
.../Chat/Messages/Content/AskUserQuestion.tsx | 171 +++++++++++-------
client/src/components/Chat/ask/options.tsx | 76 ++++++++
client/src/locales/en/translation.json | 2 +
4 files changed, 216 insertions(+), 132 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 66c73e2654..e0c0f85c85 100644
--- a/client/src/components/Chat/Input/AskUserQuestionPopover.tsx
+++ b/client/src/components/Chat/Input/AskUserQuestionPopover.tsx
@@ -1,12 +1,12 @@
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, X } from 'lucide-react';
import AskUserQuestions from '~/components/Chat/Messages/Content/AskUserQuestions';
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
@@ -16,10 +16,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,
@@ -114,7 +114,6 @@ function AskUserQuestionPopoverPanel({
submit,
submitOption,
skip,
- dismiss,
collapse,
handlePopoverKeyDown,
} = ask;
@@ -156,7 +155,7 @@ function AskUserQuestionPopoverPanel({
scroll region: the panel is absolutely positioned, so anything that
overflows it is unreachable by page scroll. */}
@@ -170,64 +169,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. */}
@@ -240,7 +209,7 @@ function AskUserQuestionPopoverPanel({