Skip to content

Commit

Permalink
Merge pull request #294 from Chainlit/at/CHA-229
Browse files Browse the repository at this point in the history
refactor: Collapse long message
  • Loading branch information
alimtunc authored Aug 22, 2023
2 parents a37a8bd + 9340bbc commit 49182f1
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 39 deletions.
52 changes: 52 additions & 0 deletions src/chainlit/frontend/src/components/atoms/Collapse.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React from 'react';
import { useToggle } from 'usehooks-ts';

import { DownloadRounded, ExpandLess, ExpandMore } from '@mui/icons-material';
import {
Box,
IconButton,
Collapse as MCollapse,
Stack,
Theme
} from '@mui/material';

interface CollapseProps {
children: React.ReactNode;
onDownload: () => void;
}

const Collapse = ({ children, onDownload }: CollapseProps): JSX.Element => {
const [expandAll, toggleExpandAll] = useToggle(false);

return (
<Box>
<MCollapse
sx={{
border: (theme: Theme) => `3px solid ${theme.palette.divider}`,
borderRadius: 1,
padding: 1
}}
in={expandAll}
collapsedSize={30}
>
{children}
</MCollapse>
<Stack
sx={{
position: 'absolute',
right: 0
}}
direction="row"
>
<IconButton onClick={toggleExpandAll}>
{expandAll ? <ExpandLess /> : <ExpandMore />}
</IconButton>
<IconButton onClick={onDownload}>
<DownloadRounded />
</IconButton>
</Stack>
</Box>
);
};

export default Collapse;
Original file line number Diff line number Diff line change
@@ -1,16 +1,20 @@
import { exportToFile } from 'helpers/export';
import { memo } from 'react';
import { ReactMarkdown } from 'react-markdown/lib/react-markdown';
import remarkGfm from 'remark-gfm';

import { Link, Stack, Typography } from '@mui/material';

import Code from 'components/atoms/Code';
import Collapse from 'components/atoms/Collapse';
import ElementRef from 'components/atoms/element/ref';

import { IMessageElement } from 'state/element';

import InlinedElements from './inlined';

const COLLAPSE_MIN_LENGTH = 300;

interface Props {
id?: string;
content?: string;
Expand Down Expand Up @@ -110,47 +114,57 @@ export default memo(function MessageContent({

if (!preparedContent) return null;

return (
<Stack width="100%">
<Stack direction="row">
<Typography
sx={{
width: '100%',
minHeight: '20px',
fontSize: '1rem',
lineHeight: '1.5rem',
fontFamily: 'Inter',
fontWeight: authorIsUser ? 500 : 300
const renderContent = () => (
<Stack direction="row">
<Typography
sx={{
width: '100%',
minHeight: '20px',
fontSize: '1rem',
lineHeight: '1.5rem',
fontFamily: 'Inter',
fontWeight: authorIsUser ? 500 : 300
}}
component="div"
>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
className="markdown-body"
components={{
a({ children, ...props }) {
const name = children[0] as string;
const element = refElements.find((e) => e.name === name);

if (element) {
return <ElementRef element={element} />;
} else {
return (
<Link {...props} target="_blank">
{children}
</Link>
);
}
},
code({ ...props }) {
return <Code {...props} />;
}
}}
component="div"
>
<ReactMarkdown
remarkPlugins={[remarkGfm]}
className="markdown-body"
components={{
a({ children, ...props }) {
const name = children[0] as string;
const element = refElements.find((e) => e.name === name);

if (element) {
return <ElementRef element={element} />;
} else {
return (
<Link {...props} target="_blank">
{children}
</Link>
);
}
},
code({ ...props }) {
return <Code {...props} />;
}
}}
>
{preparedContent}
</ReactMarkdown>
</Typography>
</Stack>
{preparedContent}
</ReactMarkdown>
</Typography>
</Stack>
);

return (
<Stack width="100%">
{preparedContent.length > COLLAPSE_MIN_LENGTH ? (
<Collapse onDownload={() => exportToFile(preparedContent, `${id}.txt`)}>
{renderContent()}
</Collapse>
) : (
renderContent()
)}
<InlinedElements elements={inlinedElements} />
</Stack>
);
Expand Down
11 changes: 11 additions & 0 deletions src/chainlit/frontend/src/helpers/export.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function exportToFile(data: string, filename: string) {
const blob = new Blob([data], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const link = document.createElement('a');

link.setAttribute('href', url);
link.setAttribute('download', filename);
link.click();

URL.revokeObjectURL(url);
}

0 comments on commit 49182f1

Please sign in to comment.