|
1 | 1 | import type { MermaidConfig } from "mermaid"; |
2 | 2 | import { type ComponentProps, useContext, useEffect, useState } from "react"; |
| 3 | +import { createPortal } from "react-dom"; |
3 | 4 | import { StreamdownContext } from "../../index"; |
4 | 5 | import { Maximize2Icon, XIcon } from "../icons"; |
5 | 6 | import { cn } from "../utils"; |
@@ -102,44 +103,47 @@ export const MermaidFullscreenButton = ({ |
102 | 103 | <Maximize2Icon size={14} /> |
103 | 104 | </button> |
104 | 105 |
|
105 | | - {isFullscreen ? ( |
106 | | - // biome-ignore lint/a11y/useSemanticElements: "div is used as a backdrop overlay, not a button" |
107 | | - <div |
108 | | - className="fixed inset-0 z-50 flex items-center justify-center bg-background/95 backdrop-blur-sm" |
109 | | - onClick={handleToggle} |
110 | | - onKeyDown={(e) => { |
111 | | - if (e.key === "Escape") { |
112 | | - handleToggle(); |
113 | | - } |
114 | | - }} |
115 | | - role="button" |
116 | | - tabIndex={0} |
117 | | - > |
118 | | - <button |
119 | | - className="absolute top-4 right-4 z-10 rounded-md p-2 text-muted-foreground transition-all hover:bg-muted hover:text-foreground" |
120 | | - onClick={handleToggle} |
121 | | - title="Exit fullscreen" |
122 | | - type="button" |
123 | | - > |
124 | | - <XIcon size={20} /> |
125 | | - </button> |
126 | | - {/* biome-ignore lint/a11y/noStaticElementInteractions: "div with role=presentation is used for event propagation control" */} |
127 | | - <div |
128 | | - className="flex size-full items-center justify-center p-4" |
129 | | - onClick={(e) => e.stopPropagation()} |
130 | | - onKeyDown={(e) => e.stopPropagation()} |
131 | | - role="presentation" |
132 | | - > |
133 | | - <Mermaid |
134 | | - chart={chart} |
135 | | - className="size-full [&_svg]:h-auto [&_svg]:w-auto" |
136 | | - config={config} |
137 | | - fullscreen={true} |
138 | | - showControls={showPanZoomControls} |
139 | | - /> |
140 | | - </div> |
141 | | - </div> |
142 | | - ) : null} |
| 106 | + {isFullscreen |
| 107 | + ? createPortal( |
| 108 | + // biome-ignore lint/a11y/useSemanticElements: "div is used as a backdrop overlay, not a button" |
| 109 | + <div |
| 110 | + className="fixed inset-0 z-50 flex items-center justify-center bg-background/95 backdrop-blur-sm" |
| 111 | + onClick={handleToggle} |
| 112 | + onKeyDown={(e) => { |
| 113 | + if (e.key === "Escape") { |
| 114 | + handleToggle(); |
| 115 | + } |
| 116 | + }} |
| 117 | + role="button" |
| 118 | + tabIndex={0} |
| 119 | + > |
| 120 | + <button |
| 121 | + className="absolute top-4 right-4 z-10 rounded-md p-2 text-muted-foreground transition-all hover:bg-muted hover:text-foreground" |
| 122 | + onClick={handleToggle} |
| 123 | + title="Exit fullscreen" |
| 124 | + type="button" |
| 125 | + > |
| 126 | + <XIcon size={20} /> |
| 127 | + </button> |
| 128 | + {/* biome-ignore lint/a11y/noStaticElementInteractions: "div with role=presentation is used for event propagation control" */} |
| 129 | + <div |
| 130 | + className="flex size-full items-center justify-center p-4" |
| 131 | + onClick={(e) => e.stopPropagation()} |
| 132 | + onKeyDown={(e) => e.stopPropagation()} |
| 133 | + role="presentation" |
| 134 | + > |
| 135 | + <Mermaid |
| 136 | + chart={chart} |
| 137 | + className="size-full [&_svg]:h-auto [&_svg]:w-auto" |
| 138 | + config={config} |
| 139 | + fullscreen={true} |
| 140 | + showControls={showPanZoomControls} |
| 141 | + /> |
| 142 | + </div> |
| 143 | + </div>, |
| 144 | + document.body |
| 145 | + ) |
| 146 | + : null} |
143 | 147 | </> |
144 | 148 | ); |
145 | 149 | }; |
0 commit comments