diff --git a/src/components/code/__snapshots__/code_block.test.tsx.snap b/src/components/code/__snapshots__/code_block.test.tsx.snap
index e642da216f7..8c1bd5ff1b5 100644
--- a/src/components/code/__snapshots__/code_block.test.tsx.snap
+++ b/src/components/code/__snapshots__/code_block.test.tsx.snap
@@ -85,54 +85,41 @@ exports[`EuiCodeBlock fullscreen displays content in fullscreen mode 1`] = `
-
-
-
+
+
-
+ />
+
+
+
-
`;
@@ -412,74 +399,68 @@ exports[`EuiCodeBlock props isCopyable is rendered 1`] = `
-
-
+
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+ />
+
+
+
+
+
+
-
`;
diff --git a/src/components/code/code_block.tsx b/src/components/code/code_block.tsx
index b8261e255bb..37cffeed115 100644
--- a/src/components/code/code_block.tsx
+++ b/src/components/code/code_block.tsx
@@ -27,7 +27,7 @@ import { EuiButtonIcon } from '../button';
import { keysOf, ExclusiveUnion } from '../common';
import { EuiCopy } from '../copy';
import { EuiFocusTrap } from '../focus_trap';
-import { EuiI18n } from '../i18n';
+import { useEuiI18n } from '../i18n';
import { useInnerText } from '../inner_text';
import { useMutationObserver } from '../observer/mutation_observer';
import { useResizeObserver } from '../observer/resize_observer';
@@ -171,7 +171,7 @@ export const EuiCodeBlock: FunctionComponent = ({
[_isVirtualized, data]
);
- const { innerTextRef, showCopyButton, CopyButton } = useCopy({
+ const { innerTextRef, showCopyButton, textToCopy } = useCopy({
isCopyable,
isVirtualized,
children,
@@ -187,8 +187,8 @@ export const EuiCodeBlock: FunctionComponent = ({
const {
showFullScreenButton,
onKeyDown,
- FullScreenButton,
- FullScreenDisplay,
+ isFullScreen,
+ toggleFullScreen,
} = useFullScreen({ overflowHeight });
// Classes used in both fullscreen and non-fullscreen mode
@@ -232,28 +232,46 @@ export const EuiCodeBlock: FunctionComponent = ({
[preClasses, onKeyDown]
);
- const optionalStyles: CSSProperties = {};
-
- if (overflowHeight) {
- const property =
- typeof overflowHeight === 'string' ? 'height' : 'maxHeight';
- optionalStyles[property] = overflowHeight;
- }
+ const overflowHeightStyles: CSSProperties = useMemo(() => {
+ if (overflowHeight) {
+ const property =
+ typeof overflowHeight === 'string' ? 'height' : 'maxHeight';
+ return {
+ [property]: overflowHeight,
+ };
+ }
+ return {};
+ }, [overflowHeight]);
- const wrapperProps = {
- className: classes,
- style: optionalStyles,
- };
+ const wrapperProps = useMemo(
+ () => ({
+ className: classes,
+ style: overflowHeightStyles,
+ }),
+ [classes, overflowHeightStyles]
+ );
- let codeBlockControls;
- if (showCopyButton || showFullScreenButton) {
- codeBlockControls = (
-
-
-
-
- );
- }
+ const codeBlockControls = useMemo(() => {
+ if (showCopyButton || showFullScreenButton) {
+ return (
+
+ {showFullScreenButton && (
+
+ )}
+ {showCopyButton && }
+
+ );
+ }
+ }, [
+ isFullScreen,
+ toggleFullScreen,
+ showCopyButton,
+ showFullScreenButton,
+ textToCopy,
+ ]);
return (
@@ -268,7 +286,7 @@ export const EuiCodeBlock: FunctionComponent
= ({
) : (
@@ -277,21 +295,23 @@ export const EuiCodeBlock: FunctionComponent = ({
)}
{codeBlockControls}
-
- {isVirtualized ? (
-
- ) : (
-
- {content}
-
- )}
- {codeBlockControls}
-
+ {isFullScreen && (
+
+ {isVirtualized ? (
+
+ ) : (
+
+ {content}
+
+ )}
+ {codeBlockControls}
+
+ )}
);
};
@@ -333,6 +353,26 @@ const useOverflowDetection = () => {
* Copy logic
*/
+const CopyButton: FunctionComponent<{
+ textToCopy: string;
+}> = ({ textToCopy }) => {
+ const copyButton = useEuiI18n('euiCodeBlock.copyButton', 'Copy');
+ return (
+
+
+ {(copy) => (
+
+ )}
+
+
+ );
+};
+
const useCopy = ({
isCopyable,
isVirtualized,
@@ -351,36 +391,53 @@ const useCopy = ({
const showCopyButton = isCopyable && textToCopy;
- const CopyButton = () => {
- if (!showCopyButton) return null;
-
- return (
-
-
- {(copyButton: string) => (
-
- {(copy) => (
-
- )}
-
- )}
-
-
- );
- };
-
- return { innerTextRef, showCopyButton, CopyButton };
+ return { innerTextRef, showCopyButton, textToCopy };
};
/**
* Fullscreen logic
*/
+const FullScreenButton: FunctionComponent<{
+ isFullScreen: boolean;
+ toggleFullScreen: () => void;
+}> = ({ isFullScreen, toggleFullScreen }) => {
+ const [fullscreenCollapse, fullscreenExpand] = useEuiI18n(
+ ['euiCodeBlock.fullscreenCollapse', 'euiCodeBlock.fullscreenExpand'],
+ ['Collapse', 'Expand']
+ );
+ return (
+
+ );
+};
+
+const FullScreenDisplay: FunctionComponent<{
+ className: string;
+}> = ({ children, className }) => {
+ // Force fullscreen to use large font and padding.
+ const fullScreenClasses = classNames(
+ className,
+ 'euiCodeBlock--fontLarge',
+ 'euiCodeBlock--paddingLarge',
+ 'euiCodeBlock-isFullScreen'
+ );
+
+ // Attaches to the body because of EuiOverlayMask's React portal usage.
+ return (
+
+
+ {children}
+
+
+ );
+};
+
const useFullScreen = ({
overflowHeight,
}: {
@@ -388,9 +445,9 @@ const useFullScreen = ({
}) => {
const [isFullScreen, setIsFullScreen] = useState(false);
- const toggleFullScreen = () => {
- setIsFullScreen(!isFullScreen);
- };
+ const toggleFullScreen = useCallback(() => {
+ setIsFullScreen((isFullScreen) => !isFullScreen);
+ }, []);
const onKeyDown = useCallback((event: KeyboardEvent) => {
if (event.key === keys.ESCAPE) {
@@ -402,57 +459,10 @@ const useFullScreen = ({
const showFullScreenButton = !!overflowHeight;
- const FullScreenButton: React.FC = () => {
- if (!showFullScreenButton) return null;
- return (
-
- {([fullscreenCollapse, fullscreenExpand]: string[]) => (
-
- )}
-
- );
- };
-
- const FullScreenDisplay: React.FC<{ className: string }> = ({
- children,
- className,
- }) => {
- if (!isFullScreen) return null;
-
- // Force fullscreen to use large font and padding.
- const fullScreenClasses = classNames(
- className,
- 'euiCodeBlock--fontLarge',
- 'euiCodeBlock--paddingLarge',
- 'euiCodeBlock-isFullScreen'
- );
-
- // Attaches to the body because of EuiOverlayMask's React portal usage.
- return (
-
-
- {children}
-
-
- );
- };
-
return {
showFullScreenButton,
- FullScreenButton,
- FullScreenDisplay,
+ isFullScreen,
+ toggleFullScreen,
onKeyDown,
};
};
diff --git a/upcoming_changelogs/6077.md b/upcoming_changelogs/6077.md
new file mode 100644
index 00000000000..9f6b78681df
--- /dev/null
+++ b/upcoming_changelogs/6077.md
@@ -0,0 +1,4 @@
+**Bug fixes**
+
+- Fixed unintentional subcomponent remounting in `EuiCodeBlock` during rerenders
+