better markdown formatting in chat and widgets
This commit is contained in:
parent
fcd300d6c2
commit
5c1e3fd17a
4 changed files with 209 additions and 6 deletions
|
|
@ -20,7 +20,9 @@
|
|||
"cors": "^2.8.6",
|
||||
"express": "^5.2.1",
|
||||
"react": "^19.2.0",
|
||||
"react-dom": "^19.2.0"
|
||||
"react-dom": "^19.2.0",
|
||||
"react-markdown": "^10.1.0",
|
||||
"remark-gfm": "^4.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.1",
|
||||
|
|
|
|||
|
|
@ -267,13 +267,198 @@ input, textarea {
|
|||
}
|
||||
|
||||
/* Briefing Widget Styles */
|
||||
.briefing-text {
|
||||
white-space: pre-line;
|
||||
line-height: 1.7;
|
||||
.briefing-markdown {
|
||||
font-size: 1.05rem;
|
||||
line-height: 1.7;
|
||||
margin: 8px 0 0 0;
|
||||
}
|
||||
|
||||
.briefing-markdown p {
|
||||
margin: 0 0 0.75em 0;
|
||||
}
|
||||
|
||||
.briefing-markdown p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.briefing-markdown h1,
|
||||
.briefing-markdown h2,
|
||||
.briefing-markdown h3,
|
||||
.briefing-markdown h4 {
|
||||
margin: 1em 0 0.35em 0;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.briefing-markdown h1 { font-size: 1.5rem; }
|
||||
.briefing-markdown h2 { font-size: 1.3rem; }
|
||||
.briefing-markdown h3 { font-size: 1.15rem; }
|
||||
.briefing-markdown h4 { font-size: 1.05rem; }
|
||||
|
||||
.briefing-markdown ul,
|
||||
.briefing-markdown ol {
|
||||
margin: 0.4em 0 0.75em 0;
|
||||
padding-left: 1.4em;
|
||||
}
|
||||
|
||||
.briefing-markdown li {
|
||||
margin-bottom: 0.25em;
|
||||
}
|
||||
|
||||
.briefing-markdown strong {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.briefing-markdown em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.briefing-markdown code {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 0.9em;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
padding: 0.1em 0.3em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.app-light .briefing-markdown code {
|
||||
background-color: rgba(0, 0, 0, 0.07);
|
||||
}
|
||||
|
||||
.briefing-markdown hr {
|
||||
border: none;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.15);
|
||||
margin: 0.75em 0;
|
||||
}
|
||||
|
||||
.app-light .briefing-markdown hr {
|
||||
border-top-color: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
/* Chat Markdown - condensed for the chat bubble context */
|
||||
.chat-markdown {
|
||||
font-size: inherit;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
.chat-markdown p {
|
||||
margin: 0 0 0.4em 0;
|
||||
}
|
||||
|
||||
.chat-markdown p:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.chat-markdown h1,
|
||||
.chat-markdown h2,
|
||||
.chat-markdown h3,
|
||||
.chat-markdown h4 {
|
||||
margin: 0.5em 0 0.2em 0;
|
||||
line-height: 1.2;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.chat-markdown ul,
|
||||
.chat-markdown ol {
|
||||
margin: 0.2em 0 0.4em 0;
|
||||
padding-left: 1.2em;
|
||||
}
|
||||
|
||||
.chat-markdown li {
|
||||
margin-bottom: 0.15em;
|
||||
}
|
||||
|
||||
.chat-markdown li p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.chat-markdown strong {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.chat-markdown em {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.chat-markdown code {
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 0.85em;
|
||||
background-color: rgba(0, 0, 0, 0.2);
|
||||
padding: 0.1em 0.25em;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.chat-markdown pre {
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
border-radius: 4px;
|
||||
padding: 0.5em 0.75em;
|
||||
overflow-x: auto;
|
||||
margin: 0.3em 0 0.4em 0;
|
||||
}
|
||||
|
||||
.chat-markdown pre code {
|
||||
background: none;
|
||||
padding: 0;
|
||||
font-size: 0.82em;
|
||||
}
|
||||
|
||||
.chat-markdown blockquote {
|
||||
border-left: 3px solid rgba(255, 255, 255, 0.35);
|
||||
margin: 0.3em 0;
|
||||
padding: 0 0 0 0.6em;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
.app-light .chat-markdown code {
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.app-light .chat-markdown pre {
|
||||
background-color: rgba(0, 0, 0, 0.07);
|
||||
}
|
||||
|
||||
.app-light .chat-markdown blockquote {
|
||||
border-left-color: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.chat-markdown hr {
|
||||
border: none;
|
||||
border-top: 1px solid rgba(255, 255, 255, 0.25);
|
||||
margin: 0.4em 0;
|
||||
}
|
||||
|
||||
.app-light .chat-markdown hr {
|
||||
border-top-color: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.chat-markdown table {
|
||||
border-collapse: collapse;
|
||||
font-size: 0.85em;
|
||||
margin: 0.3em 0 0.4em 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.chat-markdown th,
|
||||
.chat-markdown td {
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
padding: 0.2em 0.5em;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.chat-markdown th {
|
||||
font-weight: 700;
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.app-light .chat-markdown th,
|
||||
.app-light .chat-markdown td {
|
||||
border-color: rgba(0, 0, 0, 0.15);
|
||||
}
|
||||
|
||||
.app-light .chat-markdown th {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
/* Weather Widget Styles */
|
||||
.weather-error-message {
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { useState, useRef, useEffect } from 'react';
|
||||
import { Box, TextField, IconButton, Paper, CircularProgress } from '@mui/material';
|
||||
import { Send, ExpandLess, ExpandMore } from '@mui/icons-material';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import { sendChatMessage } from '../services/claudeService';
|
||||
|
||||
function ChatInterface({ briefing, sourceData }) {
|
||||
|
|
@ -86,7 +88,15 @@ function ChatInterface({ briefing, sourceData }) {
|
|||
}}
|
||||
>
|
||||
<div className={msg.role === 'user' ? 'chat-message-user' : 'chat-message-assistant'}>
|
||||
{msg.content}
|
||||
{msg.role === 'user' ? (
|
||||
msg.content
|
||||
) : (
|
||||
<div className="chat-markdown">
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
||||
{msg.content}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Box>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { useState, useEffect, useRef } from 'react';
|
||||
import { Skeleton, Box, IconButton, Collapse, FormControlLabel, Switch, ToggleButtonGroup, ToggleButton, Select, MenuItem, FormControl, InputLabel, Typography } from '@mui/material';
|
||||
import { VolumeUp, PlayArrow, Pause, Settings, Stop } from '@mui/icons-material';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
import GenericWidget from './GenericWidget';
|
||||
|
||||
function BriefingWidget({ briefing, sx }) {
|
||||
|
|
@ -319,7 +321,11 @@ function BriefingWidget({ briefing, sx }) {
|
|||
{/* Briefing Content */}
|
||||
<Box sx={{ mt: 1 }}>
|
||||
{briefing ? (
|
||||
<p className="briefing-text">{briefing}</p>
|
||||
<div className="briefing-markdown">
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
||||
{briefing}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<Skeleton variant="text" sx={{ fontSize: '1rem' }} />
|
||||
|
|
|
|||
Loading…
Reference in a new issue