openhands / src /components /features /markdown /markdown-table-scroll.tsx
SaylorTwift's picture
SaylorTwift HF Staff
Add files using upload-large-folder tool
9b906ea verified
Raw
History Blame Contribute Delete
2.89 kB
import React from "react";
import { cn } from "#/utils/utils";
import {
readScrollFadeState,
type ScrollFadeState,
} from "#/utils/scroll-fade-state";
export { readScrollFadeState };
const FADE_WIDTH_CLASS = "w-10";
interface MarkdownTableScrollProps {
children: React.ReactNode;
}
export function MarkdownTableScroll({ children }: MarkdownTableScrollProps) {
const scrollRef = React.useRef<HTMLDivElement>(null);
const [fadeState, setFadeState] = React.useState<ScrollFadeState>({
left: false,
right: false,
});
const updateFadeState = React.useCallback(() => {
const element = scrollRef.current;
if (!element) {
return;
}
setFadeState(readScrollFadeState(element));
}, []);
React.useLayoutEffect(() => {
updateFadeState();
const element = scrollRef.current;
if (!element) {
return undefined;
}
const resizeObserver = new ResizeObserver(updateFadeState);
resizeObserver.observe(element);
const table = element.firstElementChild;
if (table) {
resizeObserver.observe(table);
}
return () => resizeObserver.disconnect();
}, [updateFadeState, children]);
return (
<div className="relative max-w-full">
<div
ref={scrollRef}
data-testid="markdown-table-scroll"
onScroll={updateFadeState}
className="max-w-full overflow-x-auto custom-scrollbar-always"
>
{children}
</div>
{/* The fades blend into whatever surface the table sits on, which differs
between the chat stream and cards like the markdown artifact preview.
Set `--oh-scroll-fade-from` on any ancestor to match another surface.
The value is inlined at both edges because Tailwind only extracts
classes from literal strings, not interpolated constants. */}
<div
aria-hidden
data-testid="markdown-table-scroll-fade-left"
data-visible={fadeState.left ? "true" : "false"}
className={cn(
"pointer-events-none absolute inset-y-0 left-0 z-10",
FADE_WIDTH_CLASS,
"bg-gradient-to-r from-[var(--oh-scroll-fade-from,var(--oh-color-base))] to-transparent",
"transition-opacity duration-300 ease-out motion-reduce:transition-none",
fadeState.left ? "opacity-100" : "opacity-0",
)}
/>
<div
aria-hidden
data-testid="markdown-table-scroll-fade-right"
data-visible={fadeState.right ? "true" : "false"}
className={cn(
"pointer-events-none absolute inset-y-0 right-0 z-10",
FADE_WIDTH_CLASS,
"bg-gradient-to-l from-[var(--oh-scroll-fade-from,var(--oh-color-base))] to-transparent",
"transition-opacity duration-300 ease-out motion-reduce:transition-none",
fadeState.right ? "opacity-100" : "opacity-0",
)}
/>
</div>
);
}