Improve markdown styling and enable text selection on mobile
- Fix agent chat bottom scroll padding by adding overflow hidden to inputAreaContainer
- Create shared markdown-styles.ts with comprehensive styling for tables, headings, code blocks, blockquotes, and horizontal rules
- Enable text selection in AssistantMessage and AgentThoughtMessage by overriding markdown render rules with selectable={true}
- Path chips remain non-selectable to preserve onPress navigation
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
adc56da129
commit
38a4c70aec
@@ -1139,6 +1139,7 @@ const styles = StyleSheet.create(((theme: any) => ({
|
||||
minHeight: FOOTER_HEIGHT,
|
||||
alignItems: "center",
|
||||
width: "100%",
|
||||
overflow: "hidden",
|
||||
},
|
||||
inputAreaContent: {
|
||||
width: "100%",
|
||||
|
||||
@@ -42,6 +42,7 @@ import {
|
||||
extractReadEntries,
|
||||
} from "@/utils/tool-call-parsers";
|
||||
import { ToolCallSheetProvider } from "./tool-call-sheet";
|
||||
import { createMarkdownStyles } from "@/styles/markdown-styles";
|
||||
|
||||
const MAX_CHAT_WIDTH = 960;
|
||||
type PermissionResolvedMessage = Extract<
|
||||
@@ -594,62 +595,7 @@ function PermissionRequestCard({
|
||||
);
|
||||
|
||||
const markdownStyles = useMemo(
|
||||
() => ({
|
||||
body: {
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.base,
|
||||
lineHeight: 22,
|
||||
},
|
||||
text: {
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.base,
|
||||
lineHeight: 22,
|
||||
},
|
||||
paragraph: {
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
strong: {
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
},
|
||||
bullet_list: {
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
ordered_list: {
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
list_item: {
|
||||
flexDirection: "row" as const,
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
code_inline: {
|
||||
fontFamily: "monospace",
|
||||
backgroundColor: theme.colors.card,
|
||||
paddingHorizontal: theme.spacing[1],
|
||||
paddingVertical: theme.spacing[1],
|
||||
borderRadius: theme.borderRadius.sm,
|
||||
},
|
||||
code_block: {
|
||||
fontFamily: "monospace",
|
||||
backgroundColor: theme.colors.card,
|
||||
padding: theme.spacing[2],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
},
|
||||
fence: {
|
||||
fontFamily: "monospace",
|
||||
backgroundColor: theme.colors.card,
|
||||
padding: theme.spacing[2],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
},
|
||||
blockquote: {
|
||||
borderLeftWidth: theme.borderWidth[1],
|
||||
borderLeftColor: theme.colors.border,
|
||||
paddingLeft: theme.spacing[3],
|
||||
marginBottom: theme.spacing[2],
|
||||
},
|
||||
blockquote_text: {
|
||||
color: theme.colors.mutedForeground,
|
||||
},
|
||||
}),
|
||||
() => createMarkdownStyles(theme),
|
||||
[theme]
|
||||
);
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
} from "lucide-react-native";
|
||||
import { StyleSheet, useUnistyles } from "react-native-unistyles";
|
||||
import { baseColors, theme } from "@/styles/theme";
|
||||
import { createMarkdownStyles, createCompactMarkdownStyles } from "@/styles/markdown-styles";
|
||||
import { Colors } from "@/constants/theme";
|
||||
import * as Clipboard from "expo-clipboard";
|
||||
import type { TodoEntry, ThoughtStatus } from "@/types/stream";
|
||||
@@ -161,27 +162,7 @@ export const assistantMessageStylesheet = StyleSheet.create((theme) => ({
|
||||
fontSize: theme.fontSize.xs,
|
||||
fontWeight: theme.fontWeight.bold,
|
||||
},
|
||||
// Markdown styles
|
||||
markdownBody: {
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.base,
|
||||
lineHeight: 24,
|
||||
},
|
||||
markdownText: {
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.base,
|
||||
lineHeight: 22,
|
||||
},
|
||||
markdownParagraph: {
|
||||
marginTop: 0,
|
||||
marginBottom: theme.spacing[2],
|
||||
},
|
||||
markdownStrong: {
|
||||
fontWeight: theme.fontWeight.bold,
|
||||
},
|
||||
markdownEm: {
|
||||
fontStyle: "italic" as const,
|
||||
},
|
||||
// Used in custom markdownRules for inline code styling
|
||||
markdownCodeInline: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
color: theme.colors.secondaryForeground,
|
||||
@@ -191,47 +172,7 @@ export const assistantMessageStylesheet = StyleSheet.create((theme) => ({
|
||||
fontFamily: "monospace",
|
||||
fontSize: 13,
|
||||
},
|
||||
markdownCodeBlock: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
color: theme.colors.secondaryForeground,
|
||||
padding: theme.spacing[3],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
fontFamily: "monospace",
|
||||
fontSize: 13,
|
||||
},
|
||||
markdownFence: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
borderColor: theme.colors.border,
|
||||
color: theme.colors.secondaryForeground,
|
||||
padding: theme.spacing[3],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
marginVertical: theme.spacing[2],
|
||||
fontFamily: "monospace",
|
||||
fontSize: 13,
|
||||
},
|
||||
markdownLink: {
|
||||
color: theme.colors.primary,
|
||||
textDecorationLine: "underline" as const,
|
||||
},
|
||||
markdownList: {
|
||||
marginBottom: theme.spacing[2],
|
||||
},
|
||||
markdownListItem: {
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
markdownBlockquote: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
borderLeftWidth: 4,
|
||||
borderLeftColor: theme.colors.primary,
|
||||
paddingHorizontal: theme.spacing[3],
|
||||
paddingVertical: theme.spacing[2],
|
||||
marginVertical: theme.spacing[2],
|
||||
borderRadius: theme.borderRadius.sm,
|
||||
},
|
||||
markdownBlockquoteText: {
|
||||
color: theme.colors.foreground,
|
||||
fontStyle: "italic" as const,
|
||||
},
|
||||
// Used in custom markdownRules for path chip styling
|
||||
pathChip: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
borderRadius: theme.borderRadius.full,
|
||||
@@ -391,95 +332,75 @@ export const AssistantMessage = memo(function AssistantMessage({
|
||||
const lastPathRef = useRef<string | null>(null);
|
||||
|
||||
const markdownStyles = useMemo(
|
||||
() => ({
|
||||
body: {
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.base,
|
||||
lineHeight: 24,
|
||||
},
|
||||
text: {
|
||||
color: theme.colors.foreground,
|
||||
},
|
||||
paragraph: {
|
||||
marginTop: 0,
|
||||
marginBottom: theme.spacing[2],
|
||||
},
|
||||
strong: {
|
||||
fontWeight: theme.fontWeight.bold,
|
||||
},
|
||||
em: {
|
||||
fontStyle: "italic" as const,
|
||||
},
|
||||
code_inline: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
color: theme.colors.secondaryForeground,
|
||||
paddingHorizontal: theme.spacing[2],
|
||||
paddingVertical: 2,
|
||||
borderRadius: theme.borderRadius.sm,
|
||||
fontFamily: "monospace",
|
||||
fontSize: 13,
|
||||
},
|
||||
code_block: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
color: theme.colors.secondaryForeground,
|
||||
padding: theme.spacing[3],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
fontFamily: "monospace",
|
||||
fontSize: 13,
|
||||
},
|
||||
fence: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
borderColor: theme.colors.border,
|
||||
color: theme.colors.secondaryForeground,
|
||||
padding: theme.spacing[3],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
marginVertical: theme.spacing[2],
|
||||
fontFamily: "monospace",
|
||||
fontSize: 13,
|
||||
},
|
||||
link: {
|
||||
color: theme.colors.primary,
|
||||
textDecorationLine: "underline" as const,
|
||||
},
|
||||
bullet_list: {
|
||||
marginBottom: theme.spacing[2],
|
||||
},
|
||||
ordered_list: {
|
||||
marginBottom: theme.spacing[2],
|
||||
},
|
||||
list_item: {
|
||||
marginBottom: theme.spacing[1],
|
||||
},
|
||||
blockquote: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
borderLeftWidth: 4,
|
||||
borderLeftColor: theme.colors.primary,
|
||||
paddingHorizontal: theme.spacing[3],
|
||||
paddingVertical: theme.spacing[2],
|
||||
marginVertical: theme.spacing[2],
|
||||
borderRadius: theme.borderRadius.sm,
|
||||
},
|
||||
blockquote_text: {
|
||||
color: theme.colors.foreground,
|
||||
fontStyle: "italic" as const,
|
||||
},
|
||||
}),
|
||||
() => createMarkdownStyles(theme),
|
||||
[theme]
|
||||
);
|
||||
|
||||
const markdownRules = useMemo(() => {
|
||||
if (!onInlinePathPress) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
code_inline: (node: any) => {
|
||||
text: (
|
||||
node: any,
|
||||
_children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.text]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
textgroup: (
|
||||
node: any,
|
||||
children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.textgroup]} selectable>
|
||||
{children}
|
||||
</Text>
|
||||
),
|
||||
code_block: (
|
||||
node: any,
|
||||
_children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.code_block]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
fence: (
|
||||
node: any,
|
||||
_children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.fence]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
code_inline: (
|
||||
node: any,
|
||||
_children: ReactNode[],
|
||||
_parent: any,
|
||||
_styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => {
|
||||
const content = node.content ?? "";
|
||||
const parsed = parseInlinePathToken(content, lastPathRef);
|
||||
const parsed = onInlinePathPress
|
||||
? parseInlinePathToken(content, lastPathRef)
|
||||
: null;
|
||||
|
||||
if (!parsed) {
|
||||
return (
|
||||
<Text key={node.key} style={assistantMessageStylesheet.markdownCodeInline}>
|
||||
<Text
|
||||
key={node.key}
|
||||
style={[inheritedStyles, assistantMessageStylesheet.markdownCodeInline]}
|
||||
selectable
|
||||
>
|
||||
{content}
|
||||
</Text>
|
||||
);
|
||||
@@ -489,6 +410,7 @@ export const AssistantMessage = memo(function AssistantMessage({
|
||||
<Text
|
||||
key={node.key}
|
||||
onPress={() => parsed && onInlinePathPress?.(parsed)}
|
||||
selectable={false}
|
||||
style={[assistantMessageStylesheet.pathChip, assistantMessageStylesheet.pathChipText]}
|
||||
>
|
||||
{content}
|
||||
@@ -1020,42 +942,7 @@ export function AgentThoughtMessage({ message, status = "ready" }: AgentThoughtM
|
||||
const [isExpanded, setIsExpanded] = useState(false);
|
||||
const markdownContent = useMemo(() => message?.trim() ?? "", [message]);
|
||||
const markdownStyles = useMemo(
|
||||
() => ({
|
||||
body: {
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.sm,
|
||||
lineHeight: 20,
|
||||
},
|
||||
text: {
|
||||
color: theme.colors.foreground,
|
||||
},
|
||||
paragraph: {
|
||||
marginBottom: theme.spacing[2],
|
||||
},
|
||||
strong: {
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
},
|
||||
em: {
|
||||
fontStyle: "italic" as const,
|
||||
},
|
||||
code_inline: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
color: theme.colors.secondaryForeground,
|
||||
paddingHorizontal: theme.spacing[1],
|
||||
paddingVertical: 2,
|
||||
borderRadius: theme.borderRadius.sm,
|
||||
fontFamily: "monospace",
|
||||
fontSize: theme.fontSize.xs,
|
||||
},
|
||||
code_block: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
color: theme.colors.secondaryForeground,
|
||||
padding: theme.spacing[3],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
fontFamily: "monospace",
|
||||
fontSize: theme.fontSize.sm,
|
||||
},
|
||||
}),
|
||||
() => createCompactMarkdownStyles(theme),
|
||||
[theme]
|
||||
);
|
||||
|
||||
@@ -1063,12 +950,76 @@ export function AgentThoughtMessage({ message, status = "ready" }: AgentThoughtM
|
||||
setIsExpanded((prev) => !prev);
|
||||
}, []);
|
||||
|
||||
const markdownRules = useMemo(() => {
|
||||
return {
|
||||
text: (
|
||||
node: any,
|
||||
_children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.text]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
textgroup: (
|
||||
node: any,
|
||||
children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.textgroup]} selectable>
|
||||
{children}
|
||||
</Text>
|
||||
),
|
||||
code_block: (
|
||||
node: any,
|
||||
_children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.code_block]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
fence: (
|
||||
node: any,
|
||||
_children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.fence]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
code_inline: (
|
||||
node: any,
|
||||
_children: ReactNode[],
|
||||
_parent: any,
|
||||
styles: any,
|
||||
inheritedStyles: any = {}
|
||||
) => (
|
||||
<Text key={node.key} style={[inheritedStyles, styles.code_inline]} selectable>
|
||||
{node.content}
|
||||
</Text>
|
||||
),
|
||||
};
|
||||
}, []);
|
||||
|
||||
const renderDetails = useCallback(() => {
|
||||
if (!markdownContent) {
|
||||
return <Text style={agentThoughtStylesheet.emptyText}>No captured thinking</Text>;
|
||||
}
|
||||
return <Markdown style={markdownStyles}>{markdownContent}</Markdown>;
|
||||
}, [markdownContent, markdownStyles]);
|
||||
return (
|
||||
<Markdown style={markdownStyles} rules={markdownRules}>
|
||||
{markdownContent}
|
||||
</Markdown>
|
||||
);
|
||||
}, [markdownContent, markdownRules, markdownStyles]);
|
||||
|
||||
return (
|
||||
<ExpandableBadge
|
||||
|
||||
@@ -0,0 +1,365 @@
|
||||
import type { Theme } from "./theme";
|
||||
|
||||
/**
|
||||
* Creates comprehensive markdown styles for react-native-markdown-display.
|
||||
*
|
||||
* Usage:
|
||||
* const markdownStyles = useMemo(() => createMarkdownStyles(theme), [theme]);
|
||||
* <Markdown style={markdownStyles}>{content}</Markdown>
|
||||
*/
|
||||
export function createMarkdownStyles(theme: Theme) {
|
||||
return {
|
||||
// =========================================================================
|
||||
// BASE STYLES
|
||||
// =========================================================================
|
||||
|
||||
body: {
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.base,
|
||||
lineHeight: 22,
|
||||
},
|
||||
|
||||
text: {
|
||||
color: theme.colors.foreground,
|
||||
},
|
||||
|
||||
paragraph: {
|
||||
marginTop: 0,
|
||||
marginBottom: theme.spacing[3],
|
||||
flexWrap: "wrap" as const,
|
||||
flexDirection: "row" as const,
|
||||
alignItems: "flex-start" as const,
|
||||
justifyContent: "flex-start" as const,
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// HEADINGS
|
||||
// =========================================================================
|
||||
|
||||
heading1: {
|
||||
fontSize: theme.fontSize["3xl"],
|
||||
fontWeight: theme.fontWeight.bold,
|
||||
color: theme.colors.foreground,
|
||||
marginTop: theme.spacing[6],
|
||||
marginBottom: theme.spacing[3],
|
||||
lineHeight: 32,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.colors.border,
|
||||
paddingBottom: theme.spacing[2],
|
||||
},
|
||||
|
||||
heading2: {
|
||||
fontSize: theme.fontSize["2xl"],
|
||||
fontWeight: theme.fontWeight.bold,
|
||||
color: theme.colors.foreground,
|
||||
marginTop: theme.spacing[6],
|
||||
marginBottom: theme.spacing[3],
|
||||
lineHeight: 28,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: theme.colors.border,
|
||||
paddingBottom: theme.spacing[2],
|
||||
},
|
||||
|
||||
heading3: {
|
||||
fontSize: theme.fontSize.xl,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
color: theme.colors.foreground,
|
||||
marginTop: theme.spacing[4],
|
||||
marginBottom: theme.spacing[2],
|
||||
lineHeight: 26,
|
||||
},
|
||||
|
||||
heading4: {
|
||||
fontSize: theme.fontSize.lg,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
color: theme.colors.foreground,
|
||||
marginTop: theme.spacing[4],
|
||||
marginBottom: theme.spacing[2],
|
||||
lineHeight: 24,
|
||||
},
|
||||
|
||||
heading5: {
|
||||
fontSize: theme.fontSize.base,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
color: theme.colors.foreground,
|
||||
marginTop: theme.spacing[3],
|
||||
marginBottom: theme.spacing[1],
|
||||
lineHeight: 22,
|
||||
},
|
||||
|
||||
heading6: {
|
||||
fontSize: theme.fontSize.base,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
color: theme.colors.mutedForeground,
|
||||
marginTop: theme.spacing[3],
|
||||
marginBottom: theme.spacing[1],
|
||||
lineHeight: 20,
|
||||
textTransform: "uppercase" as const,
|
||||
letterSpacing: 0.5,
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// TEXT FORMATTING
|
||||
// =========================================================================
|
||||
|
||||
strong: {
|
||||
fontWeight: theme.fontWeight.bold,
|
||||
},
|
||||
|
||||
em: {
|
||||
fontStyle: "italic" as const,
|
||||
},
|
||||
|
||||
s: {
|
||||
textDecorationLine: "line-through" as const,
|
||||
color: theme.colors.mutedForeground,
|
||||
},
|
||||
|
||||
link: {
|
||||
color: theme.colors.primary,
|
||||
textDecorationLine: "underline" as const,
|
||||
},
|
||||
|
||||
blocklink: {
|
||||
color: theme.colors.primary,
|
||||
textDecorationLine: "underline" as const,
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// CODE
|
||||
// =========================================================================
|
||||
|
||||
code_inline: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
color: theme.colors.secondaryForeground,
|
||||
paddingHorizontal: theme.spacing[1],
|
||||
paddingVertical: 2,
|
||||
borderRadius: theme.borderRadius.sm,
|
||||
fontFamily: "monospace",
|
||||
fontSize: theme.fontSize.sm,
|
||||
},
|
||||
|
||||
code_block: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
color: theme.colors.secondaryForeground,
|
||||
padding: theme.spacing[3],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
fontFamily: "monospace",
|
||||
fontSize: theme.fontSize.sm,
|
||||
marginVertical: theme.spacing[2],
|
||||
},
|
||||
|
||||
fence: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
color: theme.colors.secondaryForeground,
|
||||
padding: theme.spacing[3],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
borderWidth: 1,
|
||||
borderColor: theme.colors.border,
|
||||
fontFamily: "monospace",
|
||||
fontSize: theme.fontSize.sm,
|
||||
marginVertical: theme.spacing[3],
|
||||
},
|
||||
|
||||
pre: {
|
||||
marginVertical: theme.spacing[2],
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// TABLES
|
||||
// =========================================================================
|
||||
|
||||
table: {
|
||||
borderWidth: 1,
|
||||
borderColor: theme.colors.border,
|
||||
borderRadius: theme.borderRadius.md,
|
||||
marginVertical: theme.spacing[3],
|
||||
},
|
||||
|
||||
thead: {
|
||||
backgroundColor: theme.colors.secondary,
|
||||
},
|
||||
|
||||
tbody: {},
|
||||
|
||||
th: {
|
||||
padding: theme.spacing[2],
|
||||
borderBottomWidth: 1,
|
||||
borderRightWidth: 1,
|
||||
borderColor: theme.colors.border,
|
||||
backgroundColor: theme.colors.secondary,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.sm,
|
||||
textAlign: "left" as const,
|
||||
},
|
||||
|
||||
tr: {
|
||||
borderBottomWidth: 1,
|
||||
borderColor: theme.colors.border,
|
||||
flexDirection: "row" as const,
|
||||
},
|
||||
|
||||
td: {
|
||||
padding: theme.spacing[2],
|
||||
borderRightWidth: 1,
|
||||
borderColor: theme.colors.border,
|
||||
color: theme.colors.foreground,
|
||||
fontSize: theme.fontSize.sm,
|
||||
flex: 1,
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// LISTS
|
||||
// =========================================================================
|
||||
|
||||
bullet_list: {
|
||||
marginVertical: theme.spacing[2],
|
||||
paddingLeft: theme.spacing[1],
|
||||
},
|
||||
|
||||
ordered_list: {
|
||||
marginVertical: theme.spacing[2],
|
||||
paddingLeft: theme.spacing[1],
|
||||
},
|
||||
|
||||
list_item: {
|
||||
marginBottom: theme.spacing[1],
|
||||
flexDirection: "row" as const,
|
||||
alignItems: "flex-start" as const,
|
||||
},
|
||||
|
||||
bullet_list_content: {
|
||||
flex: 1,
|
||||
flexWrap: "wrap" as const,
|
||||
},
|
||||
|
||||
ordered_list_content: {
|
||||
flex: 1,
|
||||
flexWrap: "wrap" as const,
|
||||
},
|
||||
|
||||
bullet_list_icon: {
|
||||
color: theme.colors.mutedForeground,
|
||||
marginRight: theme.spacing[2],
|
||||
fontSize: theme.fontSize.base,
|
||||
lineHeight: 22,
|
||||
},
|
||||
|
||||
ordered_list_icon: {
|
||||
color: theme.colors.mutedForeground,
|
||||
marginRight: theme.spacing[2],
|
||||
fontSize: theme.fontSize.base,
|
||||
fontWeight: theme.fontWeight.semibold,
|
||||
lineHeight: 22,
|
||||
minWidth: 20,
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// BLOCKQUOTE
|
||||
// =========================================================================
|
||||
|
||||
blockquote: {
|
||||
backgroundColor: theme.colors.muted,
|
||||
borderLeftWidth: 4,
|
||||
borderLeftColor: theme.colors.primary,
|
||||
paddingHorizontal: theme.spacing[4],
|
||||
paddingVertical: theme.spacing[3],
|
||||
marginVertical: theme.spacing[3],
|
||||
borderRadius: theme.borderRadius.md,
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// HORIZONTAL RULE
|
||||
// =========================================================================
|
||||
|
||||
hr: {
|
||||
backgroundColor: theme.colors.border,
|
||||
height: 1,
|
||||
marginVertical: theme.spacing[6],
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// IMAGES
|
||||
// =========================================================================
|
||||
|
||||
image: {
|
||||
borderRadius: theme.borderRadius.md,
|
||||
marginVertical: theme.spacing[2],
|
||||
},
|
||||
|
||||
// =========================================================================
|
||||
// BREAKS
|
||||
// =========================================================================
|
||||
|
||||
hardbreak: {
|
||||
height: theme.spacing[2],
|
||||
},
|
||||
|
||||
softbreak: {},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a smaller variant of markdown styles for compact UI elements
|
||||
* like thought bubbles, tooltips, or side panels.
|
||||
*/
|
||||
export function createCompactMarkdownStyles(theme: Theme) {
|
||||
const baseStyles = createMarkdownStyles(theme);
|
||||
|
||||
return {
|
||||
...baseStyles,
|
||||
|
||||
body: {
|
||||
...baseStyles.body,
|
||||
fontSize: theme.fontSize.sm,
|
||||
lineHeight: 20,
|
||||
},
|
||||
|
||||
heading1: {
|
||||
...baseStyles.heading1,
|
||||
fontSize: theme.fontSize.xl,
|
||||
marginTop: theme.spacing[4],
|
||||
marginBottom: theme.spacing[2],
|
||||
lineHeight: 26,
|
||||
},
|
||||
|
||||
heading2: {
|
||||
...baseStyles.heading2,
|
||||
fontSize: theme.fontSize.lg,
|
||||
marginTop: theme.spacing[3],
|
||||
marginBottom: theme.spacing[2],
|
||||
lineHeight: 24,
|
||||
},
|
||||
|
||||
heading3: {
|
||||
...baseStyles.heading3,
|
||||
fontSize: theme.fontSize.base,
|
||||
marginTop: theme.spacing[3],
|
||||
marginBottom: theme.spacing[1],
|
||||
lineHeight: 22,
|
||||
},
|
||||
|
||||
paragraph: {
|
||||
...baseStyles.paragraph,
|
||||
marginBottom: theme.spacing[2],
|
||||
},
|
||||
|
||||
code_inline: {
|
||||
...baseStyles.code_inline,
|
||||
fontSize: theme.fontSize.xs,
|
||||
},
|
||||
|
||||
code_block: {
|
||||
...baseStyles.code_block,
|
||||
fontSize: theme.fontSize.xs,
|
||||
padding: theme.spacing[2],
|
||||
},
|
||||
|
||||
fence: {
|
||||
...baseStyles.fence,
|
||||
fontSize: theme.fontSize.xs,
|
||||
padding: theme.spacing[2],
|
||||
},
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user