Skip to content

Commit 58855be

Browse files
committed
fixes
#310886
1 parent 334c5b7 commit 58855be

File tree

1 file changed

+70
-6
lines changed

1 file changed

+70
-6
lines changed

src/vs/workbench/contrib/chat/browser/widget/chatContentParts/chatQuestionCarouselPart.ts

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import './media/chatQuestionCarousel.css';
3939

4040
const PREVIOUS_QUESTION_ACTION_ID = 'workbench.action.chat.previousQuestion';
4141
const NEXT_QUESTION_ACTION_ID = 'workbench.action.chat.nextQuestion';
42+
const QUESTION_TITLE_TRUNCATION_THRESHOLD = 200;
4243
export interface IChatQuestionCarouselOptions {
4344
onSubmit: (answers: Map<string, IChatQuestionAnswerValue> | undefined) => void;
4445
shouldAutoFocus?: boolean;
@@ -72,6 +73,10 @@ export class ChatQuestionCarouselPart extends Disposable implements IChatContent
7273
private _skipAllButton: Button | undefined;
7374

7475
private _isSkipped = false;
76+
private _isQuestionTextExpanded = false;
77+
private _expandButton: Button | undefined;
78+
private _renderQuestionTitle: ((expanded: boolean) => void) | undefined;
79+
private _questionTitleIsLong = false;
7580

7681
private readonly _textInputBoxes: Map<string, InputBox> = new Map();
7782
private readonly _singleSelectItems: Map<string, { items: HTMLElement[]; selectedIndex: number; optionIndices: number[] }> = new Map();
@@ -167,6 +172,14 @@ export class ChatQuestionCarouselPart extends Disposable implements IChatContent
167172
collapseButton.element.setAttribute('aria-label', collapseToggleTitle);
168173
this._collapseButton = collapseButton;
169174

175+
// Expand button for showing/hiding full question text
176+
const expandButton = interactiveStore.add(new Button(this._headerActionsContainer, { ...defaultButtonStyles, secondary: true, supportIcons: true }));
177+
expandButton.element.classList.add('chat-question-collapse-toggle');
178+
this._expandButton = expandButton;
179+
this._isQuestionTextExpanded = false;
180+
this.updateExpandButton();
181+
interactiveStore.add(expandButton.onDidClick(() => this.toggleQuestionTextExpanded()));
182+
170183
// Close/skip button (X) - placed in header row, only shown when allowSkip is true
171184
if (carousel.allowSkip) {
172185
this._closeButtonContainer = dom.$('.chat-question-close-container');
@@ -312,6 +325,31 @@ export class ChatQuestionCarouselPart extends Disposable implements IChatContent
312325
}
313326
}
314327

328+
private toggleQuestionTextExpanded(): void {
329+
this._isQuestionTextExpanded = !this._isQuestionTextExpanded;
330+
if (this._renderQuestionTitle) {
331+
this._renderQuestionTitle(this._isQuestionTextExpanded);
332+
}
333+
this.updateExpandButton();
334+
this._onDidChangeHeight.fire();
335+
}
336+
337+
private updateExpandButton(): void {
338+
if (!this._expandButton) {
339+
return;
340+
}
341+
const expanded = this._isQuestionTextExpanded;
342+
const label = expanded
343+
? localize('chat.questionCarousel.collapseQuestionText', "Collapse Question Text")
344+
: localize('chat.questionCarousel.expandQuestionText', "Expand Question Text");
345+
this._expandButton.label = expanded
346+
? `$(${Codicon.screenNormal.id})`
347+
: `$(${Codicon.screenFull.id})`;
348+
this._expandButton.element.setAttribute('aria-label', label);
349+
this._expandButton.element.setAttribute('aria-expanded', String(expanded));
350+
this._expandButton.setTitle(label);
351+
}
352+
315353
/**
316354
* Navigates the carousel by the given delta.
317355
* @param delta Negative for previous, positive for next
@@ -425,6 +463,7 @@ export class ChatQuestionCarouselPart extends Disposable implements IChatContent
425463
this._closeButtonContainer = undefined;
426464
this._focusTerminalButtonContainer = undefined;
427465
this._collapseButton = undefined;
466+
this._expandButton = undefined;
428467
this._footerRow = undefined;
429468
this._stepIndicator = undefined;
430469
this._submitHint = undefined;
@@ -664,6 +703,12 @@ export class ChatQuestionCarouselPart extends Disposable implements IChatContent
664703
// Clear previous content
665704
dom.clearNode(this._questionContainer);
666705

706+
// Reset expand state for new question
707+
this._isQuestionTextExpanded = false;
708+
this._renderQuestionTitle = undefined;
709+
this._questionTitleIsLong = false;
710+
this.updateExpandButton();
711+
667712
const question = this.carousel.questions[this._currentIndex];
668713
if (!question) {
669714
return;
@@ -687,20 +732,39 @@ export class ChatQuestionCarouselPart extends Disposable implements IChatContent
687732
const title = dom.$('.chat-question-title');
688733
const messageContent = this.getQuestionText(questionText);
689734
title.setAttribute('aria-label', messageContent);
690-
questionRenderStore.add(this._hoverService.setupDelayedHover(title, { content: messageContent }));
691735

692-
const titleText = question.required
693-
? new MarkdownString(`${isMarkdownString(questionText) ? questionText.value : questionText} *`)
694-
: (isMarkdownString(questionText) ? MarkdownString.lift(questionText) : new MarkdownString(questionText));
695-
const renderedTitle = questionRenderStore.add(this._markdownRendererService.render(titleText));
696-
title.appendChild(renderedTitle.element);
736+
const isLong = messageContent.length > QUESTION_TITLE_TRUNCATION_THRESHOLD;
737+
const renderTitle = (expanded: boolean) => {
738+
dom.clearNode(title);
739+
const rawValue = isMarkdownString(questionText) ? questionText.value : questionText;
740+
const displayValue = (isLong && !expanded)
741+
? rawValue.slice(0, QUESTION_TITLE_TRUNCATION_THRESHOLD).replace(/\s+\S*$/, '') + '…'
742+
: rawValue;
743+
const suffixed = question.required ? `${displayValue} *` : displayValue;
744+
const md = isMarkdownString(questionText)
745+
? new MarkdownString(suffixed, { isTrusted: questionText.isTrusted, supportThemeIcons: questionText.supportThemeIcons })
746+
: new MarkdownString(suffixed);
747+
const rendered = questionRenderStore.add(this._markdownRendererService.render(md));
748+
title.appendChild(rendered.element);
749+
};
750+
751+
renderTitle(this._isQuestionTextExpanded);
752+
this._renderQuestionTitle = renderTitle;
753+
this._questionTitleIsLong = isLong;
697754
titleRow.appendChild(title);
755+
} else {
756+
this._renderQuestionTitle = undefined;
757+
this._questionTitleIsLong = false;
698758
}
699759

700760
headerRow.appendChild(titleRow);
701761

702762
if (this._headerActionsContainer) {
703763
dom.clearNode(this._headerActionsContainer);
764+
if (this._expandButton) {
765+
this._headerActionsContainer.appendChild(this._expandButton.element);
766+
dom.setVisibility(this._questionTitleIsLong, this._expandButton.element);
767+
}
704768
if (this._focusTerminalButtonContainer) {
705769
this._headerActionsContainer.appendChild(this._focusTerminalButtonContainer);
706770
}

0 commit comments

Comments
 (0)