Add 'scrollable' prop to Markdown component for better control over scrolling behavior (#964)

The scrollable prop controls if ScrollbarOverlay is added to the
Markdown component.
This commit is contained in:
Red J Adaya 2024-10-07 04:30:02 +08:00 committed by GitHub
parent f1fe401dbe
commit 28ca193c19
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 59 additions and 9 deletions

View File

@ -7,6 +7,7 @@
overflow: hidden;
height: 100%;
width: 100%;
.content {
height: 100%;
width: 100%;
@ -17,6 +18,10 @@
font-size: 14px;
overflow-wrap: break-word;
&.non-scrollable {
overflow: hidden;
}
.heading {
&:first-of-type {
margin-top: 0 !important;

View File

@ -178,9 +178,19 @@ type MarkdownProps = {
className?: string;
onClickExecute?: (cmd: string) => void;
resolveOpts?: MarkdownResolveOpts;
scrollable?: boolean;
};
const Markdown = ({ text, textAtom, showTocAtom, style, className, resolveOpts, onClickExecute }: MarkdownProps) => {
const Markdown = ({
text,
textAtom,
showTocAtom,
style,
className,
resolveOpts,
scrollable = true,
onClickExecute,
}: MarkdownProps) => {
const textAtomValue = useAtomValueSafe(textAtom);
const tocRef = useRef<TocItem[]>([]);
const showToc = useAtomValueSafe(showTocAtom) ?? false;
@ -240,8 +250,8 @@ const Markdown = ({ text, textAtom, showTocAtom, style, className, resolveOpts,
text = textAtomValue ?? text;
return (
<div className={clsx("markdown", className)} style={style}>
const ScrollableMarkdown = () => {
return (
<OverlayScrollbarsComponent
ref={contentsOsRef}
className="content"
@ -274,6 +284,45 @@ const Markdown = ({ text, textAtom, showTocAtom, style, className, resolveOpts,
{text}
</ReactMarkdown>
</OverlayScrollbarsComponent>
);
};
const NonScrollableMarkdown = () => {
return (
<div className="content non-scrollable">
<ReactMarkdown
remarkPlugins={[remarkGfm, [RemarkFlexibleToc, { tocRef: tocRef.current }]]}
rehypePlugins={[
rehypeRaw,
rehypeHighlight,
() =>
rehypeSanitize({
...defaultSchema,
attributes: {
...defaultSchema.attributes,
span: [
...(defaultSchema.attributes?.span || []),
// Allow all class names starting with `hljs-`.
["className", /^hljs-./],
// Alternatively, to allow only certain class names:
// ['className', 'hljs-number', 'hljs-title', 'hljs-variable']
],
},
tagNames: [...(defaultSchema.tagNames || []), "span"],
}),
() => rehypeSlug({ prefix: idPrefix }),
]}
components={markdownComponents}
>
{text}
</ReactMarkdown>
</div>
);
};
return (
<div className={clsx("markdown", className)} style={style}>
{scrollable ? <ScrollableMarkdown /> : <NonScrollableMarkdown />}
{toc && (
<OverlayScrollbarsComponent className="toc" options={{ scrollbars: { autoHide: "leave" } }}>
<div className="toc-inner">

View File

@ -14,7 +14,6 @@ import { atom, Atom, PrimitiveAtom, useAtomValue, useSetAtom, WritableAtom } fro
import type { OverlayScrollbars } from "overlayscrollbars";
import { OverlayScrollbarsComponent, OverlayScrollbarsComponentRef } from "overlayscrollbars-react";
import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
import tinycolor from "tinycolor2";
import "./waveai.less";
interface ChatMessageType {
@ -263,11 +262,8 @@ function makeWaveAiViewModel(blockId): WaveAiModel {
const ChatItem = ({ chatItem }: ChatItemProps) => {
const { isAssistant, text, isError } = chatItem;
const senderClassName = isAssistant ? "chat-msg-assistant" : "chat-msg-user";
const msgClassName = `chat-msg ${senderClassName}`;
const cssVar = "--panel-bg-color";
const panelBgColor = getComputedStyle(document.documentElement).getPropertyValue(cssVar).trim();
const color = tinycolor(panelBgColor);
const renderError = (err: string): React.JSX.Element => <div className="chat-msg-error">{err}</div>;
@ -284,7 +280,7 @@ const ChatItem = ({ chatItem }: ChatItemProps) => {
</div>
</div>
<div className="chat-msg chat-msg-assistant">
<Markdown text={text} />
<Markdown text={text} scrollable={false} />
</div>
</>
) : (
@ -299,7 +295,7 @@ const ChatItem = ({ chatItem }: ChatItemProps) => {
return (
<>
<div className="chat-msg chat-msg-user">
<Markdown className="msg-text" text={text} />
<Markdown className="msg-text" text={text} scrollable={false} />
</div>
</>
);