From b053ff44083ad72afd4f677f1562ad161f69fb8f Mon Sep 17 00:00:00 2001 From: Exotic209093 <134711311+Exotic209093@users.noreply.github.com> Date: Sun, 13 Sep 2026 19:17:31 +0100 Subject: [PATCH] fix(mobile): render markdown in question cards Fixes #11132 --- .../features/threads/PendingUserInputCard.tsx | 73 +++++++++++++++---- 1 file changed, 58 insertions(+), 15 deletions(-) diff --git a/apps/mobile/src/features/threads/PendingUserInputCard.tsx b/apps/mobile/src/features/threads/PendingUserInputCard.tsx index 80fe6be689bb..e210c7f7b925 100644 --- a/apps/mobile/src/features/threads/PendingUserInputCard.tsx +++ b/apps/mobile/src/features/threads/PendingUserInputCard.tsx @@ -1,6 +1,6 @@ import { QuestionAttachments } from "./QuestionAttachments"; import type { ApprovalRequestId, UserInputQuestion } from "@t3tools/contracts"; -import { useCallback, useRef } from "react"; +import { useMemo, useCallback, useRef } from "react"; import { Platform, Pressable, ScrollView, View, type LayoutChangeEvent } from "react-native"; import Animated, { Easing, @@ -12,6 +12,7 @@ import Animated, { withTiming, type SharedValue, } from "react-native-reanimated"; +import { Markdown, type PartialMarkdownTheme } from "react-native-nitro-markdown"; import { USER_INPUT_TOGGLE_DURATION_MS } from "./pendingUserInputLayout"; @@ -19,6 +20,10 @@ import { SymbolView } from "../../components/AppSymbol"; import { AppText as Text } from "../../components/AppText"; import { ControlPill } from "../../components/ControlPill"; import { cn } from "../../lib/cn"; +import { useUniwindTheme } from "../../lib/useUniwindTheme"; +import { useFontFamily } from "../../lib/useFontFamily"; +import { resolveMarkdownFontSizes } from "../../lib/appearancePreferences"; +import { useAppearancePreferences } from "../settings/appearance/AppearancePreferencesProvider"; import { isPendingUserInputOptionSelected, type PendingUserInput, @@ -91,6 +96,55 @@ const CARD_LAYOUT_TRANSITION = LinearTransition.duration(200); export function PendingUserInputCard(props: PendingUserInputCardProps) { const questionCount = props.pendingUserInput.questions.length; + const { appearance } = useAppearancePreferences(); + const markdownFontSizes = useMemo( + () => resolveMarkdownFontSizes(appearance.baseFontSize), + [appearance.baseFontSize], + ); + const regularFontFamily = useFontFamily("regular"); + const boldFontFamily = useFontFamily("bold"); + const theme = useUniwindTheme(); + const markdownBodyColor = theme["--color-md-body"]; + const markdownStrongColor = theme["--color-md-strong"]; + const markdownLinkColor = theme["--color-md-link"]; + const inlineMarkdownTheme = useMemo( + () => ({ + colors: { + text: markdownBodyColor, + heading: markdownStrongColor, + link: markdownLinkColor, + surface: "transparent", + }, + spacing: { xs: 0, s: 0, m: 0, l: 0, xl: 0 }, + fontSizes: { + s: markdownFontSizes.s, + m: markdownFontSizes.m, + h1: markdownFontSizes.h1, + h2: markdownFontSizes.h2, + h3: markdownFontSizes.h3, + h4: markdownFontSizes.h4, + h5: markdownFontSizes.h5, + h6: markdownFontSizes.h6, + }, + fontFamilies: { + regular: regularFontFamily, + heading: boldFontFamily, + mono: regularFontFamily, + }, + headingWeight: "700", + borderRadius: { s: 4, m: 8, l: 12 }, + showCodeLanguage: false, + }), + [ + markdownBodyColor, + markdownStrongColor, + markdownLinkColor, + markdownFontSizes, + regularFontFamily, + boldFontFamily, + ], + ); + const cardCoverage = props.cardCoverage; const barHeightRef = useRef(0); const cardHeightRef = useRef(0); @@ -263,9 +317,7 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) { {question.header} - - {question.question} - + {question.question} {question.options.map((option) => { const optionValue = option.value ?? option.label.trim(); @@ -288,18 +340,9 @@ export function PendingUserInputCard(props: PendingUserInputCardProps) { } > - - {option.label} - + {option.label} {description ? ( - - {description} - + {description} ) : null}