A React Native app for the ultimate thinking partner.
at sdk-v1-upgrade 197 lines 7.2 kB view raw
1import { Platform, StyleSheet } from 'react-native'; 2import { darkTheme, lightTheme, type Theme } from '../theme'; 3 4export interface MarkdownStyleOptions { 5 isUser: boolean; 6 isDark?: boolean; 7} 8 9export const createMarkdownStyles = ({ isUser, isDark = true }: MarkdownStyleOptions) => { 10 const theme = isDark ? darkTheme : lightTheme; 11 // Dark mode: white bg -> black text, Light mode: black bg -> white text 12 const userTextColor = isDark ? '#000000' : '#FFFFFF'; 13 const assistantTextColor = theme.colors.text.primary; 14 15 const codeFontFamily = Platform.select({ 16 ios: 'Menlo', 17 android: 'monospace', 18 default: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "DejaVu Sans Mono", "Courier New", monospace', 19 }); 20 21 return StyleSheet.create({ 22 body: { 23 color: isUser ? userTextColor : assistantTextColor, 24 fontSize: theme.typography.body.fontSize, 25 lineHeight: theme.typography.body.fontSize * 1.4, 26 fontFamily: theme.typography.body.fontFamily, 27 // Prevent long URLs/words from overflowing bubbles (RN Web) 28 wordBreak: 'break-word' as any, 29 overflowWrap: 'anywhere' as any, 30 whiteSpace: 'pre-wrap' as any, 31 }, 32 paragraph: { 33 marginTop: isUser ? 0 : theme.spacing[1], 34 marginBottom: isUser ? 0 : theme.spacing[2], 35 color: isUser ? userTextColor : assistantTextColor, 36 fontSize: theme.typography.body.fontSize, 37 lineHeight: theme.typography.body.fontSize * 1.4, 38 fontFamily: theme.typography.body.fontFamily, 39 wordBreak: 'break-word' as any, 40 overflowWrap: 'anywhere' as any, 41 whiteSpace: 'pre-wrap' as any, 42 }, 43 strong: { 44 fontFamily: 'Lexend_700Bold', 45 fontWeight: '700', 46 }, 47 em: { fontStyle: 'italic' }, 48 49 code_inline: { 50 // Inline code should look like text (no bubble) 51 backgroundColor: 'transparent', 52 color: isUser ? userTextColor : (isDark ? '#E5E5E5' : '#2A2A2A'), 53 paddingHorizontal: 0, 54 paddingVertical: 0, 55 borderRadius: 0, 56 borderWidth: 0, 57 borderColor: 'transparent', 58 fontFamily: codeFontFamily, 59 fontSize: theme.typography.code.fontSize, 60 lineHeight: theme.typography.code.fontSize * 1.5, 61 }, 62 code_block: { 63 // Slightly lighter than the chat background for contrast 64 backgroundColor: theme.colors.background.tertiary, 65 color: isUser ? userTextColor : (isDark ? '#E5E5E5' : '#2A2A2A'), 66 padding: theme.spacing[1.5], 67 // 90-degree corners to match app visual style 68 borderRadius: 0, 69 // Thin top/bottom separators for structure 70 borderTopWidth: StyleSheet.hairlineWidth, 71 borderBottomWidth: StyleSheet.hairlineWidth, 72 borderColor: theme.colors.border.primary, 73 fontFamily: codeFontFamily, 74 fontSize: theme.typography.codeBlock.fontSize, 75 marginTop: theme.spacing[1], 76 marginBottom: theme.spacing[2], 77 }, 78 // Some markdown renders fenced blocks using `fence` instead of `code_block` 79 fence: { 80 backgroundColor: theme.colors.background.tertiary, 81 color: isUser ? userTextColor : (isDark ? '#E5E5E5' : '#2A2A2A'), 82 padding: theme.spacing[1.5], 83 borderRadius: 0, 84 borderTopWidth: StyleSheet.hairlineWidth, 85 borderBottomWidth: StyleSheet.hairlineWidth, 86 borderColor: theme.colors.border.primary, 87 fontFamily: codeFontFamily, 88 fontSize: theme.typography.codeBlock.fontSize, 89 marginTop: theme.spacing[1], 90 marginBottom: theme.spacing[2], 91 }, 92 // Wrapper around fenced blocks on web; keep it transparent 93 pre: { 94 backgroundColor: 'transparent', 95 }, 96 97 heading1: { 98 fontSize: theme.typography.h1.fontSize, 99 fontWeight: theme.typography.h1.fontWeight, 100 fontFamily: 'Lexend_700Bold', 101 color: isUser ? userTextColor : assistantTextColor, 102 lineHeight: theme.typography.h1.fontSize * theme.typography.h1.lineHeight, 103 letterSpacing: theme.typography.h1.letterSpacing, 104 marginTop: theme.spacing[2], 105 marginBottom: theme.spacing[1], 106 }, 107 heading2: { 108 fontSize: theme.typography.h2.fontSize, 109 fontWeight: theme.typography.h2.fontWeight, 110 fontFamily: 'Lexend_500Medium', 111 color: isUser ? userTextColor : assistantTextColor, 112 lineHeight: theme.typography.h2.fontSize * theme.typography.h2.lineHeight, 113 letterSpacing: theme.typography.h2.letterSpacing, 114 marginTop: theme.spacing[1.5], 115 marginBottom: theme.spacing[1], 116 }, 117 heading3: { 118 fontSize: theme.typography.h3.fontSize, 119 fontWeight: theme.typography.h3.fontWeight, 120 fontFamily: 'Lexend_500Medium', 121 color: isUser ? userTextColor : assistantTextColor, 122 lineHeight: theme.typography.h3.fontSize * theme.typography.h3.lineHeight, 123 letterSpacing: theme.typography.h3.letterSpacing, 124 marginTop: theme.spacing[1], 125 marginBottom: theme.spacing[0.5], 126 }, 127 128 bullet_list: { marginTop: theme.spacing[0.5], marginBottom: theme.spacing[1] }, 129 ordered_list: { marginTop: theme.spacing[0.5], marginBottom: theme.spacing[1] }, 130 list_item: { flexDirection: 'row', marginVertical: 2 }, 131 bullet_list_icon: { 132 color: isUser ? userTextColor : theme.colors.text.secondary, 133 marginRight: theme.spacing[1], 134 fontSize: theme.typography.body.fontSize, 135 }, 136 bullet_list_content: { 137 color: isUser ? userTextColor : assistantTextColor, 138 fontSize: theme.typography.body.fontSize, 139 fontFamily: theme.typography.body.fontFamily, 140 lineHeight: theme.typography.body.fontSize * 1.4, 141 flex: 1, 142 }, 143 144 blockquote: { 145 backgroundColor: isUser ? theme.colors.background.surface : theme.colors.background.tertiary, 146 borderLeftWidth: 4, 147 borderLeftColor: isUser ? theme.colors.text.secondary : theme.colors.interactive.primary, 148 paddingLeft: theme.spacing[1.5], 149 paddingVertical: theme.spacing[1], 150 marginTop: theme.spacing[1.5], 151 marginBottom: theme.spacing[2], 152 }, 153 154 link: { 155 color: isUser ? theme.colors.text.inverse : theme.colors.interactive.primary, 156 textDecorationLine: 'underline', 157 wordBreak: 'break-all' as any, 158 overflowWrap: 'anywhere' as any, 159 }, 160 hr: { 161 backgroundColor: isUser ? theme.colors.border.secondary : theme.colors.border.primary, 162 height: 1, 163 marginVertical: theme.spacing[1], 164 }, 165 table: { 166 borderWidth: 1, 167 borderColor: theme.colors.border.primary, 168 borderRadius: 4, 169 }, 170 thead: {}, 171 tbody: {}, 172 th: { 173 flex: 1, 174 padding: 8, 175 borderWidth: 1, 176 borderColor: theme.colors.border.primary, 177 fontFamily: 'Lexend_600SemiBold', 178 fontSize: theme.typography.bodySmall.fontSize, 179 color: isUser ? userTextColor : assistantTextColor, 180 }, 181 tr: { 182 flexDirection: 'row', 183 borderBottomWidth: 1, 184 borderColor: theme.colors.border.primary, 185 }, 186 td: { 187 flex: 1, 188 padding: 8, 189 borderWidth: 1, 190 borderColor: theme.colors.border.primary, 191 fontSize: theme.typography.body.fontSize, 192 color: isUser ? userTextColor : assistantTextColor, 193 }, 194 }); 195}; 196 197export default createMarkdownStyles;