feat: Render question text and options with markdown (#339)

This commit is contained in:
dotblue
2026-03-23 05:02:52 +08:00
committed by GitHub
parent b6ecdc7b44
commit bcc2558dff
4 changed files with 34 additions and 29 deletions
@@ -3,6 +3,7 @@ import type { ApiClient } from '@/api/client'
import type { ChatToolCall } from '@/chat/types'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { MarkdownRenderer } from '@/components/MarkdownRenderer'
import { isAskUserQuestionToolName, parseAskUserQuestionInput, type AskUserQuestionQuestion } from '@/components/ToolCard/askUserQuestion'
import { cn } from '@/lib/utils'
import { usePlatform } from '@/hooks/usePlatform'
@@ -40,10 +41,12 @@ function OptionRow(props: {
>
<SelectionMark checked={props.checked} mode={props.mode} />
<span className="min-w-0 flex-1">
<div className="font-medium text-[var(--app-fg)] break-words">{props.title}</div>
<div className="[&_.aui-md]:font-medium [&_.aui-md]:text-sm [&_.aui-md]:text-[var(--app-fg)]">
<MarkdownRenderer content={props.title} />
</div>
{props.description ? (
<div className="mt-0.5 text-xs text-[var(--app-hint)] break-words">
{props.description}
<div className="mt-0.5 [&_.aui-md]:text-xs [&_.aui-md]:text-[var(--app-hint)]">
<MarkdownRenderer content={props.description} />
</div>
) : null}
</span>
@@ -303,11 +306,8 @@ export function AskUserQuestionFooter(props: {
</div>
) : null}
{questions[clampedStep]?.question ? (
<div className={cn(
"text-sm text-[var(--app-fg)] break-words",
questions[clampedStep]?.header ? "mt-2" : ""
)}>
{questions[clampedStep].question}
<div className={cn(questions[clampedStep]?.header ? "mt-2" : "")}>
<MarkdownRenderer content={questions[clampedStep].question} />
</div>
) : null}
</div>
@@ -3,6 +3,7 @@ import type { ApiClient } from '@/api/client'
import type { ChatToolCall } from '@/chat/types'
import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button'
import { MarkdownRenderer } from '@/components/MarkdownRenderer'
import {
isRequestUserInputToolName,
parseRequestUserInputInput,
@@ -42,10 +43,12 @@ function OptionRow(props: {
>
<SelectionMark checked={props.checked} />
<span className="min-w-0 flex-1">
<div className="font-medium text-[var(--app-fg)] break-words">{props.title}</div>
<div className="[&_.aui-md]:font-medium [&_.aui-md]:text-sm [&_.aui-md]:text-[var(--app-fg)]">
<MarkdownRenderer content={props.title} />
</div>
{props.description ? (
<div className="mt-0.5 text-xs text-[var(--app-hint)] break-words">
{props.description}
<div className="mt-0.5 [&_.aui-md]:text-xs [&_.aui-md]:text-[var(--app-hint)]">
<MarkdownRenderer content={props.description} />
</div>
) : null}
</span>
@@ -205,8 +208,8 @@ export function RequestUserInputFooter(props: {
{currentQuestion ? (
<div className="mt-3">
{currentQuestion.question ? (
<div className="text-sm text-[var(--app-fg)] break-words">
{currentQuestion.question}
<div>
<MarkdownRenderer content={currentQuestion.question} />
</div>
) : null}
@@ -1,6 +1,7 @@
import type { ReactNode } from 'react'
import type { ToolViewProps } from '@/components/ToolCard/views/_all'
import { parseAskUserQuestionInput } from '@/components/ToolCard/askUserQuestion'
import { MarkdownRenderer } from '@/components/MarkdownRenderer'
import { cn } from '@/lib/utils'
type AnswersFormat = Record<string, string[]> | Record<string, { answers: string[] }>
@@ -134,8 +135,8 @@ export function AskUserQuestionView(props: ToolViewProps) {
return (
<div key={idx} className="rounded-md border border-[var(--app-border)] bg-[var(--app-bg)] p-3">
{q.question ? (
<div className="text-sm text-[var(--app-fg)] break-words">
{q.question}
<div>
<MarkdownRenderer content={q.question} />
</div>
) : null}
@@ -166,16 +167,16 @@ export function AskUserQuestionView(props: ToolViewProps) {
)}
<div className="min-w-0 flex-1">
<div className={cn(
"text-sm break-words",
"[&_.aui-md]:text-sm",
isSelected
? "text-emerald-700 dark:text-emerald-300 font-medium"
: "text-[var(--app-fg)]"
? "[&_.aui-md]:text-emerald-700 dark:[&_.aui-md]:text-emerald-300 [&_.aui-md]:font-medium"
: "[&_.aui-md]:text-[var(--app-fg)]"
)}>
{opt.label}
<MarkdownRenderer content={opt.label} />
</div>
{opt.description ? (
<div className="mt-0.5 text-xs text-[var(--app-hint)] break-words">
{opt.description}
<div className="mt-0.5 [&_.aui-md]:text-xs [&_.aui-md]:text-[var(--app-hint)]">
<MarkdownRenderer content={opt.description} />
</div>
) : null}
</div>
@@ -3,6 +3,7 @@ import {
parseRequestUserInputInput,
parseRequestUserInputAnswers
} from '@/components/ToolCard/requestUserInput'
import { MarkdownRenderer } from '@/components/MarkdownRenderer'
import { cn } from '@/lib/utils'
function getSelectionMark(isSelected: boolean): string {
@@ -42,8 +43,8 @@ export function RequestUserInputView(props: ToolViewProps) {
return (
<div key={q.id} className="rounded-md border border-[var(--app-border)] bg-[var(--app-bg)] p-3">
{q.question ? (
<div className="text-sm text-[var(--app-fg)] break-words">
{q.question}
<div>
<MarkdownRenderer content={q.question} />
</div>
) : null}
@@ -92,16 +93,16 @@ export function RequestUserInputView(props: ToolViewProps) {
)}
<div className="min-w-0 flex-1">
<div className={cn(
"text-sm break-words",
"[&_.aui-md]:text-sm",
isSelected
? "text-emerald-700 dark:text-emerald-300 font-medium"
: "text-[var(--app-fg)]"
? "[&_.aui-md]:text-emerald-700 dark:[&_.aui-md]:text-emerald-300 [&_.aui-md]:font-medium"
: "[&_.aui-md]:text-[var(--app-fg)]"
)}>
{opt.label}
<MarkdownRenderer content={opt.label} />
</div>
{opt.description ? (
<div className="mt-0.5 text-xs text-[var(--app-hint)] break-words">
{opt.description}
<div className="mt-0.5 [&_.aui-md]:text-xs [&_.aui-md]:text-[var(--app-hint)]">
<MarkdownRenderer content={opt.description} />
</div>
) : null}
</div>