authorgravatar for maria@kuuro.netmaria <maria@kuuro.net> 2026-10-14 23:10:05+00:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-14 23:10:05+00:00
log5a4e9980533705774dc3f45b35cacf76c3d78dbc
tree1d8f661505aa514eb2cd52019e649232dc32e34a
parent7bdfed98d733d1bcda99f43d43b24cd6913f2fce
signature Signed by PGP key B5690EEEBB952194

fix(web): mermaid code toggle stays in place when switching views (#19601)


1 files changed, 12 insertions(+), 9 deletions(-)

apps/web/src/components/ChatMarkdown.tsx+12-9
...@@ -849,7 +849,7 @@ function MarkdownCodeBlock({...@@ -849,7 +849,7 @@ function MarkdownCodeBlock({
849 theme,849 theme,
850 onRunShellCommand,850 onRunShellCommand,
851 isStreaming,851 isStreaming,
852 leadingActions,852 viewToggle,
853 canWrap = true,853 canWrap = true,
854 diagram = false,854 diagram = false,
855 children,855 children,
...@@ -860,9 +860,10 @@ function MarkdownCodeBlock({...@@ -860,9 +860,10 @@ function MarkdownCodeBlock({
860 theme: "light" | "dark";860 theme: "light" | "dark";
861 onRunShellCommand?: ((command: string) => void) | undefined;861 onRunShellCommand?: ((command: string) => void) | undefined;
862 isStreaming: boolean;862 isStreaming: boolean;
863 leadingActions?: ReactNode;863 /** Switches between source and rendered content; sits left of copy in both views. */
864 viewToggle?: ReactNode;
864 canWrap?: boolean;865 canWrap?: boolean;
865 /** Renders content instead of code, with actions below it like tables. */866 /** Renders content frameless, with the code header's actions above it. */
866 diagram?: boolean;867 diagram?: boolean;
867 children: ReactNode;868 children: ReactNode;
868}) {869}) {
...@@ -942,12 +943,14 @@ function MarkdownCodeBlock({...@@ -942,12 +943,14 @@ function MarkdownCodeBlock({
942943
943 if (diagram) {944 if (diagram) {
944 return (945 return (
945 <div className="my-[0.65rem]" data-language={language}>946 // The transparent border and header padding match the code frame, so the
946 {children}947 // actions stay in place when switching views.
947 <div className="mt-0.5 flex items-center justify-between select-none">948 <div className="my-[0.65rem] border border-transparent" data-language={language}>
948 {leadingActions}949 <div className="flex items-center justify-end gap-0.5 pt-1.5 pr-1.5 select-none">
950 {viewToggle}
949 {copyButton}951 {copyButton}
950 </div>952 </div>
953 {children}
951 </div>954 </div>
952 );955 );
953 }956 }
...@@ -962,7 +965,6 @@ function MarkdownCodeBlock({...@@ -962,7 +965,6 @@ function MarkdownCodeBlock({
962 headerProps={THREAD_FIND_IGNORE_PROPS}965 headerProps={THREAD_FIND_IGNORE_PROPS}
963 actions={966 actions={
964 <span className="flex items-center gap-0.5" role="toolbar" aria-label="Code block actions">967 <span className="flex items-center gap-0.5" role="toolbar" aria-label="Code block actions">
965 {leadingActions}
966 {canWrap ? (968 {canWrap ? (
967 <Tooltip>969 <Tooltip>
968 <TooltipTrigger970 <TooltipTrigger
...@@ -1000,6 +1002,7 @@ function MarkdownCodeBlock({...@@ -1000,6 +1002,7 @@ function MarkdownCodeBlock({
1000 <TooltipPopup side="top">Run in terminal</TooltipPopup>1002 <TooltipPopup side="top">Run in terminal</TooltipPopup>
1001 </Tooltip>1003 </Tooltip>
1002 ) : null}1004 ) : null}
1005 {viewToggle}
1003 {copyButton}1006 {copyButton}
1004 </span>1007 </span>
1005 }1008 }
...@@ -1043,7 +1046,7 @@ function MarkdownMermaidCodeBlock({...@@ -1043,7 +1046,7 @@ function MarkdownMermaidCodeBlock({
1043 isStreaming={isStreaming}1046 isStreaming={isStreaming}
1044 canWrap={!showDiagram}1047 canWrap={!showDiagram}
1045 diagram={showDiagram}1048 diagram={showDiagram}
1046 leadingActions={1049 viewToggle={
1047 isStreaming ? null : (1050 isStreaming ? null : (
1048 <Tooltip>1051 <Tooltip>
1049 <TooltipTrigger1052 <TooltipTrigger