🎨 refactor: Improve Mermaid Artifacts Styling (#9742)

* 🎨 refactor: Improve Mermaid Artifacts Styling

* refactor: Replace ArtifactMarkdown with MermaidMarkdown
This commit is contained in:
Danny Avila 2025-09-20 08:19:44 -04:00 committed by GitHub
parent fcaf55143d
commit 0352067da2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 49 additions and 20 deletions

View file

@ -4,7 +4,7 @@ import {
SandpackProvider, SandpackProvider,
SandpackProviderProps, SandpackProviderProps,
} from '@codesandbox/sandpack-react/unstyled'; } from '@codesandbox/sandpack-react/unstyled';
import type { SandpackPreviewRef } from '@codesandbox/sandpack-react/unstyled'; import type { SandpackPreviewRef, PreviewProps } from '@codesandbox/sandpack-react/unstyled';
import type { TStartupConfig } from 'librechat-data-provider'; import type { TStartupConfig } from 'librechat-data-provider';
import type { ArtifactFiles } from '~/common'; import type { ArtifactFiles } from '~/common';
import { sharedFiles, sharedOptions } from '~/utils/artifacts'; import { sharedFiles, sharedOptions } from '~/utils/artifacts';
@ -13,6 +13,7 @@ export const ArtifactPreview = memo(function ({
files, files,
fileKey, fileKey,
template, template,
isMermaid,
sharedProps, sharedProps,
previewRef, previewRef,
currentCode, currentCode,
@ -20,6 +21,7 @@ export const ArtifactPreview = memo(function ({
}: { }: {
files: ArtifactFiles; files: ArtifactFiles;
fileKey: string; fileKey: string;
isMermaid: boolean;
template: SandpackProviderProps['template']; template: SandpackProviderProps['template'];
sharedProps: Partial<SandpackProviderProps>; sharedProps: Partial<SandpackProviderProps>;
previewRef: React.MutableRefObject<SandpackPreviewRef>; previewRef: React.MutableRefObject<SandpackPreviewRef>;
@ -54,6 +56,15 @@ export const ArtifactPreview = memo(function ({
return _options; return _options;
}, [startupConfig, template]); }, [startupConfig, template]);
const style: PreviewProps['style'] | undefined = useMemo(() => {
if (isMermaid) {
return {
backgroundColor: '#282C34',
};
}
return;
}, [isMermaid]);
if (Object.keys(artifactFiles).length === 0) { if (Object.keys(artifactFiles).length === 0) {
return null; return null;
} }
@ -73,6 +84,7 @@ export const ArtifactPreview = memo(function ({
showRefreshButton={false} showRefreshButton={false}
tabIndex={0} tabIndex={0}
ref={previewRef} ref={previewRef}
style={style}
/> />
</SandpackProvider> </SandpackProvider>
); );

View file

@ -8,6 +8,7 @@ import { useAutoScroll } from '~/hooks/Artifacts/useAutoScroll';
import { ArtifactCodeEditor } from './ArtifactCodeEditor'; import { ArtifactCodeEditor } from './ArtifactCodeEditor';
import { useGetStartupConfig } from '~/data-provider'; import { useGetStartupConfig } from '~/data-provider';
import { ArtifactPreview } from './ArtifactPreview'; import { ArtifactPreview } from './ArtifactPreview';
import { MermaidMarkdown } from './MermaidMarkdown';
import { cn } from '~/utils'; import { cn } from '~/utils';
export default function ArtifactTabs({ export default function ArtifactTabs({
@ -44,23 +45,25 @@ export default function ArtifactTabs({
id="artifacts-code" id="artifacts-code"
className={cn('flex-grow overflow-auto')} className={cn('flex-grow overflow-auto')}
> >
<ArtifactCodeEditor {isMermaid ? (
files={files} <MermaidMarkdown content={content} isSubmitting={isSubmitting} />
fileKey={fileKey} ) : (
template={template} <ArtifactCodeEditor
artifact={artifact} files={files}
editorRef={editorRef} fileKey={fileKey}
sharedProps={sharedProps} template={template}
/> artifact={artifact}
editorRef={editorRef}
sharedProps={sharedProps}
/>
)}
</Tabs.Content> </Tabs.Content>
<Tabs.Content <Tabs.Content value="preview" className="flex-grow overflow-auto">
value="preview"
className={cn('flex-grow overflow-auto', isMermaid ? 'bg-[#282C34]' : 'bg-white')}
>
<ArtifactPreview <ArtifactPreview
files={files} files={files}
fileKey={fileKey} fileKey={fileKey}
template={template} template={template}
isMermaid={isMermaid}
previewRef={previewRef} previewRef={previewRef}
sharedProps={sharedProps} sharedProps={sharedProps}
currentCode={currentCode} currentCode={currentCode}

View file

@ -9,6 +9,7 @@ import { useEditorContext } from '~/Providers';
import ArtifactTabs from './ArtifactTabs'; import ArtifactTabs from './ArtifactTabs';
import { CopyCodeButton } from './Code'; import { CopyCodeButton } from './Code';
import { useLocalize } from '~/hooks'; import { useLocalize } from '~/hooks';
import { cn } from '~/utils';
import store from '~/store'; import store from '~/store';
export default function Artifacts() { export default function Artifacts() {
@ -58,9 +59,10 @@ export default function Artifacts() {
<div className="flex h-full w-full items-center justify-center"> <div className="flex h-full w-full items-center justify-center">
{/* Main Container */} {/* Main Container */}
<div <div
className={`flex h-full w-full flex-col overflow-hidden border border-border-medium bg-surface-primary text-xl text-text-primary shadow-xl transition-all duration-500 ease-in-out ${ className={cn(
isVisible ? 'scale-100 opacity-100 blur-0' : 'scale-105 opacity-0 blur-sm' `flex h-full w-full flex-col overflow-hidden border border-border-medium bg-surface-primary text-xl text-text-primary shadow-xl transition-all duration-500 ease-in-out`,
}`} isVisible ? 'scale-100 opacity-100 blur-0' : 'scale-105 opacity-0 blur-sm',
)}
> >
{/* Header */} {/* Header */}
<div className="flex items-center justify-between border-b border-border-medium bg-surface-primary-alt p-2"> <div className="flex items-center justify-between border-b border-border-medium bg-surface-primary-alt p-2">
@ -74,16 +76,17 @@ export default function Artifacts() {
{/* Refresh button */} {/* Refresh button */}
{activeTab === 'preview' && ( {activeTab === 'preview' && (
<button <button
className={`mr-2 text-text-secondary transition-transform duration-500 ease-in-out ${ className={cn(
isRefreshing ? 'rotate-180' : '' 'mr-2 text-text-secondary transition-transform duration-500 ease-in-out',
}`} isRefreshing ? 'rotate-180' : '',
)}
onClick={handleRefresh} onClick={handleRefresh}
disabled={isRefreshing} disabled={isRefreshing}
aria-label="Refresh" aria-label="Refresh"
> >
<RefreshCw <RefreshCw
size={16} size={16}
className={`transform ${isRefreshing ? 'animate-spin' : ''}`} className={cn('transform', isRefreshing ? 'animate-spin' : '')}
/> />
</button> </button>
)} )}

View file

@ -0,0 +1,11 @@
import { CodeMarkdown } from './Code';
export function MermaidMarkdown({
content,
isSubmitting,
}: {
content: string;
isSubmitting: boolean;
}) {
return <CodeMarkdown content={`\`\`\`mermaid\n${content}\`\`\``} isSubmitting={isSubmitting} />;
}